'.
@@ -1168,13 +1217,19 @@ sub update_paste_buffer {
# Construct identifiers for current contents of user's paste buffer
if (@currpaste) {
foreach my $suffix (@currpaste) {
- my $cid = $env{'docs.markedcopy_crs_'.$suffix};
- my $url = $env{'docs.markedcopy_url_'.$suffix};
- my $mapidx = $env{'docs.markedcopy_map_'.$suffix};
- if (($cid =~ /^$match_domain(?:_)$match_courseid$/) &&
- ($url ne '')) {
- $pasteurls{$cid.'_'.$url.'_'.$mapidx} = 1;
- }
+ my $cid = $env{'docs.markedcopy_crs_'.$suffix};
+ my $url = $env{'docs.markedcopy_url_'.$suffix};
+ my $mapidx = $env{'docs.markedcopy_map_'.$suffix};
+ if (($cid =~ /^$match_domain(?:_)$match_courseid$/) &&
+ ($url ne '')) {
+ if ($url eq '/res/lib/templates/simpleproblem.problem') {
+ $pasteurls{$cid.'_'.$mapidx} = 1;
+ } elsif ($url =~ m{^/res/$match_domain/$match_username/}) {
+ $pasteurls{$url} = 1;
+ } else {
+ $pasteurls{$cid.'_'.$url} = 1;
+ }
+ }
}
}
@@ -1183,7 +1238,7 @@ sub update_paste_buffer {
my @pathitems = split(/\&/,$env{'form.folderpath'});
my @folderconf = split(/\:/,$pathitems[-1]);
- my $ispage = $folderconf[4];
+ my $ispage = $folderconf[5];
foreach my $item (@possibles) {
my ($orderidx,$cmd) = split(/:/,$item);
@@ -1196,7 +1251,13 @@ sub update_paste_buffer {
$env{'form.folderpath'},\%curr_groups);
next if ($denied{'copy'});
$url=~s{http(:|:)//https(:|:)//}{https$2//};
- next if (exists($pasteurls{$coursedom.'_'.$coursenum.'_'.$mapidx}));
+ if ($url eq '/res/lib/templates/simpleproblem.problem') {
+ next if (exists($pasteurls{$coursedom.'_'.$coursenum.'_'.$mapidx}));
+ } elsif ($url =~ m{^/res/$match_domain/$match_username/}) {
+ next if (exists($pasteurls{$url}));
+ } else {
+ next if (exists($pasteurls{$coursedom.'_'.$coursenum.'_'.$url}));
+ }
my ($suffix,$errortxt,$locknotfreed) =
&new_timebased_suffix($env{'user.domain'},$env{'user.name'},'paste');
if ($suffix ne '') {
@@ -1741,7 +1802,7 @@ sub do_paste_from_buffer {
%msgs = &Apache::lonlocal::texthash (
notinsupp => 'Paste failed: content type is not supported within Supplemental Content',
notincrs => 'Paste failed: Item is from a different course which you do not have rights to edit.',
- notindom => 'Paste failed: Item is an external tool from a course in a different donain.',
+ notindom => 'Paste failed: Item is an external tool from a course in a different domain.',
duplicate => 'Paste failed: only one instance of a particular published sequence or page is allowed within each course.',
);
@@ -1770,14 +1831,7 @@ sub do_paste_from_buffer {
# Retrieve information about all course maps in main content area
my $allmaps = {};
- if ($folder =~ /^default/) {
- $allmaps =
- &Apache::loncommon::allmaps_incourse($coursedom,$coursenum,
- $env{"course.$env{'request.course.id'}.home"},
- $env{'request.course.id'});
- }
-
- my (@toclear,%mapurls,%lockerrs,%msgerrs,%results);
+ my (@toclear,%mapurls,%lockerrs,%msgerrs,%results,$donechk);
# Loop over the items to paste
foreach my $suffix (@dopaste) {
@@ -1795,6 +1849,13 @@ sub do_paste_from_buffer {
if ($is_map{$suffix}) {
# If pasting a map, check if map contains other maps
my (%hierarchy,%titles);
+ if (($folder =~ /^default/) && (!$donechk)) {
+ $allmaps =
+ &Apache::loncommon::allmaps_incourse($coursedom,$coursenum,
+ $env{"course.$env{'request.course.id'}.home"},
+ $env{'request.course.id'});
+ $donechk = 1;
+ }
&contained_map_check($url,$folder,$coursenum,$coursedom,
\%removefrommap,\%removeparam,\%addedmaps,
\%hierarchy,\%titles,$allmaps);
@@ -1852,13 +1913,18 @@ sub do_paste_from_buffer {
}
if ($url=~ m{/(bulletinboard|smppg|ext\.tool)$}) {
my $prefix = $1;
- my $fromothercrs;
+ my $fromothercrs;
#need to copy the db contents to a new one, unless this is a move.
my %info = (
src => $url,
cdom => $coursedom,
cnum => $coursenum,
);
+ if ($prefix eq 'ext.tool') {
+ if ($prefixchg{$suffix} eq 'docstosupp') {
+ $info{'delgradable'} = 1;
+ }
+ }
if (($srcdom{$suffix} =~ /^$match_domain$/) && ($srcnum{$suffix} =~ /^$match_courseid$/)) {
unless (($srcdom{$suffix} eq $coursedom) && ($srcnum{$suffix} eq $coursenum)) {
$fromothercrs = 1;
@@ -1950,6 +2016,18 @@ sub do_paste_from_buffer {
©_templated_files($url,$srcdom{$suffix},$srcnum{$suffix},$srcmapidx{$suffix},
$coursedom,$coursenum,$template,$newidx,"$folder.$container");
}
+ } elsif ($url =~ /ext\.tool$/) {
+ if (($newidx) && ($folder=~/^default/)) {
+ my $marker = (split(m{/},$url))[4];
+ my %toolsettings = &Apache::lonnet::dump('exttool_'.$marker,$coursedom,$coursenum);
+ my $val = 'no';
+ if ($toolsettings{'gradable'}) {
+ $val = 'yes';
+ }
+ &LONCAPA::map::storeparameter($newidx,'parameter_0_gradable',$val,
+ 'string_yesno');
+ &remember_parms($newidx,'gradable','set',$val);
+ }
}
$LONCAPA::map::resources[$newidx]=$title.':'.&LONCAPA::map::qtunescape($url).
':'.$ext.':normal:res';
@@ -2198,6 +2276,9 @@ sub dbcopy {
}
}
$db_name =~ s{_\d*$ }{_$suffix}x;
+ if (($prefix eq 'exttool') && ($dbref->{'delgradable'}) && ($contents{'gradable'})) {
+ delete($contents{'gradable'});
+ }
$result=&Apache::lonnet::put($db_name,\%contents,
$coursedom,$coursenum);
if ($result eq 'ok') {
@@ -2260,7 +2341,9 @@ sub copy_templated_files {
my @simpleprobqtypes = qw(radio option string essay numerical);
my $qtype=$srcparms{$srcprefix.'questiontype'};
if (grep(/^\Q$qtype\E$/,@simpleprobqtypes)) {
- my %newdata;
+ my %newdata = (
+ $newprefix.'questiontype' => $qtype,
+ );
foreach my $type (@simpleprobqtypes) {
if ($type eq $qtype) {
$newdata{"$weightprefix.$type.weight"}=1;
@@ -2482,16 +2565,38 @@ sub url_paste_fixups {
$changed = 1;
}
}
- } elsif ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/.+$}) {
+ } elsif ($ressrc =~ m{^/adm/($match_domain)/($match_courseid)/(.+)$}) {
next if ($skip);
my $srcdom = $1;
my $srcnum = $2;
+ my $rem = $3;
+ my ($is_exttool,$exttoolchg);
+ if ($rem =~ m{\d+/ext\.tool$}) {
+ $is_exttool = 1;
+ }
if (($srcdom ne $cdom) || ($srcnum ne $cnum)) {
$rewrites->{$oldurl}{$id} = $ressrc;
$dbcopies->{$oldurl}{$id}{'src'} = $ressrc;
$dbcopies->{$oldurl}{$id}{'cdom'} = $srcdom;
$dbcopies->{$oldurl}{$id}{'cnum'} = $srcnum;
$changed = 1;
+ if ($is_exttool) {
+ $exttoolchg = 1;
+ }
+ } elsif (($rem =~ m{\d+/ext\.tool$}) &&
+ ($env{'form.docs.markedcopy_options'} ne 'move')) {
+ $dbcopies->{$oldurl}{$id}{'src'} = $ressrc;
+ $dbcopies->{$oldurl}{$id}{'cdom'} = $srcdom;
+ $dbcopies->{$oldurl}{$id}{'cnum'} = $srcnum;
+ $changed = 1;
+ $exttoolchg = 1;
+ }
+ if (($is_exttool) && ($prefixchg)) {
+ if ($oldurl =~ m{^/uploaded/$match_domain/$match_courseid/default}) {
+ if ($exttoolchg) {
+ $dbcopies->{$oldurl}{$id}{'delgradable'} = 1;
+ }
+ }
}
} elsif ($ressrc =~ m{^/adm/$match_domain/$match_username/\d+/(smppg|bulletinboard)$}) {
if (($fromcdom ne $cdom) || ($fromcnum ne $cnum) ||
@@ -2712,9 +2817,7 @@ sub apply_fixups {
}
}
if (ref($resdatacopy{$key}) eq 'HASH') {
- if ($newsubdir{$key}) {
-
- }
+ my ($gotnewmapname,$newmapname,$srcfolder,$srccontainer);
foreach my $idx (keys(%{$resdatacopy{$key}})) {
if (ref($resdatacopy{$key}{$idx}) eq 'HASH') {
my $srcurl = $resdatacopy{$key}{$idx}{'src'};
@@ -2724,15 +2827,18 @@ sub apply_fixups {
($resdatacopy{$key}{$idx}{'cnum'} =~ /^$match_courseid$/)) {
my $srcdom = $resdatacopy{$key}{$idx}{'cdom'};
my $srcnum = $resdatacopy{$key}{$idx}{'cnum'};
- my ($newmapname) = ($key =~ m{/([^/]+)$});
- my ($srcfolder,$srccontainer) = split(/\./,$newmapname);
+ unless ($gotnewmapname) {
+ ($newmapname) = ($key =~ m{/([^/]+)$});
+ ($srcfolder,$srccontainer) = split(/\./,$newmapname);
+ if ($newsubdir{$key}) {
+ $newmapname =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir{$key}/;
+ }
+ $gotnewmapname = 1;
+ }
my $srcmapinfo = $srcfolder.':'.$idx;
if ($srccontainer eq 'page') {
$srcmapinfo .= ':1';
}
- if ($newsubdir{$key}) {
- $newmapname =~ s/^((?:default|supplemental)_)(\d+)/$1$newsubdir{$key}/;
- }
©_templated_files($srcurl,$srcdom,$srcnum,$srcmapinfo,$cdom,
$cnum,$template,$idx,$newmapname);
}
@@ -2755,7 +2861,8 @@ sub apply_fixups {
}
}
}
- for (my $i=0; $i<@LONCAPA::map::order; $i++) {
+ my $total = scalar(@LONCAPA::map::order) - 1;
+ for (my $i=$total; $i>=0; $i--) {
my $idx = $LONCAPA::map::order[$i];
if (defined($LONCAPA::map::resources[$idx])) {
my $changed;
@@ -2765,7 +2872,7 @@ sub apply_fixups {
splice(@LONCAPA::map::order,$i,1);
if (ref($currparam{$idx}) eq 'ARRAY') {
foreach my $name (@{$currparam{$idx}}) {
- &LONCAPA::map::delparameter($idx,'parameter_'.$name);
+ &LONCAPA::map::delparameter($idx,$name);
}
}
next;
@@ -2807,7 +2914,7 @@ sub apply_fixups {
foreach my $idx (keys(%remparam)) {
if (ref($remparam{$idx}) eq 'ARRAY') {
foreach my $name (@{$remparam{$idx}}) {
- &LONCAPA::map::delparameter($idx,'parameter_'.$name);
+ &LONCAPA::map::delparameter($idx,$name);
}
}
}
@@ -4050,11 +4157,19 @@ END
my ($editlink,$extresform,$anchor,$hiddenres,$nomodal);
my $orig_url = $url;
$orig_url=~s{http(:|:)//https(:|:)//}{https$2//};
- $url=~s{^http(|s)(:|:)//}{/adm/wrapper/ext/};
+ if ($container eq 'page') {
+ $url=~s{^http(|s)(:|:)//}{/ext/};
+ } else {
+ $url=~s{^http(|s)(:|:)//}{/adm/wrapper/ext/};
+ }
if (!$supplementalflag && $residx && $symb) {
if ((!$isfolder) && (!$ispage)) {
(undef,undef,$url)=&Apache::lonnet::decode_symb($symb);
- $url=&Apache::lonnet::clutter($url);
+ if (($url =~ m{^ext/}) && ($container eq 'page')) {
+ $url=&Apache::lonnet::clutter_with_no_wrapper($url);
+ } else {
+ $url=&Apache::lonnet::clutter($url);
+ }
if ($url=~/^\/*uploaded\//) {
$url=~/\.(\w+)$/;
my $embstyle=&Apache::loncommon::fileembstyle($1);
@@ -4068,7 +4183,7 @@ END
} elsif ($url=~m{^(|/adm/wrapper)/ext/([^#]+)}) {
my $wrapped = $1;
my $exturl = $2;
- if ($wrapped eq '') {
+ if (($wrapped eq '') && ($container ne 'page')) {
$url='/adm/wrapper'.$url;
}
if (($ENV{'SERVER_PORT'} == 443) && ($exturl !~ /^https:/)) {
@@ -4079,19 +4194,18 @@ END
} elsif ($url eq "/public/$coursedom/$coursenum/syllabus") {
if (($ENV{'SERVER_PORT'} == 443) &&
($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) {
- $url .= '?usehttp=1';
+ unless (&Apache::lonnet::uses_sts()) {
+ $url .= '?usehttp=1';
+ }
$nomodal = 1;
}
}
if (&Apache::lonnet::symbverify($symb,$url)) {
my $shownsymb = $symb;
if ($isexternal) {
- if ($url =~ /^([^#]+)#([^#]+)$/) {
- $url = $1;
- $anchor = $2;
- if ($symb =~ m{^([^#]+)\Q#$anchor\E$}) {
- $shownsymb = $1.&escape('#').$anchor;
- }
+ $url =~ s/\#[^#]+$//;
+ if ($container eq 'page') {
+ $url = &Apache::lonnet::clutter($url);
}
}
unless ($env{'request.role.adv'}) {
@@ -4104,7 +4218,7 @@ END
}
}
if ($url ne '') {
- $url.=(($url=~/\?/)?'&':'?').'symb='.&HTML::Entities::encode($shownsymb,'"<>&');
+ $url.=(($url=~/\?/)?'&':'?').'symb='.&escape($shownsymb);
}
} elsif (!$env{'request.role.adv'}) {
my $checkencrypt;
@@ -4125,7 +4239,7 @@ END
my $shownsymb = &Apache::lonenc::encrypted($symb);
my $shownurl = &Apache::lonenc::encrypted($url);
if (&Apache::lonnet::symbverify($shownsymb,$shownurl)) {
- $url = $shownurl.(($shownurl=~/\?/)?'&':'?').'symb='.&HTML::Entities::encode($shownsymb,'"<>&');
+ $url = $shownurl.(($shownurl=~/\?/)?'&':'?').'symb='.&escape($shownsymb);
if ($env{'request.enc'} ne '') {
delete($env{'request.enc'});
}
@@ -4145,8 +4259,11 @@ END
$url = $1;
$anchor = $2;
if (($url =~ m{^(|/adm/wrapper)/ext/(?!https:)}) && ($ENV{'SERVER_PORT'} == 443)) {
- if ($hostname ne '') {
- $url = 'http://'.$hostname.$url;
+ unless (&Apache::lonnet::uses_sts()) {
+ if ($hostname ne '') {
+ $url = 'http://'.$hostname.$url;
+ }
+ $url .= (($url =~ /\?/) ? '&':'?').'usehttp=1';
}
$nomodal = 1;
}
@@ -4154,10 +4271,12 @@ END
} elsif ($url =~ m{^\Q/public/$coursedom/$coursenum/syllabus\E}) {
if (($ENV{'SERVER_PORT'} == 443) &&
($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) {
- if ($hostname ne '') {
- $url = 'http://'.$hostname.$url;
+ unless (&Apache::lonnet::uses_sts()) {
+ if ($hostname ne '') {
+ $url = 'http://'.$hostname.$url;
+ }
+ $url .= (($url =~ /\?/) ? '&':'?').'usehttp=1';
}
- $url .= (($url =~ /\?/) ? '&':'?').'usehttp=1';
$nomodal = 1;
}
}
@@ -4311,7 +4430,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.=''.
@@ -4338,8 +4457,7 @@ $form_end;
} else {
$link = $url;
}
- $link = &js_escape($link.(($url=~/\?/)?'&':'?').'inhibitmenu=yes'.
- (($anchor ne '')?$anchor:''));
+ $link = &js_escape($link.(($url=~/\?/)?'&':'?').'inhibitmenu=yes'.$anchor);
if ($nomodal) {
$line.=''.
'';
@@ -4588,7 +4706,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 +4721,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 +4770,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 +4784,9 @@ sub checkonthis {
} else {
$r->print(''.&mt('access denied').'');
}
+ if (($updated) && ($result ne 'ok')) {
+ $r->print(' '.&mt('Outdated copy removed'));
+ }
}
}
}
@@ -4706,9 +4839,71 @@ 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::get_requested_shorturls($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 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) = @_;
+ 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'));
@@ -4729,7 +4924,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 +4932,6 @@ sub verifycontent {
$r->print(&endContentScreen());
}
-
sub devalidateversioncache {
my $src=shift;
&Apache::lonnet::devalidate_cache_new('courseresversion',$env{'request.course.id'}.'_'.
@@ -5057,13 +5251,17 @@ sub changewarning {
if (!defined($message)) {
$message='Changes will become active for your current session after [_1], or the next time you log in.';
}
+ my $windowname = 'loncapaclient';
+ if ($env{'request.lti.login'}) {
+ $windowname .= 'lti';
+ }
$r->print("\n\n".
''."\n".
-' |