--- loncom/interface/londocs.pm 2012/05/10 17:56:58 1.484.2.3 +++ loncom/interface/londocs.pm 2012/07/05 21:33:39 1.489 @@ -1,7 +1,7 @@ # The LearningOnline Network # Documents # -# $Id: londocs.pm,v 1.484.2.3 2012/05/10 17:56:58 raeburn Exp $ +# $Id: londocs.pm,v 1.489 2012/07/05 21:33:39 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -40,7 +40,9 @@ 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; @@ -425,16 +427,18 @@ sub log_docs { sub docs_change_log { my ($r,$coursenum,$coursedom,$folder,$allowed,$crstype,$iconpath)=@_; + my $supplementalflag=($env{'form.folderpath'}=~/^supplemental/); my $js = ''."\n"; $r->print(&Apache::loncommon::start_page('Content Change Log',$js)); $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content Change Log')); - $r->print(&startContentScreen('docs')); + $r->print(&startContentScreen(($supplementalflag?'suppdocs':'docs'))); my %orderhash; my $container='sequence'; my $pathitem; @@ -453,6 +457,9 @@ 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, @@ -527,18 +534,30 @@ 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) { - $r->print(&LONCAPA::map::qtescape($oldname)); + my $shown = &LONCAPA::map::qtescape($oldname); + if ($is_supp) { + $shown = &Apache::loncommon::parse_supplemental_title($shown); + } + $r->print($shown); } } $r->print(''); @@ -549,13 +568,21 @@ 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) { - $r->print(&LONCAPA::map::qtescape($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(''); @@ -600,7 +627,7 @@ 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) = &parse_supplemental_title($title); + ($title) = &Apache::loncommon::parse_supplemental_title($title); } elsif ($env{'docs.markedcopy_supplemental'}) { &Apache::lonnet::delenv('docs.markedcopy_supplemental'); } @@ -612,23 +639,42 @@ sub update_paste_buffer { } sub print_paste_buffer { - my ($r,$container) = @_; + my ($r,$container,$folder) = @_; return if (!defined($env{'docs.markedcopy_url'})); + my $is_external; + my $extension = (split(/\./,$env{'docs.markedcopy_url'}))[-1]; + if ($env{'docs.markedcopy_url'} =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//} ) { + $is_external = 1; + } + + my $canpaste; + if ($folder =~ /^supplemental/) { + $canpaste = &supp_pasteable($env{'docs.markedcopy_url'}); + } else { + $canpaste = 1; + } + + my $pasteinfo; + if ($canpaste) { + $pasteinfo = '
' + .' '; + } else { + $pasteinfo = &mt('Paste buffer contains:').' '; + } + $r->print('
' .''.&mt('Clipboard').'' - .'' - .' ' - ); + .$pasteinfo + ); my $type; - if ($env{'docs.markedcopy_url'} =~ m{^(?:/adm/wrapper/ext|(?:http|https)(?::|:))//} ) { + if ($is_external) { $type = &mt('External Resource'); $r->print($type.': '. &LONCAPA::map::qtescape($env{'docs.markedcopy_title'}).' ('. &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) { @@ -636,19 +682,36 @@ sub print_paste_buffer { $icon .= '/navmap.folder.closed.gif'; } $icon = ''; - $r->print($icon.$type.': '. &parse_supplemental_title(&LONCAPA::map::qtescape($env{'docs.markedcopy_title'}))); + $r->print($icon.$type.': '. &Apache::loncommon::parse_supplemental_title(&LONCAPA::map::qtescape($env{'docs.markedcopy_title'}))); } - if ($container eq 'page') { - $r->print(' + if ($canpaste) { + if ($container eq 'page') { + $r->print(' '); - } else { - $r->print(' + } else { + $r->print(' '); + } + $r->print(''); + } else { + $r->print('

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

'); + } + $r->print('
'); +} + +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; } - $r->print(''); + return; } sub do_paste_from_buffer { @@ -658,15 +721,39 @@ sub do_paste_from_buffer { return; } +# 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'); + } + } + # paste resource to end of list my $url=&LONCAPA::map::qtescape($env{'docs.markedcopy_url'}); my $title=&LONCAPA::map::qtescape($env{'docs.markedcopy_title'}); # Maps need to be copied first - if (($url=~/\.(page|sequence)$/) && ($url=~/^\/uploaded\//)) { - $title=&mt('Copy of').' '.$title; + my ($oldurl,%removefrommap,%addedmaps,%rewrites,%copies,%dbcopies,%zombies,%params, + %moves,$srcdom,$srcnum); + $oldurl = $url; + if ($url=~/\.(page|sequence)$/) { + # If pasting a map, check if map contains other maps + &contained_map_check($url,$folder,\%removefrommap,\%addedmaps); + if (keys(%addedmaps) > 0) { + &reinit_role($coursedom,$coursenum,$env{"course.$env{'request.course.id'}.home"}); + } + my %allmaps; + 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; + } + } + if ($url=~ m{^/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+)$}) { + if ($oldid =~ m{^(/uploaded/$match_domain/$match_courseid/)(\D+)(\d+)$}) { my $path = $1; my $prefix = $2; my $ancestor = $3; @@ -674,40 +761,68 @@ sub do_paste_from_buffer { $ancestor = substr($ancestor,-10,10); } $oldid = $path.$prefix.$ancestor; - } - 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); - } - if (!$is_unique) { - if ($url=~/\.page$/) { - return &mt('Paste failed: an error occurred creating a unique URL for the composite page'); + my $counter = 0; + my $newurl=$oldid.$newid.'.'.$ext; + my $is_unique = &uniqueness_check($newurl); + if ($allmaps{$newurl}) { + $is_unique = 0; + } + while (!$is_unique && $allmaps{$newurl} && $counter < 100) { + $counter ++; + $newid ++; + $newurl = $oldid.$newid; + $is_unique = &uniqueness_check($newurl); + } + if ($is_unique) { + if ($path =~ m{^/uploaded/($match_domain)/($match_courseid)/$}) { + $srcdom = $1; + $srcnum = $2; + if (($1 ne $coursedom) && ($2 ne $coursenum)) { + my $srcdom = $1; + my $srcnum = $2; + if ($env{"user.priv.cm./$srcdom/$srcnum"} =~ /\Q:mdc&F\E/) { + &url_paste_fixups($oldid,$ext,$coursedom,$coursenum, + \%allmaps, \%rewrites,\%copies,\%dbcopies,\%zombies,\%params); + } else { + return &mt('Paste failed: Item is from a different course which you do not have rights to edit'); + } + } + } } else { - return &mt('Paste failed: an error occurred creating a unique URL for the folder'); + 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 $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'); + } + } + $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 ($allmaps{$url}) { + return &mt('Paste failed: only one instance of a particular published sequence or page is allowed within each course.'); } } - 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'); + } elsif ($url =~ m{^/uploaded/($match_domain)/($match_courseid)/}) { + if (($1 ne $coursedom) || ($2 ne $coursenum)) { + $srcdom = $1; + $srcnum = $2; + 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'); } } - $url = $newurl; - } -# published maps can only exists once, so remove it from paste buffer when done - 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); @@ -722,18 +837,58 @@ sub do_paste_from_buffer { $title=&mt('Copy of').' '.$title; } } + my ($relpath,$oldprefix,$prefixchg); + if ($url =~ m{^/uploaded/$match_domain/$match_courseid/(docs|supplemental)/(.+)$}) { + $oldprefix = $1; + $relpath = $2; + if (($folder =~ /^supplemental/) && ($oldprefix eq 'docs')) { + $prefixchg = 1; + } elsif (($folder =~ /^default/) && ($oldprefix eq 'supplemental')) { + $prefixchg = 1; + } + } $title = &LONCAPA::map::qtunescape($title); 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); + if ($relpath ne '') { + my ($prefix,$subdir,$rem) = ($relpath =~ m{^(default|\d+)/(\d+)/(.+)$}); + my ($newloc,$newsubdir) = ($folder =~ /^(default|supplemental)_?(\d*)/); + my $newprefix = $newloc; + if ($newloc eq 'default') { + $newprefix = 'docs'; + } + if ($newsubdir eq '') { + $newsubdir = 'default'; + } + if (($prefixchg) || ($srcdom ne '') && ($srcnum ne '')) { + my $newpath = "$newprefix/$newsubdir/$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{/+$}{/}; + $moves{$oldurl} = $newsubpath; + } + } + } + my $noparams = 0; + if ((ref($params{$oldurl}) eq 'HASH') && ($relpath ne '') && ($folder =~ /^supplemental/)) { + $noparams = 1; + } + &apply_fixups($coursedom,$coursenum,$oldurl,$url,$noparams,\%rewrites,\%copies, + \%dbcopies,\%zombies,\%params,\%moves); if ($env{'docs.markedcopy_supplemental'}) { if ($folder =~ /^supplemental/) { $title = $env{'docs.markedcopy_supplemental'}; } else { (undef,undef,$title) = - &parse_supplemental_title($env{'docs.markedcopy_supplemental'}); + &Apache::loncommon::parse_supplemental_title($env{'docs.markedcopy_supplemental'}); } } else { if ($folder=~/^supplemental/) { @@ -748,6 +903,23 @@ sub do_paste_from_buffer { # Store the result } +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; +} + sub uniqueness_check { my ($newurl) = @_; my $unique = 1; @@ -762,6 +934,219 @@ sub uniqueness_check { return $unique; } +sub contained_map_check { + my ($url,$folder,$removefrommap,$addedmaps) = @_; + 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'}}; + next; + } + } + if ($ressrc =~ /\.(sequence|page)$/) { + if (ref($addedmaps->{$ressrc}) eq 'ARRAY') { + push(@{$addedmaps->{$ressrc}},$url); + } else { + $addedmaps->{$ressrc} = [$url]; + } + &contained_map_check($ressrc,$folder,$removefrommap,$addedmaps); + } + } elsif ($token->[1] !~ /^resource|map|link$/) { + if ($folder =~ /^supplemental/) { + $removefrommap->{$url}{$token->[1]}; + } + } + } + } + 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,$ext,$cdom,$cnum,$allmaps,$rewrites,$copies,$dbcopies,$zombies,$params) = @_; + my $file = &Apache::lonnet::getfile("$oldurl.$ext"); + return if ($file eq '-1'); + my $parser = HTML::TokeParser->new(\$file); + $parser->attr_encoded(1); + 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 ''); + next if ($token->[2]->{'type'} eq 'external'); + my $id = $token->[2]->{'id'}; + if ($token->[2]->{'type'} eq 'zombie') { + $zombies->{$oldurl}{$ressrc} = $id; + } elsif ($ressrc =~ m{^/uploaded/($match_domain)/($match_courseid)/(.+)}) { + my $srccdom = $1; + my $srccnum = $2; + my $rem = $3; + if (($srccdom ne $cdom) || ($srccnum ne $cnum)) { + if ($rem =~ /^(default|supplemental)(_?\d*).(sequence|page)$/) { + $rewrites->{$oldurl}{$ressrc} = $id; + &url_paste_fixups($ressrc,$3,$cdom,$cnum,$allmaps,$rewrites,$copies,$dbcopies,$zombies,$params); + } else { + $rewrites->{$oldurl}{$ressrc} = $id; + $copies->{$oldurl}{$ressrc} = $id; + } + } + } elsif ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/(.+)$}) { + my $srccdom = $1; + my $srccnum = $2; + if (($srccdom ne $cdom) || ($srccnum ne $cnum)) { + $rewrites->{$oldurl}{$ressrc} = $id; + $dbcopies->{$oldurl}{$ressrc} = $id; + } + } elsif ($ressrc =~ m{^/public/($match_domain)/($match_courseid)/(.+)$}) { + my $srccdom = $1; + my $srccnum = $2; + if (($srccdom ne $cdom) || ($srccnum ne $cnum)) { + $rewrites->{$oldurl}{$ressrc} = $id; + $dbcopies->{$oldurl}{$ressrc} = $id; + } + } + } elsif ($token->[1] eq 'param') { + 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; +} + +sub apply_fixups { + my ($cdom,$cnum,$oldurl,$url,$noparams,$rewrites,$copies,$dbcopies,$zombies,$params, + $moves) = @_; + my (%newdb,%newdoc); + if (ref($dbcopies->{$oldurl}) eq 'HASH') { + foreach my $item (keys(%{$dbcopies->{$oldurl}})) { + $newdb{$item} = &dbcopy($item); + } + } + my @allcopies; + if (ref($copies->{$oldurl}) eq 'HASH') { + push(@allcopies,keys(%{$copies->{$oldurl}})); + } + if ((ref($moves) eq 'HASH') && (exists($moves->{$oldurl}))) { + push(@allcopies,$oldurl); + } + if (@allcopies > 0) { + foreach my $item (@allcopies) { + my $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); + if (&Apache::lonnet::extract_embedded_items(undef,\%allfiles,\%codebase,\$content) 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' => $oldurl, + 'context' => 'paste'}); + if ($numexisting > 0) { + if (ref($existing) eq 'HASH') { + my ($relpath) = ($item =~ m{^(/uploaded/$match_domain/$match_courseid/(?:docs|supplemental)/(?:default|\d+)/.*/)[^/]+$}); + foreach my $dep (keys(%{$existing})) { + $dep =~ s{^\Q$relpath\E}{}; + my $depfile = $relpath.$dep; + my $depstorefn; + if ((ref($copies->{$oldurl}) eq 'HASH') && + ($copies->{$oldurl}{$item})) { + $depstorefn = $relpath; + $depstorefn =~s{^/\w+/$match_domain/$match_courseid/}{}; + } elsif ((ref($moves) eq 'HASH') && + (exists($moves->{$oldurl}))) { + $depstorefn = $moves->{$oldurl}; + } + $depstorefn .= $dep; + my $depcontent = &Apache::lonnet::getfile($depfile); + unless ($depcontent eq '-1') { + &Apache::lonclonecourse::writefile($env{'request.course.id'},$depstorefn,$depcontent); + } + } + } + } + } + } + my $storefn=$item; + unless (exists($moves->{$oldurl})) { + $storefn=~s{^/\w+/$match_domain/$match_courseid/}{}; + $newdoc{$item} = &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn,$content); + } + } + } + } + if (((ref($rewrites->{$oldurl}) eq 'HASH') || (ref($zombies->{$oldurl}) eq 'HASH')) || + ($noparams) || (keys(%newdb) > 0) || (keys(%newdoc) > 0)) { + my $map = &Apache::lonnet::getfile($url); + my $newcontent; + unless ($map eq '-1') { + my $parser = HTML::TokeParser->new(\$map); + $parser->attr_encoded(1); + while (my $token = $parser->get_token) { + if ($token->[0] eq 'S') { + next if ($token->[2]->{'type'} eq 'zombie'); + next if (($token->[1] eq 'param') && $noparams); + if ($token->[1] eq 'resource') { + my $src = $token->[2]->{'src'}; + my $id = $token->[2]->{'id'}; + if (($rewrites->{$oldurl}{$src} eq $id) || ($newdb{$src} ne '') + || ($newdoc{$src} ne '')) { + if (ref($rewrites->{$oldurl}) eq 'HASH') { + if ($rewrites->{$oldurl}{$src} eq $id) { + $token->[2]->{'src'} =~ s{^(/uploaded|adm|public)/$match_domain/$match_courseid/}{$1/$cdom/$cnum}; + } + } elsif ($newdb{$src} ne '') { + $token->[2]->{'src'} = $newdb{$src}; + } + $newcontent .= "<$token->[1] "; + foreach my $attr (@{$token->[3]}) { + $newcontent .= ' '.$attr.'="'.$token->[2]->{$attr},'"' + } + $newcontent .= ' />'; + } else { + $newcontent .= $token->[4]."\n"; + } + } + } elsif ($token->[0] eq 'E') { + $newcontent .= $token->[2]."\n"; + } + } + } + my $storefn=$url; + $storefn=~s{^/\w+/$match_domain/$match_courseid/}{}; + my $storeres = + &Apache::lonclonecourse::writefile($env{'request.course.id'},$storefn, + $newcontent); + } + return; +} + my %parameter_type = ( 'randompick' => 'int_pos', 'hiddenresource' => 'string_yesno', 'encrypturl' => 'string_yesno', @@ -1014,7 +1399,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); + &print_paste_buffer($r,$container,$folder); } else { if (&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) { #Function Box for Supplemental Content for users with mdc priv. @@ -1190,36 +1575,13 @@ 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,$crstype)=@_; my ($foldertitle,$pagetitle,$renametitle); if (&is_supplemental_title($title)) { - ($title,$foldertitle,$renametitle) = &parse_supplemental_title($title); + ($title,$foldertitle,$renametitle) = &Apache::loncommon::parse_supplemental_title($title); $pagetitle = $foldertitle; } else { $title=&HTML::Entities::encode($title,'"<>&\''); @@ -2108,6 +2470,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"; @@ -2540,6 +2903,7 @@ sub handler { 'upld' => 'Import Document', 'srch' => 'Search', 'impo' => 'Import', + 'lnks' => 'Import from Stored Links', 'selm' => 'Select Map', 'load' => 'Load Map', 'reco' => 'Recover Deleted Documents', @@ -2607,6 +2971,7 @@ SEDFFORM my @simpleeditdefaultforma = ( { ''.$lt{srch}.'' => "$uploadtag$lt{'srch'}" }, { ''.$lt{impo}.'' => "$lt{'impo'}$help{'Importing_LON-CAPA_Resource'}" }, + { ''.$lt{lnks}.'' => "$lt{'lnks'}" }, ); $simpleeditdefaultform .= &create_form_ul(&create_list_elements(@simpleeditdefaultforma)); $simpleeditdefaultform .=(< ['Import Documents',$fileuploadform], - 'bb' => ['Published Resources',$simpleeditdefaultform], + 'aa' => ['Import Content',$fileuploadform], + 'bb' => ['Published Content',$simpleeditdefaultform], 'cc' => ['Grading Resources',$gradingform], ); unless ($env{'form.pagepath'}) { @@ -2993,7 +3358,7 @@ my @supimportdoc = ( $supupdocform = &create_form_ul(&create_list_elements(@supimportdoc)) . '
    ' . $supupdocform; my %suporderhash = ( '00' => ['Supnewfolder', $supnewfolderform], - 'ee' => ['Import Documents',$supupdocform], + 'ee' => ['Import Content',$supupdocform], 'ff' => ['Special Documents',&create_form_ul(&create_list_elements(@specialdocs))] ); if ($supplementalflag) { @@ -3278,26 +3643,24 @@ sub generate_edit_table { my $backicon = $iconpath.'clickhere.gif'; my $backtext = &mt('To Overview'); $form = '
    '. - '