--- loncom/interface/londocs.pm 2012/12/13 02:27:27 1.484.2.13 +++ loncom/interface/londocs.pm 2012/05/15 01:41:27 1.487 @@ -1,7 +1,7 @@ # The LearningOnline Network # Documents # -# $Id: londocs.pm,v 1.484.2.13 2012/12/13 02:27:27 raeburn Exp $ +# $Id: londocs.pm,v 1.487 2012/05/15 01:41:27 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -40,9 +40,7 @@ use Apache::lonxml; use Apache::lonclonecourse; use Apache::lonnavmaps; use Apache::lonnavdisplay(); -use Apache::lonuserstate(); use HTML::Entities; -use HTML::TokeParser; use GDBM_File; use Apache::lonlocal; use Cwd; @@ -69,14 +67,10 @@ sub mapread { } sub storemap { - my ($coursenum,$coursedom,$map,$contentchg)=@_; - my $report; - if (($contentchg) && ($map =~ /^default/)) { - $report = 1; - } + my ($coursenum,$coursedom,$map)=@_; my ($outtext,$errtext)= &LONCAPA::map::storemap('/uploaded/'.$coursedom.'/'.$coursenum.'/'. - $map,1,$report); + $map,1); if ($errtext) { return ($errtext,2); } $hadchanges=1; @@ -309,7 +303,7 @@ sub group_import { join(':', ($name, $url, $ext, 'normal', 'res')); } } - return &storemap($coursenum, $coursedom, $folder.'.'.$container,1); + return &storemap($coursenum, $coursedom, $folder.'.'.$container); } sub breadcrumbs { @@ -322,6 +316,7 @@ sub breadcrumbs { @folders=split('&',$env{'form.folderpath'}); } my $folderpath; + my $cpinfo=''; my $plain=''; my $randompick=-1; my $isencrypted=0; @@ -354,7 +349,7 @@ sub breadcrumbs { $name = &mt('Supplemental '.$crstype.' Content'); } &Apache::lonhtmlcommon::add_breadcrumb( - {'href'=>$url, + {'href'=>$url.$cpinfo, 'title'=>$name, 'text'=>$name, 'no_mt'=>1, @@ -368,7 +363,7 @@ sub breadcrumbs { } sub log_docs { - return &Apache::lonnet::write_log('course','docslog',@_); + return &Apache::lonnet::instructor_log('docslog',@_); } { @@ -441,7 +436,7 @@ sub docs_change_log { ''."\n"; $r->print(&Apache::loncommon::start_page('Content Change Log',$js)); $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content Change Log')); - $r->print(&startContentScreen(($supplementalflag?'suppdocs':'docs'))); + $r->print(&startContentScreen('docs')); my %orderhash; my $container='sequence'; my $pathitem; @@ -460,9 +455,6 @@ sub docs_change_log { my $jumpto = $readfile; $jumpto =~ s{^/}{}; my $tid = 1; - if ($supplementalflag) { - $tid = 2; - } my ($breadcrumbtrail) = &breadcrumbs($allowed,$crstype); $r->print($breadcrumbtrail. &generate_edit_table($tid,\%orderhash,undef,$iconpath,$jumpto, @@ -537,30 +529,18 @@ sub docs_change_log { ':'.$docslog{$id}{'exe_udom'}.''. $send_msg_link.''. $docslog{$id}{'logentry'}{'folder'}.''); - my $is_supp = 0; - if ($docslog{$id}{'logentry'}{'currentfolder'} =~ /^supplemental/) { - $is_supp = 1; - } # Before for (my $idx=0;$idx<=$docslog{$id}{'logentry'}{'maxidx'};$idx++) { my $oldname=(split(/\:/,$docslog{$id}{'logentry'}{'before_resources_'.$idx}))[0]; my $newname=(split(/\:/,$docslog{$id}{'logentry'}{'after_resources_'.$idx}))[0]; if ($oldname ne $newname) { - my $shown = &LONCAPA::map::qtescape($oldname); - if ($is_supp) { - $shown = &Apache::loncommon::parse_supplemental_title($shown); - } - $r->print($shown); + $r->print(&LONCAPA::map::qtescape($oldname)); } } $r->print(''); @@ -571,21 +551,13 @@ sub docs_change_log { my $oldname=(split(/\:/,$docslog{$id}{'logentry'}{'before_resources_'.$idx}))[0]; my $newname=(split(/\:/,$docslog{$id}{'logentry'}{'after_resources_'.$idx}))[0]; if ($oldname ne '' && $oldname ne $newname) { - my $shown = &LONCAPA::map::qtescape($newname); - if ($is_supp) { - $shown = &Apache::loncommon::parse_supplemental_title(&LONCAPA::map::qtescape($newname)); - } - $r->print($shown); + $r->print(&LONCAPA::map::qtescape($newname)); } } $r->print(''); @@ -615,7 +587,7 @@ sub docs_change_log { } sub update_paste_buffer { - my ($coursenum,$coursedom,$folder) = @_; + my ($coursenum,$coursedom) = @_; return if (!defined($env{'form.markcopy'})); return if (!defined($env{'form.copyfolder'})); @@ -630,128 +602,35 @@ sub update_paste_buffer { my ($title,$url)=split(':',$LONCAPA::map::resources[$LONCAPA::map::order[$env{'form.markcopy'}]]); if (&is_supplemental_title($title)) { &Apache::lonnet::appenv({'docs.markedcopy_supplemental' => $title}); - ($title) = &Apache::loncommon::parse_supplemental_title($title); + ($title) = &parse_supplemental_title($title); } elsif ($env{'docs.markedcopy_supplemental'}) { &Apache::lonnet::delenv('docs.markedcopy_supplemental'); } $url=~s{http(:|:)//https(:|:)//}{https$2//}; - (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); + &Apache::lonnet::appenv({'docs.markedcopy_title' => $title, + 'docs.markedcopy_url' => $url}); 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,$coursedom,$coursenum) = @_; + my ($r,$container) = @_; return if (!defined($env{'docs.markedcopy_url'})); - 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,$nopaste,$othercrs,$areachange,$is_uploaded_map); - if ($folder =~ /^supplemental/) { - $canpaste = &supp_pasteable($env{'docs.markedcopy_url'}); - unless ($canpaste) { - $nopaste = &mt('Paste into Supplemental Content unavailable for this type of content.'); - } - } else { - $canpaste = 1; - } - - if ($canpaste) { - 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').''); - my ($type,$buffer); - if ($is_external) { + .''.&mt('Clipboard').'' + .'
' + .' ' + ); + + my $type; + if ($env{'docs.markedcopy_url'} =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//} ) { $type = &mt('External Resource'); - $buffer = $type.': '. + $r->print($type.': '. &LONCAPA::map::qtescape($env{'docs.markedcopy_title'}).' ('. - &LONCAPA::map::qtescape($env{'docs.markedcopy_url'}).')'; + &LONCAPA::map::qtescape($env{'docs.markedcopy_url'}).')'); } else { + my $extension = (split(/\./,$env{'docs.markedcopy_url'}))[-1]; my $icon = &Apache::loncommon::icon($extension); if ($extension eq 'sequence' && $env{'docs.markedcopy_url'} =~ m{/default_\d+\.sequence$ }x) { @@ -759,449 +638,116 @@ sub print_paste_buffer { $icon .= '/navmap.folder.closed.gif'; } $icon = ''; - $buffer = $icon.$type.': '. &Apache::loncommon::parse_supplemental_title(&LONCAPA::map::qtescape($env{'docs.markedcopy_title'})); + $r->print($icon.$type.': '. &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(' + if ($container eq 'page') { + $r->print(' '); - } else { - $r->print(' + } else { + $r->print(' '); - } - $r->print('
'); - } else { - $r->print(&mt('Paste buffer contains:').' '.$buffer. - '

'.$nopaste.'

'); } - $r->print('
'); + $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)(?::|:))//}) || - (($url =~ /\.sequence$/) && ($url =~ m{^/uploaded/})) || - ($url =~ m{^/uploaded/$match_domain/$match_courseid/(docs|supplemental)/(default|\d+)/\d+/}) || - ($url =~ m{^/adm/$match_domain/$match_username/aboutme}) || - ($url =~ m{^/public/$match_domain/$match_courseid/syllabus})) { - return 1; - } - 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,$container,$errors) = @_; + my ($coursenum,$coursedom,$folder) = @_; -# Early out if paste buffer is empty if (!$env{'form.pastemarked'}) { - return (); - } - -# 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')); - } + return; } -# Prepare to paste resource at end of list +# paste resource to 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,%tomove); - if ($url=~/\.(page|sequence)$/) { - $is_map = 1; - } - if ($url =~ m{^/uploaded/($match_domain)/($match_courseid)/([^/]+)}) { - $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.')); +# Maps need to be copied first + if (($url=~/\.(page|sequence)$/) && ($url=~/^\/uploaded\//)) { + $title=&mt('Copy of').' '.$title; + my $newid=$$.int(rand(100)).time; + my ($oldid,$ext) = ($url=~/^(.+)\.(\w+)$/); + if ($oldid =~ m{^(/uploaded/\Q$coursedom\E/\Q$coursenum\E/)(\D+)(\d+)$}) { + my $path = $1; + my $prefix = $2; + my $ancestor = $3; + if (length($ancestor) > 10) { + $ancestor = substr($ancestor,-10,10); } + $oldid = $path.$prefix.$ancestor; } -# 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', - doc => 'docs'); - %after = ( map => 'supplemental', - doc => 'supplemental' ); - } elsif (($folder =~ /^default/) && ($oldprefix =~ /^supplemental/)) { - $prefixchg = 1; - %before = ( map => 'supplemental', - doc => 'supplemental'); - %after = ( map => 'default', - doc => 'docs'); - } - -# 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; - } - } + my $counter = 0; + my $newurl=$oldid.$newid.'.'.$ext; + my $is_unique = &uniqueness_check($newurl); + while (!$is_unique && $counter < 100) { + $counter ++; + $newid ++; + $newurl = $oldid.$newid; + $is_unique = &uniqueness_check($newurl); } - } - -# Maps need to be copied first - my ($oldurl,%removefrommap,%removeparam,%addedmaps,%rewrites,%retitles,%copies, - %dbcopies,%zombies,%params,%docmoves,%mapmoves,%newsubdir,%newurls); - $oldurl = $url; - if ($is_map) { - if ($folder =~ /^default/) { - 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 (!$is_unique) { + 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'); } } -# 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)) { - $allmaps{$res->src()} = 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'); } } - &contained_map_check($url,$folder,\%removefrommap,\%removeparam, - \%addedmaps,\%hierarchy,\%titles,\%allmaps); - if ($url=~ m{^/uploaded/}) { - 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; - } - } - } - 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); - } - } elsif ($url=~m {^/res/}) { + $url = $newurl; + } # published maps can only exists once, so remove it from paste buffer when done - &Apache::lonnet::delenv('docs.markedcopy'); -# 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.')); - } - } - } + if (($url=~/\.(page|sequence)$/) && ($url=~m {^/res/})) { + &Apache::lonnet::delenv('docs.markedcopy'); } if ($url=~ m{/smppg$}) { - my $db_name = &Apache::lonsimplepage::get_db_name($url); - if ($db_name =~ /^smppage_/) { - #simple pages, need to copy the db contents to a new one. - my %contents=&Apache::lonnet::dump($db_name,$coursedom,$coursenum); - my $now = time(); - $db_name =~ s{_\d*$ }{_$now}x; - my $dbresult=&Apache::lonnet::put($db_name,\%contents, - $coursedom,$coursenum); - if ($dbresult eq 'ok') { - $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.')); - } - } + my $db_name = &Apache::lonsimplepage::get_db_name($url); + if ($db_name =~ /^smppage_/) { + #simple pages, need to copy the db contents to a new one. + my %contents=&Apache::lonnet::dump($db_name,$coursedom,$coursenum); + my $now = time(); + $db_name =~ s{_\d*$ }{_$now}x; + my $result=&Apache::lonnet::put($db_name,\%contents, + $coursedom,$coursenum); + $url =~ s{/(\d*)/smppg$ }{/$now/smppg}x; + $title=&mt('Copy of').' '.$title; + } } $title = &LONCAPA::map::qtunescape($title); my $ext='false'; if ($url=~m{^http(|s)://}) { $ext='true'; } $url = &LONCAPA::map::qtunescape($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,$newdocsdir) = ($folder =~ /^(default|supplemental)_?(\d*)/); - my $newprefix = $newloc; - if ($newloc eq 'default') { - $newprefix = 'docs'; - } - if ($newdocsdir eq '') { - $newdocsdir = 'default'; - } - if (($prefixchg) || ($srcdom ne $coursedom) || ($srcnum ne $coursenum)) { - 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.')); - } else { - my ($newsubpath) = ($newpath =~ m{^(.*/)[^/]*$}); - $newsubpath =~ s{/+$}{/}; - $docmoves{$oldurl} = $newsubpath; - } - } - } - } - } -# 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/) { - (undef,undef,$title) = - &Apache::loncommon::parse_supplemental_title($env{'docs.markedcopy_supplemental'}); - } - } else { - if ($folder=~/^supplemental/) { - $title=time.'___&&&___'.$env{'user.name'}.'___&&&___'. - $env{'user.domain'}.'___&&&___'.$title; - } - } - $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; + my $newidx = &LONCAPA::map::getresidx($url); + if ($env{'docs.markedcopy_supplemental'}) { + if ($folder =~ /^supplemental/) { + $title = $env{'docs.markedcopy_supplemental'}; } 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; - } + (undef,undef,$title) = + &parse_supplemental_title($env{'docs.markedcopy_supplemental'}); } - 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')); - } + } else { + if ($folder=~/^supplemental/) { + $title=time.'___&&&___'.$env{'user.name'}.'___&&&___'. + $env{'user.domain'}.'___&&&___'.$title; } } - return ($newurl); -} -sub dbcopy { - my ($url,$coursedom,$coursenum) = @_; - if ($url=~ m{/smppg$}) { - my $db_name = &Apache::lonsimplepage::get_db_name($url); - if ($db_name =~ /^smppage_/) { - #simple pages, need to copy the db contents to a new one. - my %contents=&Apache::lonnet::dump($db_name,$coursedom,$coursenum); - my $now = time(); - $db_name =~ s{_\d*$ }{_$now}x; - my $result=&Apache::lonnet::put($db_name,\%contents, - $coursedom,$coursenum); - $url =~ s{/(\d*)/smppg$ }{/$now/smppg}x; - } - } - return $url; + $LONCAPA::map::resources[$newidx]= $title.':'.$url.':'.$ext.':normal:res'; + push(@LONCAPA::map::order, $newidx); + return 'ok'; +# Store the result } sub uniqueness_check { @@ -1218,458 +764,6 @@ sub uniqueness_check { return $unique; } -sub contained_map_check { - 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); - $parser->attr_encoded(1); - while (my $token = $parser->get_token) { - next if ($token->[0] ne 'S'); - if ($token->[1] eq 'resource') { - next if ($token->[2]->{'type'} eq 'zombie'); - my $ressrc = $token->[2]->{'src'}; - if ($folder =~ /^supplemental/) { - unless (&supp_pasteable($ressrc)) { - $removefrommap->{$url}{$token->[2]->{'id'}} = $ressrc; - next; - } - } - 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 { - 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,$removeparam, - $addedmaps,$hierarchy,$titles,$allmaps); - } - } elsif ($token->[1] eq 'param') { - if ($folder =~ /^supplemental/) { - 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'}]; - } - } - } - } - } - return; -} - -sub reinit_role { - my ($cdom,$cnum,$chome) = @_; - my ($furl,$ferr) = &Apache::lonuserstate::readmap("$cdom/$cnum"); - unless ($ferr) { - &Apache::loncommon::update_content_constraints($cdom,$cnum,$chome,$cdom.'_'.$cnum); - } - return; -} - -sub url_paste_fixups { - 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})) { - $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); - $parser->attr_encoded(1); - my $changed = 0; - while (my $token = $parser->get_token) { - next if ($token->[0] ne 'S'); - if ($token->[1] eq 'resource') { - my $ressrc = $token->[2]->{'src'}; - next if ($ressrc eq ''); - my $id = $token->[2]->{'id'}; - my $title = $token->[2]->{'title'}; - if ($checktitle) { - 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 $srcdom = $1; - my $srcnum = $2; - my $rem = $3; - 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,$folder,$prefixchg,$cdom,$cnum,$allmaps, - $rewrites,$retitles,$copies,$dbcopies,$zombies, - $params,$mapmoves,$mapchanges,$tomove,$newsubdir, - $newurls)) { - $mapmoves->{$ressrc} = 1; - } - $changed = 1; - } else { - $rewrites->{$oldurl}{$ressrc} = $id; - $copies->{$oldurl}{$ressrc} = $id; - $changed = 1; - } - } - } elsif ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/(.+)$}) { - 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)/(.+)$}) { - 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'}); - } else { - @{$params->{$oldurl}{$to}} = ($token->[2]->{'name'}); - } - } - } - } - return $changed; -} - -sub apply_fixups { - 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') { - my %added; - foreach my $innerkey (keys(%{$copies->{$key}})) { - if (($innerkey ne '') && (!$added{$innerkey})) { - push(@allcopies,$innerkey); - $added{$innerkey} = 1; - } - } - undef(%added); - } - if ($key eq $oldurl) { - if ((exists($docmoves->{$key}))) { - unless (grep(/^\Q$oldurl\E/,@allcopies)) { - push(@allcopies,$oldurl); - } - } - } - if (@allcopies > 0) { - foreach my $item (@allcopies) { - 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') { - my $storefn; - if (($key eq $oldurl) && (ref($docmoves) eq 'HASH') && (exists($docmoves->{$key}))) { - $storefn = $docmoves->{$key}; - } else { - $storefn = $relpath; - $storefn =~s{^/uploaded/$match_domain/$match_courseid/}{}; - if ($prefixchg) { - $storefn =~ s/^\Q$before->{'doc'}\E/$after->{'doc'}/; - } - if ($newsubdir->{$key}) { - $storefn =~ s#^(docs|supplemental)/\Q$oldsubdir\E/#$1/$newsubdir->{$key}#; - } - } - ©_dependencies($item,$storefn,$relpath,$errors,\$content); - my $copyurl = - &Apache::lonclonecourse::writefile($env{'request.course.id'}, - $storefn.$fname,$content); - if ($copyurl eq '/adm/notfound.html') { - if ((ref($docmoves) eq 'HASH') && (exists($docmoves->{$oldurl}))) { - return &mt('Paste failed: an error occurred copying the file.'); - } elsif (ref($errors) eq 'HASH') { - $errors->{$item} = 1; - } - } - } - } - } - } - } - foreach my $key (keys(%{$mapmoves})) { - my $storefn=$key; - $storefn=~s{^/uploaded/$match_domain/$match_courseid/}{}; - 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') { - $errors->{$key} = 1; - } - } else { - my $newmap = - &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn, - $mapcontent); - if ($newmap eq '/adm/notfound.html') { - if (ref($errors) eq 'HASH') { - $errors->{$key} = 1; - } - } - } - } - my %updates; - if ($is_map) { - foreach my $key (keys(%{$rewrites})) { - $updates{$key} = 1; - } - foreach my $key (keys(%{$zombies})) { - $updates{$key} = 1; - } - foreach my $key (keys(%{$removefrommap})) { - $updates{$key} = 1; - } - foreach my $key (keys(%{$removeparam})) { - $updates{$key} = 1; - } - foreach my $key (keys(%{$dbcopies})) { - $updates{$key} = 1; - } - foreach my $key (keys(%{$retitles})) { - $updates{$key} = 1; - } - foreach my $key (keys(%updates)) { - my (%torewrite,%toretitle,%toremove,%remparam,%currparam,%zombie,%newdb); - if (ref($rewrites->{$key}) eq 'HASH') { - %torewrite = %{$rewrites->{$key}}; - } - if (ref($retitles->{$key}) eq 'HASH') { - %toretitle = %{$retitles->{$key}}; - } - 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}}; - } - if (ref($dbcopies->{$key}) eq 'HASH') { - foreach my $item (keys(%{$dbcopies->{$key}})) { - $newdb{$item} = &dbcopy($item); - } - } - 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); - } - } - 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'}#; - } - } - 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}#; - } - } - } - $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); - } - } - } - my $storefn; - if ($key eq $oldurl) { - $storefn = $url; - $storefn=~s{^/uploaded/$match_domain/$match_courseid/}{}; - } else { - $storefn = $key; - $storefn=~s{^/uploaded/$match_domain/$match_courseid/}{}; - if ($prefixchg) { - $storefn =~ s/^\Q$before->{'map'}\E/$after->{'map'}/; - } - if ($newsubdir->{$key}) { - $storefn =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir->{$key}/; - } - } - 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.'); - } - } - } - return 'ok'; -} - -sub copy_dependencies { - my ($item,$storefn,$relpath,$errors,$contentref) = @_; - my $content; - if (ref($contentref)) { - $content = $$contentref; - } else { - $content = &Apache::lonnet::getfile($item); - } - unless ($content eq '-1') { - my $mm = new File::MMagic; - my $mimetype = $mm->checktype_contents($content); - if ($mimetype eq 'text/html') { - my (%allfiles,%codebase,$state); - my $res = &Apache::lonnet::extract_embedded_items(undef,\%allfiles,\%codebase,\$content); - if ($res eq 'ok') { - my ($numexisting,$numpathchanges,$existing); - (undef,$numexisting,$numpathchanges,$existing) = - &Apache::loncommon::ask_for_embedded_content( - '/adm/coursedocs',$state,\%allfiles,\%codebase, - {'error_on_invalid_names' => 1, - 'ignore_remote_references' => 1, - 'docs_url' => $item, - 'context' => 'paste'}); - if ($numexisting > 0) { - if (ref($existing) eq 'HASH') { - foreach my $dep (keys(%{$existing})) { - my $depfile = $dep; - unless ($depfile =~ m{^\Q$relpath\E}) { - $depfile = $relpath.$dep; - } - my $depcontent = &Apache::lonnet::getfile($depfile); - unless ($depcontent eq '-1') { - my $storedep = $dep; - $storedep =~ s{^\Q$relpath\E}{}; - my $dep_url = - &Apache::lonclonecourse::writefile( - $env{'request.course.id'}, - $storefn.$storedep,$depcontent); - if ($dep_url eq '/adm/notfound.html') { - if (ref($errors) eq 'HASH') { - $errors->{$depfile} = 1; - } - } else { - ©_dependencies($depfile,$storefn,$relpath,$errors,\$depcontent); - } - } - } - } - } - } - } - } - return; -} - my %parameter_type = ( 'randompick' => 'int_pos', 'hiddenresource' => 'string_yesno', 'encrypturl' => 'string_yesno', @@ -1743,7 +837,7 @@ sub handle_edit_cmd { sub editor { my ($r,$coursenum,$coursedom,$folder,$allowed,$upload_output,$crstype, - $supplementalflag,$orderhash,$iconpath,$uploadtag)=@_; + $supplementalflag,$orderhash,$iconpath)=@_; my $container= ($env{'form.pagepath'}) ? 'page' : 'sequence'; @@ -1790,35 +884,20 @@ sub editor { } if ($env{'form.pastemarked'}) { - my %paste_errors; - 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') { + my $paste_res = + &do_paste_from_buffer($coursenum,$coursedom,$folder); + if ($paste_res eq 'ok') { + ($errtext,$fatal) = &storemap($coursenum,$coursedom,$folder.'.'.$container); + return $errtext if ($fatal); + } elsif ($paste_res ne '') { $r->print('

