'.
@@ -1852,13 +1901,18 @@ sub do_paste_from_buffer {
}
if ($url=~ m{/(bulletinboard|smppg|ext\.tool)$}) {
my $prefix = $1;
- my $fromothercrs;
+ my $fromothercrs;
#need to copy the db contents to a new one, unless this is a move.
my %info = (
src => $url,
cdom => $coursedom,
cnum => $coursenum,
);
+ if ($prefix eq 'ext.tool') {
+ if ($prefixchg{$suffix} eq 'docstosupp') {
+ $info{'delgradable'} = 1;
+ }
+ }
if (($srcdom{$suffix} =~ /^$match_domain$/) && ($srcnum{$suffix} =~ /^$match_courseid$/)) {
unless (($srcdom{$suffix} eq $coursedom) && ($srcnum{$suffix} eq $coursenum)) {
$fromothercrs = 1;
@@ -1950,6 +2004,18 @@ sub do_paste_from_buffer {
©_templated_files($url,$srcdom{$suffix},$srcnum{$suffix},$srcmapidx{$suffix},
$coursedom,$coursenum,$template,$newidx,"$folder.$container");
}
+ } elsif ($url =~ /ext\.tool$/) {
+ if (($newidx) && ($folder=~/^default/)) {
+ my $marker = (split(m{/},$url))[4];
+ my %toolsettings = &Apache::lonnet::dump('exttool_'.$marker,$coursedom,$coursenum);
+ my $val = 'no';
+ if ($toolsettings{'gradable'}) {
+ $val = 'yes';
+ }
+ &LONCAPA::map::storeparameter($newidx,'parameter_0_gradable',$val,
+ 'string_yesno');
+ &remember_parms($newidx,'gradable','set',$val);
+ }
}
$LONCAPA::map::resources[$newidx]=$title.':'.&LONCAPA::map::qtunescape($url).
':'.$ext.':normal:res';
@@ -2198,6 +2264,9 @@ sub dbcopy {
}
}
$db_name =~ s{_\d*$ }{_$suffix}x;
+ if (($prefix eq 'exttool') && ($dbref->{'delgradable'}) && ($contents{'gradable'})) {
+ delete($contents{'gradable'});
+ }
$result=&Apache::lonnet::put($db_name,\%contents,
$coursedom,$coursenum);
if ($result eq 'ok') {
@@ -2482,16 +2551,38 @@ sub url_paste_fixups {
$changed = 1;
}
}
- } elsif ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/.+$}) {
+ } elsif ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/(.+)$}) {
next if ($skip);
my $srcdom = $1;
my $srcnum = $2;
+ my $rem = $3;
+ my ($is_exttool,$exttoolchg);
+ if ($rem =~ m{\d+/ext\.tool$}) {
+ $is_exttool = 1;
+ }
if (($srcdom ne $cdom) || ($srcnum ne $cnum)) {
$rewrites->{$oldurl}{$id} = $ressrc;
$dbcopies->{$oldurl}{$id}{'src'} = $ressrc;
$dbcopies->{$oldurl}{$id}{'cdom'} = $srcdom;
$dbcopies->{$oldurl}{$id}{'cnum'} = $srcnum;
$changed = 1;
+ if ($is_exttool) {
+ $exttoolchg = 1;
+ }
+ } elsif (($rem =~ m{\d+/ext\.tool$}) &&
+ ($env{'form.docs.markedcopy_options'} ne 'move')) {
+ $dbcopies->{$oldurl}{$id}{'src'} = $ressrc;
+ $dbcopies->{$oldurl}{$id}{'cdom'} = $srcdom;
+ $dbcopies->{$oldurl}{$id}{'cnum'} = $srcnum;
+ $changed = 1;
+ $exttoolchg = 1;
+ }
+ if (($is_exttool) && ($prefixchg)) {
+ if ($oldurl =~ m{^/uploaded/$match_domain/$match_courseid/default}) {
+ if ($exttoolchg) {
+ $dbcopies->{$oldurl}{$id}{'delgradable'} = 1;
+ }
+ }
}
} elsif ($ressrc =~ m{^/adm/$match_domain/$match_username/\d+/(smppg|bulletinboard)$}) {
if (($fromcdom ne $cdom) || ($fromcnum ne $cnum) ||
@@ -2755,7 +2846,8 @@ sub apply_fixups {
}
}
}
- for (my $i=0; $i<@LONCAPA::map::order; $i++) {
+ my $total = scalar(@LONCAPA::map::order) - 1;
+ for (my $i=$total; $i>=0; $i--) {
my $idx = $LONCAPA::map::order[$i];
if (defined($LONCAPA::map::resources[$idx])) {
my $changed;
@@ -2765,7 +2857,7 @@ sub apply_fixups {
splice(@LONCAPA::map::order,$i,1);
if (ref($currparam{$idx}) eq 'ARRAY') {
foreach my $name (@{$currparam{$idx}}) {
- &LONCAPA::map::delparameter($idx,'parameter_'.$name);
+ &LONCAPA::map::delparameter($idx,$name);
}
}
next;
@@ -2807,7 +2899,7 @@ sub apply_fixups {
foreach my $idx (keys(%remparam)) {
if (ref($remparam{$idx}) eq 'ARRAY') {
foreach my $name (@{$remparam{$idx}}) {
- &LONCAPA::map::delparameter($idx,'parameter_'.$name);
+ &LONCAPA::map::delparameter($idx,$name);
}
}
}
@@ -4104,7 +4196,7 @@ END
}
}
if ($url ne '') {
- $url.=(($url=~/\?/)?'&':'?').'symb='.&HTML::Entities::encode($shownsymb,'"<>&');
+ $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($shownsymb);
}
} elsif (!$env{'request.role.adv'}) {
my $checkencrypt;
@@ -4125,7 +4217,7 @@ END
my $shownsymb = &Apache::lonenc::encrypted($symb);
my $shownurl = &Apache::lonenc::encrypted($url);
if (&Apache::lonnet::symbverify($shownsymb,$shownurl)) {
- $url = $shownurl.(($shownurl=~/\?/)?'&':'?').'symb='.&HTML::Entities::encode($shownsymb,'"<>&');
+ $url = $shownurl.(($shownurl=~/\?/)?'&':'?').'symb='.&escape($shownsymb);
if ($env{'request.enc'} ne '') {
delete($env{'request.enc'});
}
@@ -4311,7 +4403,7 @@ $form_end;
$reinit = &mt('(re-initialize course to access)');
}
$line.=''.$editlink.$renamelink;
- if ($url =~ /$LONCAPA::assess_re/) {
+ if ($orig_url =~ /$LONCAPA::assess_re/) {
$line.= ' ';
if ($curralias ne '') {
$line.=''.
@@ -4588,7 +4680,7 @@ sub untiehash {
sub checkonthis {
- my ($r,$url,$level,$title)=@_;
+ my ($r,$url,$level,$title,$checkstale)=@_;
$url=&unescape($url);
$alreadyseen{$url}=1;
$r->rflush();
@@ -4603,10 +4695,22 @@ sub checkonthis {
$r->print(''.
($title?$title:$url).' ');
if ($url=~/^\/res\//) {
+ my $updated;
+ if (($checkstale) && ($url !~ m{^/res/lib/templates/}) &&
+ ($url !~ /\.\d+\.\w+$/)) {
+ $updated = &Apache::lonnet::remove_stale_resfile($url);
+ }
my $result=&Apache::lonnet::repcopy(
&Apache::lonnet::filelocation('',$url));
if ($result eq 'ok') {
$r->print(''.&mt('ok').'');
+ if ($updated) {
+ $r->print(' ');
+ for (my $i=0;$i<=$level*5;$i++) {
+ $r->print(' ');
+ }
+ $r->print('- '.&mt('Outdated copy removed'));
+ }
$r->rflush();
&Apache::lonnet::countacc($url);
$url=~/\.(\w+)$/;
@@ -4640,7 +4744,7 @@ sub checkonthis {
&Apache::lonnet::metadata($url,'dependencies');
foreach my $dep (split(/\,/,$dependencies)) {
if (($dep=~/^\/res\//) && (!$alreadyseen{$dep})) {
- &checkonthis($r,$dep,$level+1);
+ &checkonthis($r,$dep,$level+1,'',$checkstale);
}
}
} elsif ($result eq 'unavailable') {
@@ -4654,6 +4758,9 @@ sub checkonthis {
} else {
$r->print(''.&mt('access denied').'');
}
+ if (($updated) && ($result ne 'ok')) {
+ $r->print(' '.&mt('Outdated copy removed'));
+ }
}
}
}
@@ -4706,13 +4813,75 @@ sub list_symbs {
$r->print(&endContentScreen());
}
+sub short_urls {
+ my ($r,$canedit) = @_;
+ my $crstype = &Apache::loncommon::course_type();
+ my $formname = 'shortenurl';
+ $r->print(&Apache::loncommon::start_page('Display/Set Shortened URLs'));
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs('Shortened URLs'));
+ $r->print(&startContentScreen('tools'));
+ my ($navmap,$errormsg) =
+ &Apache::loncourserespicker::get_navmap_object($crstype,'shorturls');
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my (%maps,%resources,%titles);
+ if (!ref($navmap)) {
+ $r->print($errormsg.
+ &endContentScreen());
+ return '';
+ } else {
+ $r->print(''.&mt('Tiny URLs for deep-linking into course').''."\n".
+ $r->rflush();
+ my $readonly;
+ if ($canedit) {
+ my ($numnew,$errors) = &Apache::loncommon::make_short_symbs($cdom,$cnum,$navmap);
+ if ($numnew) {
+ $r->print(''.&mt('Created [quant,_1,URL]',$numnew).' ');
+ }
+ if ((ref($errors) eq 'ARRAY') && (@{$errors} > 0)) {
+ $r->print(&mt('The following errors occurred when processing your request to create shortened URLs:').'
');
+ foreach my $error (@{$errors}) {
+ $r->print('- '.$error.'
');
+ }
+ $r->print(' ');
+ }
+ } else {
+ $readonly = 1;
+ }
+ my %currtiny = &Apache::lonnet::dump('tiny',$cdom,$cnum);
+ $r->print(&Apache::loncourserespicker::create_picker($navmap,'shorturls',$formname,$crstype,undef,
+ undef,undef,undef,undef,undef,\%currtiny,$readonly));
+ }
+ $r->print(&endContentScreen());
+}
-sub verifycontent {
+sub contentverifyform {
my ($r) = @_;
my $crstype = &Apache::loncommon::course_type();
$r->print(&Apache::loncommon::start_page('Verify '.$crstype.' Content'));
$r->print(&Apache::lonhtmlcommon::breadcrumbs('Verify '.$crstype.' Content'));
$r->print(&startContentScreen('tools'));
+ $r->print(''.&mt($crstype.' content verification').'');
+ $r->print('');
+ $r->print(&endContentScreen());
+ return;
+}
+
+sub verifycontent {
+ my ($r,$checkstale) = @_;
+ my $crstype = &Apache::loncommon::course_type();
+ $r->print(&Apache::loncommon::start_page('Verify '.$crstype.' Content'));
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs('Verify '.$crstype.' Content'));
+ $r->print(&startContentScreen('tools'));
$r->print(''.&mt($crstype.' content verification').'');
$hashtied=0;
undef %alreadyseen;
@@ -4729,7 +4898,7 @@ sub verifycontent {
}
}
if (($key=~/^src\_(.+)$/) && (!$alreadyseen{&unescape($hash{$key})})) {
- &checkonthis($r,$hash{$key},0,$hash{'title_'.$1});
+ &checkonthis($r,$hash{$key},0,$hash{'title_'.$1},$checkstale);
}
}
&untiehash();
@@ -4737,7 +4906,6 @@ sub verifycontent {
$r->print(&endContentScreen());
}
-
sub devalidateversioncache {
my $src=shift;
&Apache::lonnet::devalidate_cache_new('courseresversion',$env{'request.course.id'}.'_'.
@@ -5200,12 +5368,31 @@ sub handler {
$disabled = ' disabled="disabled"';
}
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['inhibitmenu']);
+ if ($env{'form.inhibitmenu'}) {
+ unless ($env{'form.inhibitmenu'} eq 'yes') {
+ delete($env{'form.inhibitmenu'});
+ }
+ }
+
if ($allowed && $env{'form.verify'}) {
&init_breadcrumbs('verify','Verify Content','Docs_Verify_Content');
- &verifycontent($r);
+ if (!$canedit) {
+ &verifycontent($r);
+ } elsif (($env{'form.checkstale'} ne '') && ($env{'form.checkstale'} =~ /^\d$/)) {
+ &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/coursedocs?tools=1&verify=1&checkstale=$env{'form.checkstale'}",
+ text=>'Results',
+ faq=>273,
+ bug=>'Instructor Interface'});
+ &verifycontent($r,$env{'form.checkstale'});
+ } else {
+ &contentverifyform($r);
+ }
} elsif ($allowed && $env{'form.listsymbs'}) {
&init_breadcrumbs('listsymbs','List Content IDs');
&list_symbs($r);
+ } elsif ($allowed && $env{'form.shorturls'}) {
+ &init_breadcrumbs('shorturls','Set/Display Shortened URLs','Docs_Short_URLs');
+ &short_urls($r,$canedit);
} elsif ($allowed && $env{'form.docslog'}) {
&init_breadcrumbs('docslog','Show Log');
my $folder = $env{'form.folder'};
@@ -5282,6 +5469,26 @@ sub handler {
'forcesupplement','forcestandard',
'tools','symb','command','supppath']);
+ foreach my $item ('forcesupplement','forcestandard','tools') {
+ next if ($env{'form.'.$item} eq '');
+ unless ($env{'form.'.$item} eq '1') {
+ delete($env{'form.'.$item});
+ }
+ }
+
+ if ($env{'form.command'}) {
+ unless ($env{'form.command'} =~ /^(direct|directnav|editdocs|editsupp|contents|home)$/) {
+ delete($env{'form.command'});
+ }
+ }
+
+ if ($env{'form.symb'}) {
+ my ($mapurl,$id,$resurl) = &Apache::lonnet::decode_symb($env{'form.symb'});
+ unless (($id =~ /^\d+$/) && (&Apache::lonnet::is_on_map($resurl))) {
+ delete($env{'form.symb'});
+ }
+ }
+
# standard=1: this is a "new-style" course with an uploaded map as top level
# standard=2: this is a "old-style" course, and there is nothing we can do
@@ -5304,6 +5511,38 @@ sub handler {
my $toolsflag=0;
if ($env{'form.tools'}) { $toolsflag=1; }
+ if ($env{'form.folderpath'} ne '') {
+ my @items = split(/\&/,$env{'form.folderpath'});
+ my $badpath;
+ for (my $i=0; $i<@items; $i++) {
+ my $odd = $i%2;
+ if (($odd) && (!$supplementalflag) && ($items[$i] !~ /^[^:]*:(|\d+):(|1):(|1):(|1):(|1)$/)) {
+ $badpath = 1;
+ } elsif ((!$odd) && ($items[$i] !~ /^(default|supplemental)(|_\d+)$/)) {
+ $badpath = 1;
+ }
+ last if ($badpath);
+ }
+ if ($badpath) {
+ delete($env{'form.folderpath'});
+ }
+ }
+
+ if ($env{'form.supppath'} ne '') {
+ my @items = split(/\&/,$env{'form.supppath'});
+ my $badpath;
+ for (my $i=0; $i<@items; $i++) {
+ my $odd = $i%2;
+ if ((!$odd) && ($items[$i] !~ /^supplemental(|_\d+)$/)) {
+ $badpath = 1;
+ }
+ last if ($badpath);
+ }
+ if ($badpath) {
+ delete($env{'form.supppath'});
+ }
+ }
+
my $script='';
my $showdoc=0;
my $addentries = {};
@@ -5488,7 +5727,7 @@ sub handler {
}
}
my $tabidstr = join("','",@tabids);
- %ltitools = &Apache::lonnet::get_domain_ltitools($coursedom);
+ %ltitools = &Apache::lonnet::get_domain_lti($coursedom,'consumer');
my $posslti = keys(%ltitools);
my $hostname = $r->hostname();
$script .= &editing_js($udom,$uname,$supplementalflag,$coursedom,$coursenum,$posslti,
@@ -5576,6 +5815,7 @@ sub handler {
undef($hadchanges);
$uploadphase = &process_file_upload(\$upload_output,$coursenum,$coursedom,
\%allfiles,\%codebase,$context,$crstype);
+ undef($navmap);
if ($hadchanges) {
&mark_hash_old();
}
@@ -6375,8 +6615,10 @@ unless ($container eq 'page') {
$r->print(''.$error.' ');
}
if ($hadchanges) {
- &mark_hash_old();
- }
+ unless (&is_hash_old()) {
+ &mark_hash_old();
+ }
+ }
&changewarning($r,'');
}
@@ -6574,6 +6816,7 @@ my %suporderhash = (
sub embedded_form_elems {
my ($phase,$primaryurl,$newidx) = @_;
my $folderpath = &HTML::Entities::encode($env{'form.folderpath'},'<>&"');
+ $newidx =~s /\D+//g;
return <
@@ -6594,7 +6837,11 @@ sub embedded_destination {
} elsif ($folder =~ /^(default|supplemental)_(\d+)$/) {
$destination .= $2.'/';
}
- $destination .= $env{'form.newidx'};
+ my $newidx = $env{'form.newidx'};
+ $newidx =~s /\D+//g;
+ if ($newidx) {
+ $destination .= $newidx;
+ }
my $dir_root = '/userfiles';
return ($destination,$dir_root);
}
@@ -6620,6 +6867,9 @@ sub decompression_info {
}
unshift(@hiddens,$pathitem);
foreach my $item (@hiddens) {
+ if ($item eq 'newidx') {
+ next if ($env{'form.'.$item} =~ /\D/);
+ }
if ($env{'form.'.$item}) {
$hiddenelem .= ''."\n";
@@ -6732,6 +6982,7 @@ sub generate_admin_menu {
'vc' => 'Verify Content',
'cv' => 'Check/Set Resource Versions',
'ls' => 'List Resource Identifiers',
+ 'ct' => 'Display/Set Shortened URLs for Deep-linking',
'imse' => 'Export contents to IMS Archive',
'dcd' => "Copy $crstype Content to Authoring Space",
);
@@ -6782,6 +7033,13 @@ sub generate_admin_menu {
icon => 'symbs.png',
linktitle => "List the unique identifier used for each resource instance in your $lc_crstype"
},
+ { linktext => $lt{'ct'},
+ url => "javascript:injectData(document.courseverify,'dummy','shorturls','$lt{'ct'}')",
+ permission => 'F',
+ help => 'Docs_Short_URLs',
+ icon => 'shorturls.png',
+ linktitle => "Set shortened URLs for a resource or folder in your $lc_crstype for use in deep-linking"
+ },
]
});
if ($canedit) {
@@ -6990,8 +7248,13 @@ sub editing_js {
} else {
$url = $res;
}
- $backtourl = &HTML::Entities::encode(&Apache::lonnet::clutter($url),'<>&"').'?symb='.
- &HTML::Entities::encode($caller,'<>&"');
+ $backtourl = &HTML::Entities::encode(&Apache::lonnet::clutter($url),'<>&"');
+ if ($backtourl =~ m{^\Q/uploaded/$coursedom/$coursenum/\Edefault_\d+\.sequence$}) {
+ $backtourl .= '?navmap=1';
+ } else {
+ $backtourl .= '?symb='.
+ &HTML::Entities::encode($caller,'<>&"');
+ }
if ($backtourl =~ m{^\Q/public/$coursedom/$coursenum/syllabus\E}) {
if (($ENV{'SERVER_PORT'} == 443) &&
($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) {
@@ -8712,7 +8975,9 @@ check on this
Verify Content
-=item devalidateversioncache() & checkversions()
+=item devalidateversioncache()
+
+=item checkversions()
Check Versions
|