'.$paste_res.'

'); } - if (keys(%paste_errors) > 0) { - $r->print('

'."\n". - &mt('The following files are either dependencies of a web page or references within a folder and/or composite page which could not be copied during the paste operation:')."\n". - '

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

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

'); @@ -1899,8 +978,7 @@ sub editor { unless ($name) { $name=(split(/\//,$url))[-1]; } unless ($name) { $idx++; next; } $output .= &entryline($idx,$name,$url,$folder,$allowed,$res, - $coursenum,$coursedom,$crstype, - $uploadtag,$supplementalflag); + $coursenum,$crstype); $idx++; $shown++; } @@ -1938,7 +1016,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,$coursedom,$coursenum); + &print_paste_buffer($r,$container); } else { if (&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) { #Function Box for Supplemental Content for users with mdc priv. @@ -2026,7 +1104,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,1); + $folder.'.'.$container); if ($fatal) { $$upload_output = '
'.$errtext.'
'; return; @@ -2114,14 +1192,36 @@ sub is_supplemental_title { return scalar($title =~ m/^(\d+)___&&&___($match_username)___&&&___($match_domain)___&&&___(.*)$/); } +sub parse_supplemental_title { + my ($title) = @_; + + my ($foldertitle,$renametitle); + if ($title =~ /&&&/) { + $title = &HTML::Entites::decode($title); + } + if ($title =~ m/^(\d+)___&&&___($match_username)___&&&___($match_domain)___&&&___(.*)$/) { + $renametitle=$4; + my ($time,$uname,$udom) = ($1,$2,$3); + $foldertitle=&Apache::lontexconvert::msgtexconverted($4); + my $name = &Apache::loncommon::plainname($uname,$udom); + $name = &HTML::Entities::encode($name,'"<>&\''); + $renametitle = &HTML::Entities::encode($renametitle,'"<>&\''); + $title=''.&Apache::lonlocal::locallocaltime($time).' '. + $name.':
'.$foldertitle; + } + if (wantarray) { + return ($title,$foldertitle,$renametitle); + } + return $title; +} + # --------------------------------------------------------------- An entry line sub entryline { - my ($index,$title,$url,$folder,$allowed,$residx,$coursenum,$coursedom, - $crstype,$uploadtag,$supplementalflag)=@_; + my ($index,$title,$url,$folder,$allowed,$residx,$coursenum,$crstype)=@_; my ($foldertitle,$pagetitle,$renametitle); if (&is_supplemental_title($title)) { - ($title,$foldertitle,$renametitle) = &Apache::loncommon::parse_supplemental_title($title); + ($title,$foldertitle,$renametitle) = &parse_supplemental_title($title); $pagetitle = $foldertitle; } else { $title=&HTML::Entities::encode($title,'"<>&\''); @@ -2132,6 +1232,7 @@ sub entryline { my $orderidx=$LONCAPA::map::order[$index]; + $renametitle=~s/\\/\\\\/g; $renametitle=~s/\"\;/\\\"/g; $renametitle=~s/ /%20/g; @@ -2150,18 +1251,9 @@ sub entryline { $type = $container = 'page'; $esc_path=&escape($env{'form.pagepath'}); $path = &HTML::Entities::encode($env{'form.pagepath'},'<>&"'); + $symb=&escape($env{'form.pagesymb'}); } - if (!$supplementalflag && $residx) { - my $currurl = $url; - $currurl =~ s{^http(|s)(:|:)//}{/adm/wrapper/ext/}; - my $path = 'uploaded/'. - $env{'course.'.$env{'request.course.id'}.'.domain'}.'/'. - $env{'course.'.$env{'request.course.id'}.'.num'}.'/'; - $symb = &Apache::lonnet::encode_symb($path.$folder.".$container", - $residx, - &Apache::lonnet::declutter($currurl)); - } - my %lt; + my $cpinfo=''; if ($allowed) { my $incindex=$index+1; my $selectbox=''; @@ -2184,83 +1276,35 @@ sub entryline { } $selectbox.=''; } - %lt=&Apache::lonlocal::texthash( + my %lt=&Apache::lonlocal::texthash( 'up' => 'Move Up', 'dw' => 'Move Down', 'rm' => 'Remove', 'ct' => 'Cut', 'rn' => 'Rename', - 'cp' => 'Copy', - 'ex' => 'External Resource', - 'ed' => 'Edit', - 'pr' => 'Preview', - 'sv' => 'Save', - 'ul' => 'URL', - 'ti' => 'Title', - ); + 'cp' => 'Copy'); my $nocopy=0; my $nocut=0; - my $noremove=0; - if ($url=~ m{^/res/.+\.(page|sequence)$}) { - # no copy for published maps - $nocopy=1; - } + 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=~/^\/res\/lib\/templates\//) { $nocopy=1; $nocut=1; } - my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; - my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; - if ($url eq "/uploaded/$cdom/$cnum/group_allfolders.sequence") { - if ($env{'form.folderpath'} =~ /^default&[^\&]+$/) { - my %curr_groups = &Apache::longroup::coursegroups(); - if (keys(%curr_groups) > 0) { - $noremove=1; - } - $nocut=1; - $nocopy=1; - } - } elsif ($url =~ m{^\Q/uploaded/$cdom/$cnum/group_folder_\E(\w+)\.sequence$}) { - my $group = $1; - if ($env{'form.folderpath'} =~ /^default&[^\&]+\&group_allfolders\&[^\&]+$/) { - my %curr_group = &Apache::longroup::coursegroups($cdom,$cnum,$group); - if (keys(%curr_group) > 0) { - $noremove=1; - } - } - $nocut=1; - $nocopy=1; - } elsif ($url =~ m{^\Q/adm/$cdom/$cnum/\E(\w+)/smppg$}) { - my $group = $1; - if ($env{'form.folderpath'} =~ /^default&[^\&]+\&group_allfolders\&[^\&]+\&\Qgroup_folder_$group\E\&[^\&]+$/) { - my %curr_group = &Apache::longroup::coursegroups($cdom,$cnum,$group); - my %groupsettings = &Apache::longroup::get_group_settings($curr_group{$group}); - if (keys(%groupsettings) > 0) { - $noremove=1; - } - $nocut=1; - $nocopy=1; - } - } elsif ($env{'form.folderpath'} =~ /^default&[^\&]+\&group_allfolders\&[^\&]+\&group_folder_(\w+)\&/) { - my $group = $1; - my %curr_group = &Apache::longroup::coursegroups($cdom,$cnum,$group); - if ($url =~ /group_boards_\Q$group\E/) { - my %curr_group = &Apache::longroup::coursegroups($cdom,$cnum,$group); - my %groupsettings = &Apache::longroup::get_group_settings($curr_group{$group}); - if (keys(%groupsettings) > 0) { - if (ref($groupsettings{'functions'}) eq 'HASH') { - if ($groupsettings{'functions'}{'discussion'} eq 'on') { - $noremove=1; - } - } - } - $nocut=1; - $nocopy=1; - } - } my $copylink=' '; my $cutlink=' '; - my $removelink=' '; my $skip_confirm = 0; if ( $folder =~ /^supplemental/ @@ -2284,11 +1328,6 @@ ENDCOPY $lt{'ct'} ENDCUT } - if (!$noremove) { - $removelink=(<$lt{'rm'} -ENDREM - } $form_start = '
'; @@ -2302,13 +1341,13 @@ END $line.=(<
- - $lt{'up'} + + $lt{
- - $lt{'dw'} + + $lt{
@@ -2319,7 +1358,7 @@ END $form_end -$removelink + $lt{'rm'} $cutlink $lt{'rn'} $copylink @@ -2359,38 +1398,44 @@ END } } - my $editlink; my $orig_url = $url; $orig_url=~s{http(:|:)//https(:|:)//}{https$2//}; my $external = ($url=~s{^http(|s)(:|:)//}{/adm/wrapper/ext/}); - if (!$supplementalflag && $residx && $symb) { - if ($container eq 'page') { - $url=&Apache::lonnet::clutter((&Apache::lonnet::decode_symb($symb))[2]); - $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($symb); - } - if ((!$isfolder) && (!$ispage)) { - (undef,undef,$url)=&Apache::lonnet::decode_symb($symb); - $url=&Apache::lonnet::clutter($url); - if ($url=~/^\/*uploaded\//) { - $url=~/\.(\w+)$/; - my $embstyle=&Apache::loncommon::fileembstyle($1); - if (($embstyle eq 'img') || ($embstyle eq 'emb')) { - $url='/adm/wrapper'.$url; - } elsif ($embstyle eq 'ssi') { - #do nothing with these - } elsif ($url!~/\.(sequence|page)$/) { - $url='/adm/coursedocs/showdoc'.$url; - } - } elsif ($url=~m|^/ext/|) { - $url='/adm/wrapper'.$url; - $external = 1; - } - if (&Apache::lonnet::symbverify($symb,$url)) { - $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($symb); - } else { - $url=''; - } + if ((!$isfolder) && ($residx) && ($folder!~/supplemental/) && (!$ispage)) { + my $symb=&Apache::lonnet::symbclean( + &Apache::lonnet::declutter('uploaded/'. + $env{'course.'.$env{'request.course.id'}.'.domain'}.'/'. + $env{'course.'.$env{'request.course.id'}.'.num'}.'/'.$folder. + '.sequence'). + '___'.$residx.'___'. + &Apache::lonnet::declutter($url)); + (undef,undef,$url)=&Apache::lonnet::decode_symb($symb); + $url=&Apache::lonnet::clutter($url); + if ($url=~/^\/*uploaded\//) { + $url=~/\.(\w+)$/; + my $embstyle=&Apache::loncommon::fileembstyle($1); + if (($embstyle eq 'img') || ($embstyle eq 'emb')) { + $url='/adm/wrapper'.$url; + } elsif ($embstyle eq 'ssi') { + #do nothing with these + } elsif ($url!~/\.(sequence|page)$/) { + $url='/adm/coursedocs/showdoc'.$url; + } + } elsif ($url=~m|^/ext/|) { + $url='/adm/wrapper'.$url; + $external = 1; + } + if (&Apache::lonnet::symbverify($symb,$url)) { + $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($symb); + } else { + $url=''; } + if ($container eq 'page') { + my $symb=$env{'form.pagesymb'}; + + $url=&Apache::lonnet::clutter((&Apache::lonnet::decode_symb($symb))[2]); + $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($symb); + } } my ($rand_pick_text,$rand_order_text); if ($isfolder || $extension eq 'sequence') { @@ -2407,7 +1452,7 @@ END 'parameter_encrypturl'))[0]=~/^yes$/i) .':'.((&LONCAPA::map::getparameter($orderidx, 'parameter_randomorder'))[0]=~/^yes$/i); - $url.='folderpath='.&escape($folderpath); + $url.='folderpath='.&escape($folderpath).$cpinfo; my $rpicknum = (&LONCAPA::map::getparameter($orderidx, 'parameter_randompick'))[0]; my $rpckchk; @@ -2436,50 +1481,23 @@ $form_common.' my $folderpath=$env{'form.folderpath'}; if ($folderpath) { $pagepath = $folderpath.'&' }; $pagepath.=$pagearg.'&'.$pagename; + my $symb=$env{'form.pagesymb'}; + if (!$symb) { + my $path='uploaded/'. + $env{'course.'.$env{'request.course.id'}.'.domain'}.'/'. + $env{'course.'.$env{'request.course.id'}.'.num'}.'/'; + $symb=&Apache::lonnet::encode_symb($path.$folder.'.sequence', + $residx, + $path.$pagearg.'.page'); + } $url.='pagepath='.&escape($pagepath). - '&pagesymb='.&escape($symb); + '&pagesymb='.&escape($symb).$cpinfo; } - if ($allowed) { - my $fileloc = - &Apache::lonnet::declutter(&Apache::lonnet::filelocation('',$orig_url)); - - if ($external) { - $editlink = <<"EXTLNK"; -   - - $lt{'ed'} - - - -EXTLNK - } else { - my ($cfile,$home,$switchserver,$uploaded) = - &Apache::lonnet::can_edit_resource($fileloc,$coursenum,$coursedom); - if (($cfile ne '') && ($symb ne '')) { - my $jscall = - &Apache::lonhtmlcommon::jump_to_editres($cfile,$home, - $switchserver, - $uploaded,$symb); - if ($jscall) { - $editlink = ' '.&mt('Edit').''; - } - } - } + if (($external) && ($allowed)) { + my $form = ($folder =~ /^default/)? 'newext' : 'supnewext'; + $external = ' '.&mt('Edit').''; + } else { + undef($external); } my $reinit; if ($crstype eq 'Community') { @@ -2505,7 +1523,7 @@ EXTLNK } else { $line.=$title.' '.$reinit.''; } - $line.=$editlink.""; + $line.=$external.""; $rand_pick_text = ' ' if ($rand_pick_text eq ''); $rand_order_text = ' ' if ($rand_order_text eq ''); if (($allowed) && ($folder!~/^supplemental/)) { @@ -2901,8 +1919,7 @@ ENDHEADERS ''.&mt('History').''. ''); foreach my $key (sort(keys(%changes))) { - #excludes not versionable problems from resource version history: - next unless ($changes{$key}>$starttime && $key !~ /^\/res\/lib\/templates/); + if ($changes{$key}>$starttime) { my ($root,$extension)=($key=~/^(.*)\.(\w+)$/); my $currentversion=&Apache::lonnet::getversion($key); if ($currentversion<0) { @@ -3068,9 +2085,9 @@ sub init_breadcrumbs { sub create_list_elements { my @formarr = @_; my $list = ''; - foreach my $button (@formarr){ - foreach my $picture (keys(%{$button})) { - $list .= &Apache::lonhtmlcommon::htmltag('li', $picture.' '.$button->{$picture}, {class => 'LC_menubuttons_inline_text', id => ''}); + for my $button (@formarr){ + for my $picture(keys %$button) { + $list .= &Apache::lonhtmlcommon::htmltag('li', $picture.' '.$button->{$picture}, {class => 'LC_menubuttons_inline_text'}); } } return $list; @@ -3093,6 +2110,7 @@ sub startContentScreen { if (($mode eq 'navmaps') || ($mode eq 'supplemental')) { $output .= '    '.&mt('Content Overview').'    '."\n"; $output .= '     '.&mt('Content Search').'     '."\n"; + $output .= '      '.&mt('Content Index').'      '."\n"; $output .= '
  • '.&mt('Supplemental Content').'
  • '; } else { $output .= '
  •       '.&mt('Content Editor').'      
  • '."\n"; @@ -3139,8 +2157,7 @@ sub handler { 'Adding_External_Resource','Navigate_Content', 'Adding_Folders','Docs_Overview', 'Load_Map', 'Supplemental','Score_Upload_Form','Adding_Pages', - 'Importing_LON-CAPA_Resource','Importing_IMS_Course', - 'Uploading_From_Harddrive', + 'Importing_LON-CAPA_Resource','Uploading_From_Harddrive', 'Check_Resource_Versions','Verify_Content') { $help{$topic}=&Apache::loncommon::help_open_topic('Docs_'.$topic); } @@ -3431,11 +2448,6 @@ sub handler { onload => "javascript:resize_scrollbox('contentscroll','1','1');", }; } - if ($env{'docs.markedcopy_url'}) { - $script .= &paste_popup_js(); - } - my $confirm_switch = &mt("Editing requires switching to the resource's home server.").'\n'. - &mt('Switch server?'); } # -------------------------------------------------------------------- Body tag $script = '