--- loncom/interface/londocs.pm 2014/04/02 22:21:28 1.484.2.52
+++ loncom/interface/londocs.pm 2016/08/06 21:53:02 1.484.2.64
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Documents
#
-# $Id: londocs.pm,v 1.484.2.52 2014/04/02 22:21:28 raeburn Exp $
+# $Id: londocs.pm,v 1.484.2.64 2016/08/06 21:53:02 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -652,7 +652,7 @@ sub group_import {
} else {
$fname =~ s/\W/_/g;
}
- if (length($fname > 15)) {
+ if (length($fname) > 15) {
$fname = substr($fname,0,14);
}
my $initialtext = &mt('Replace with your own content.');
@@ -977,7 +977,7 @@ sub docs_change_log {
sub update_paste_buffer {
my ($coursenum,$coursedom,$folder) = @_;
- my (@possibles,%removals,%cuts);
+ my (@possibles,%removals,%cuts,$output);
if ($env{'form.multiremove'}) {
$env{'form.multiremove'} =~ s/,$//;
map { $removals{$_} = 1; } split(/,/,$env{'form.multiremove'});
@@ -1045,10 +1045,12 @@ sub update_paste_buffer {
next if (exists($pasteurls{$coursedom.'_'.$coursenum.'_'.$url}));
my ($suffix,$errortxt,$locknotfreed) =
&new_timebased_suffix($env{'user.domain'},$env{'user.name'},'paste');
- push(@newpaste,$suffix);
- if ($locknotfreed) {
- return $locknotfreed;
- last;
+ if ($suffix ne '') {
+ push(@newpaste,$suffix);
+ } else {
+ if ($locknotfreed) {
+ return $locknotfreed;
+ }
}
if (&is_supplemental_title($title)) {
&Apache::lonnet::appenv({'docs.markedcopy_supplemental_'.$suffix => $title});
@@ -1082,13 +1084,17 @@ sub update_paste_buffer {
}
}
}
+ if ($locknotfreed) {
+ $output = $locknotfreed;
+ last;
+ }
}
if (@newpaste) {
$addtoenv{'docs.markedcopies'} = join(',',(@currpaste,@newpaste));
}
&Apache::lonnet::appenv(\%addtoenv);
delete($env{'form.markcopy'});
- return;
+ return $output;
}
sub recurse_uploaded_maps {
@@ -1191,10 +1197,14 @@ sub print_paste_buffer {
$icon = &Apache::loncommon::lonhttpdurl($r->dir_config('lonIconsURL'));
$icon .= '/navmap.folder.closed.gif';
}
+ my $title = $env{'docs.markedcopy_title_'.$suffix};
+ if ($title eq '') {
+ ($title) = ($url =~ m{/([^/]+)$});
+ }
$buffer = ''.
': '.
&Apache::loncommon::parse_supplemental_title(
- &LONCAPA::map::qtescape($env{'docs.markedcopy_title_'.$suffix}));
+ &LONCAPA::map::qtescape($title));
}
$pasteitems .= '
';
my ($options,$onclick);
@@ -1343,29 +1353,34 @@ sub supp_pasteable {
}
sub paste_popup_js {
- my %lt = &Apache::lonlocal::texthash(
+ my %html_js_lt = &Apache::lonlocal::texthash(
show => 'Show Options',
hide => 'Hide Options',
+ );
+ my %js_lt = &Apache::lonlocal::texthash(
none => 'No items selected from clipboard.',
);
+ &html_escape(\%html_js_lt);
+ &js_escape(\%html_js_lt);
+ &js_escape(\%js_lt);
return <<"END";
function showPasteOptions(suffix) {
document.getElementById('pasteoptions_'+suffix).style.display='block';
- document.getElementById('pasteoptionstext_'+suffix).innerHTML = ' $lt{'hide'}';
+ document.getElementById('pasteoptionstext_'+suffix).innerHTML = ' $html_js_lt{'hide'}';
return;
}
function hidePasteOptions(suffix) {
document.getElementById('pasteoptions_'+suffix).style.display='none';
- document.getElementById('pasteoptionstext_'+suffix).innerHTML =' $lt{'show'}';
+ document.getElementById('pasteoptionstext_'+suffix).innerHTML =' $html_js_lt{'show'}';
return;
}
function showOptions(caller,suffix) {
if (document.getElementById('pasteoptionstext_'+suffix)) {
if (caller.checked) {
- document.getElementById('pasteoptionstext_'+suffix).innerHTML =' $lt{'show'}';
+ document.getElementById('pasteoptionstext_'+suffix).innerHTML =' $html_js_lt{'show'}';
} else {
document.getElementById('pasteoptionstext_'+suffix).innerHTML ='';
}
@@ -1394,7 +1409,7 @@ function validateClipboard() {
if (numchk > 0) {
return true;
} else {
- alert("$lt{'none'}");
+ alert("$js_lt{'none'}");
return false;
}
}
@@ -2603,26 +2618,45 @@ sub update_parameter {
}
return $haschanges;
} else {
- return 0 if ($env{'form.changeparms'} !~ /^($valid_parameters_re)$/);
+ my $haschanges = 0;
+ return $haschanges if ($env{'form.changeparms'} !~ /^($valid_parameters_re)$/);
my $which = $env{'form.changeparms'};
my $idx = $env{'form.setparms'};
+ my $oldvalue = 0;
+ my $newvalue = 0;
+ my $current = (&LONCAPA::map::getparameter($idx,'parameter_'.$which))[0];
+ if ($which eq 'randompick') {
+ if ($current =~ /^(\d+)$/) {
+ $oldvalue = $1;
+ }
+ } elsif ($current =~ /^yes$/i) {
+ $oldvalue = 1;
+ }
if ($env{'form.'.$which.'_'.$idx}) {
- my $value = ($which eq 'randompick') ? $env{'form.rpicknum_'.$idx}
- : 'yes';
- &LONCAPA::map::storeparameter($idx, 'parameter_'.$which, $value,
- $parameter_type{$which});
- &remember_parms($idx,$which,'set',$value);
- } else {
- &LONCAPA::map::delparameter($idx,'parameter_'.$which);
-
- &remember_parms($idx,$which,'del');
+ $newvalue = ($which eq 'randompick') ? $env{'form.rpicknum_'.$idx}
+ : 1;
}
- return 1;
+ if ($oldvalue ne $newvalue) {
+ $haschanges = 1;
+ if ($newvalue) {
+ my $storeval = 'yes';
+ if ($which eq 'randompick') {
+ $storeval = $newvalue;
+ }
+ &LONCAPA::map::storeparameter($idx, 'parameter_'.$which, $storeval,
+ $parameter_type{$which});
+ &remember_parms($idx,$which,'set',$storeval);
+ } else {
+ &LONCAPA::map::delparameter($idx,'parameter_'.$which);
+ &remember_parms($idx,$which,'del');
+ }
+ }
+ return $haschanges;
}
+ return;
}
-
sub handle_edit_cmd {
my ($coursenum,$coursedom) =@_;
if ($env{'form.cmd'} eq '') {
@@ -2714,7 +2748,7 @@ sub editor {
&snapshotbefore();
if (&update_parameter()) {
- ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container);
+ ($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container,1);
return $errtext if ($fatal);
}
@@ -2776,9 +2810,9 @@ sub editor {
$r->print($upload_output);
# Rename, cut, copy or remove a single resource
- if (&handle_edit_cmd()) {
+ if (&handle_edit_cmd($coursenum,$coursedom)) {
my $contentchg;
- if ($env{'form.cmd'} =~ m{^(del|cut)_}) {
+ if ($env{'form.cmd'} =~ m{^(remove|cut)_}) {
$contentchg = 1;
}
($errtext,$fatal)=&storemap($coursenum,$coursedom,$folder.'.'.$container,$contentchg);
@@ -2810,7 +2844,7 @@ sub editor {
my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$res]);
$name=&LONCAPA::map::qtescape($name);
$url=&LONCAPA::map::qtescape($url);
- next unless ($name && $url);
+ next unless $url;
my %denied =
&action_restrictions($coursenum,$coursedom,$url,
$env{'form.folderpath'},\%curr_groups);
@@ -3358,6 +3392,7 @@ sub entryline {
$renametitle=~s/\\/\\\\/g;
$renametitle=~s/\"\;/\\\"/g;
+ $renametitle=~s/"/%22/g;
$renametitle=~s/ /%20/g;
$oldtitle = $renametitle;
$renametitle=~s/\'\;/\\\'/g;
@@ -3445,6 +3480,7 @@ END
$currgroups);
my ($copylink,$cutlink,$removelink);
my $skip_confirm = 0;
+ my $confirm_removal = 0;
if ( $folder =~ /^supplemental/
|| ($url =~ m{( /smppg$
|/syllabus$
@@ -3455,6 +3491,10 @@ END
|| $isexternal) {
$skip_confirm = 1;
}
+ if (($url=~m|/+uploaded/\Q$coursedom\E/\Q$coursenum\E/|) &&
+ ($url!~/$LONCAPA::assess_page_seq_re/)) {
+ $confirm_removal = 1;
+ }
if ($denied{'copy'}) {
$copylink=(<
$form_common
+
$lt{'rm'}
$form_end
ENDREM
@@ -3825,6 +3866,7 @@ sub new_timebased_suffix {
if ($type eq 'paste') {
$prefix = $type;
$namespace = 'courseeditor';
+ $idtype = 'addcode';
} elsif ($type eq 'map') {
$prefix = 'docs';
if ($area eq 'supplemental') {
@@ -3836,9 +3878,8 @@ sub new_timebased_suffix {
$prefix = $type;
$namespace = 'templated';
}
- $idtype = 'concat';
my ($suffix,$freedlock,$error) =
- &Apache::lonnet::get_timebased_id($prefix,'num',$namespace,$dom,$num);
+ &Apache::lonnet::get_timebased_id($prefix,'num',$namespace,$dom,$num,$idtype);
if (!$suffix) {
if ($type eq 'paste') {
$errtext = &mt('Failed to acquire a unique timestamp-based suffix when adding to the paste buffer.');
@@ -3858,9 +3899,19 @@ sub new_timebased_suffix {
'
'.
&mt('There was a problem removing a lockfile.').' ';
if ($type eq 'paste') {
- &mt('This will prevent use of the paste buffer until th next log-in.');
+ if ($freedlock eq 'nolock') {
+ $locknotfreed =
+ '
'.
+ &mt('A lockfile was not released when you added content to the clipboard earlier in this session.').' '.
+
+ &mt('As a result addition of items to the clipboard will be unavailable until your next log-in.');
+ } else {
+ $locknotfreed .=
+ &mt('This will prevent addition of items to the clipboard until your next log-in.');
+ }
} elsif ($type eq 'map') {
- &mt('This will prevent creation of additional folders or composite pages in this course.');
+ $locknotfreed .=
+ &mt('This will prevent creation of additional folders or composite pages in this course.');
} elsif ($type eq 'smppg') {
$locknotfreed .=
&mt('This will prevent creation of additional simple pages in this course.');
@@ -4505,12 +4556,8 @@ sub handler {
$allowed = &Apache::lonnet::allowed('mdc',$env{'request.course.id'});
}
- &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['chooseserver',
- 'inhibitmenu']);
- if ($allowed && $env{'form.chooseserver'}) {
- &choose_dump_server($r);
- return OK;
- } elsif ($allowed && $env{'form.verify'}) {
+ &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['inhibitmenu']);
+ if ($allowed && $env{'form.verify'}) {
&init_breadcrumbs('verify','Verify Content','Docs_Verify_Content');
&verifycontent($r);
} elsif ($allowed && $env{'form.listsymbs'}) {
@@ -4858,7 +4905,39 @@ sub handler {
'webctce4' => 'WebCT 4 Campus Edition',
);
# -----------------------------------------------------------------------------
+ # Calculate free quota space for a user or course.
+ my $quotatype = 'unofficial';
+ if ($crstype eq 'Community') {
+ $quotatype = 'community';
+ } elsif ($env{'course.'.$coursedom.'_'.$coursenum.'.internal.coursecode'}) {
+ $quotatype = 'official';
+ } elsif ($env{'course.'.$coursedom.'_'.$coursenum.'.internal.textbook'}) {
+ $quotatype = 'textbook';
+ }
+ my $disk_quota = &Apache::loncommon::get_user_quota($coursenum,$coursedom,
+ 'course',$quotatype); # expressed in MB
+ my $current_disk_usage = 0;
+ foreach my $subdir ('docs','supplemental') {
+ $current_disk_usage += &Apache::lonnet::diskusage($coursedom,$coursenum,
+ "userfiles/$subdir",1); # expressed in kB
+ }
+ my $free_space = 1024 * ((1024 * $disk_quota) - $current_disk_usage);
+ my $usage = $current_disk_usage/1024; # in MB
+ my $quota = $disk_quota;
+ my $percent;
+ if ($disk_quota == 0) {
+ $percent = 100.0;
+ } else {
+ $percent = 100*($current_disk_usage/$disk_quota);
+ }
+ $usage = sprintf("%.2f",$usage);
+ $quota = sprintf("%.2f",$quota);
+ $percent = sprintf("%.0f",$percent);
+ my $quotainfo = '
'.&mt('Currently using [_1] of the [_2] available.',
+ $percent.'%',$quota.' MB').'
';
+
my $fileupload=(<
FIUP
@@ -5463,7 +5542,7 @@ sub decompression_info {
my $docuname=$env{'course.'.$env{'request.course.id'}.'.num'};
my $container='sequence';
my ($pathitem,$hiddenelem);
- my @hiddens = ('newidx','comment','position','folderpath');
+ my @hiddens = ('newidx','comment','position','folderpath','archiveurl');
if ($env{'form.folderpath'} =~ /\:1$/) {
$container='page';
}
@@ -5471,7 +5550,7 @@ sub decompression_info {
foreach my $item (@hiddens) {
if ($env{'form.'.$item}) {
$hiddenelem .= ''."\n";
+ &HTML::Entities::encode($env{'form.'.$item},'<>&"').'" />'."\n";
}
}
return ($destination,$dir_root,$londocroot,$docudom,$docuname,$container,
@@ -5528,25 +5607,34 @@ sub remove_archive {
} else {
$delwarning = &mt('An error occurred retrieving the contents of the current folder.');
}
- $delwarning .= &mt('As a result the archive file has not been removed.');
+ $delwarning .= ' '.&mt('As a result the archive file has not been removed.');
} else {
my $currcmd = $env{'form.cmd'};
my $position = $env{'form.position'};
- if ($position > 0) {
- $env{'form.cmd'} = 'remove_'.$position;
- my ($title,$url,@rrest) =
- split(/:/,$LONCAPA::map::resources[$LONCAPA::map::order[$position]]);
- if (&handle_edit_cmd($docuname,$docudom)) {
- ($errtext,$fatal) = &storemap($docuname,$docudom,$map,1);
- if ($fatal) {
- if ($container eq 'page') {
- $delwarning = &mt('An error occurred updating the contents of the current page.');
+ my $archiveidx = $position;
+ if ($position > 0) {
+ if (($env{'form.autoextract_camtasia'}) && (scalar(@LONCAPA::map::order) == 2)) {
+ $archiveidx = $position-1;
+ }
+ $env{'form.cmd'} = 'remove_'.$archiveidx;
+ my ($title,$url,@rrest) =
+ split(/:/,$LONCAPA::map::resources[$LONCAPA::map::order[$archiveidx]]);
+ if ($url eq $env{'form.archiveurl'}) {
+ if (&handle_edit_cmd($docuname,$docudom)) {
+ ($errtext,$fatal) = &storemap($docuname,$docudom,$map,1);
+ if ($fatal) {
+ if ($container eq 'page') {
+ $delwarning = &mt('An error occurred updating the contents of the current page.');
+ } else {
+ $delwarning = &mt('An error occurred updating the contents of the current folder.');
+ }
} else {
- $delwarning = &mt('An error occurred updating the contents of the current folder.');
+ $delresult = &mt('Archive file removed.');
}
- } else {
- $delresult = &mt('Archive file removed.');
}
+ } else {
+ $delwarning .= &mt('Archive file had unexpected item number in folder.').
+ ' '.&mt('As a result the archive file has not been removed.');
}
}
$env{'form.cmd'} = $currcmd;
@@ -5749,7 +5837,7 @@ END
sub editing_js {
my ($udom,$uname,$supplementalflag) = @_;
- my %lt = &Apache::lonlocal::texthash(
+ my %js_lt = &Apache::lonlocal::texthash(
p_mnf => 'Name of New Folder',
t_mnf => 'New Folder',
p_mnp => 'Name of New Page',
@@ -5766,16 +5854,18 @@ sub editing_js {
p_mab_alrt2 => 'Please enter both user and domain in the format user:domain',
p_chn => 'New Title',
p_rmr1 => 'WARNING: Removing a resource makes associated grades and scores inaccessible!',
- p_rmr2a => 'Remove[_99]',
- p_rmr2b => '?[_99]',
- p_rmr3a => 'Remove those [_2]',
- p_rmr3b => 'items?[_2]',
+ p_rmr2a => 'Remove',
+ p_rmr2b => '?',
+ p_rmr3a => 'Remove those',
+ p_rmr3b => 'items?',
+ p_rmr4 => 'WARNING: Removing a resource uploaded to a course cannot be undone via "Undo Delete".',
+ p_rmr5 => 'Push "Cancel" and then use "Cut" instead if you might need to undo this change.',
p_ctr1a => 'WARNING: Cutting a resource makes associated grades and scores inaccessible!',
p_ctr1b => 'Grades remain inaccessible if resource is pasted into another folder.',
- p_ctr2a => 'Cut[_98]',
- p_ctr2b => '?[_98]',
- p_ctr3a => 'Cut those[_2]',
- p_ctr3b => 'items?[_2]',
+ p_ctr2a => 'Cut',
+ p_ctr2b => '?',
+ p_ctr3a => 'Cut those',
+ p_ctr3b => 'items?',
rpck => 'Enter number to pick (e.g., 3)',
imsfile => 'You must choose an IMS package for import',
imscms => 'You must select which Course Management System was the source of the IMS package',
@@ -5788,6 +5878,7 @@ sub editing_js {
noac => 'No actions selected.',
);
+ &js_escape(\%js_lt);
my $crstype = &Apache::loncommon::course_type();
my $docs_folderpath = &HTML::Entities::encode($env{'environment.internal.'.$env{'request.course.id'}.'.docs_folderpath.folderpath'},'<>&"');
my $main_container_page;
@@ -5809,6 +5900,7 @@ sub editing_js {
if (&Apache::lonnet::is_on_map($res)) {
$backtourl = &HTML::Entities::encode(&Apache::lonnet::clutter($res),'<>&"').'?symb='.
&HTML::Entities::encode($caller,'<>&"');
+ $backtourl = &Apache::loncommon::escape_single($backtourl);
} else {
$backtourl = '/adm/navmaps';
}
@@ -5831,7 +5923,7 @@ sub editing_js {
return <$lt{'more'}';
+ document.getElementById('more'+caller).innerHTML = ' $js_lt{'more'}';
} else {
document.getElementById('more'+caller).innerHTML = '';
}
@@ -6394,10 +6500,10 @@ function togglePick(caller,value) {
function toggleCheckUncheck(caller,more) {
if (more == 1) {
- document.getElementById('more'+caller).innerHTML = ' $lt{'less'}';
+ document.getElementById('more'+caller).innerHTML = ' $js_lt{'less'}';
document.getElementById('allfields'+caller).style.display='block';
} else {
- document.getElementById('more'+caller).innerHTML = ' $lt{'more'}';
+ document.getElementById('more'+caller).innerHTML = ' $js_lt{'more'}';
document.getElementById('allfields'+caller).style.display='none';
}
resize_scrollbox('contentscroll','1','1');
@@ -6439,6 +6545,7 @@ function checkSubmits() {
var doactions = multiActions();
var cutwarnings = 0;
var remwarnings = 0;
+ var removalinfo = 0;
if (doactions == 1) {
var remidxlist = document.cumulativeactions.allremoveidx.value;
if ((remidxlist != '') && (remidxlist != null)) {
@@ -6453,6 +6560,11 @@ function checkSubmits() {
remwarnings ++;
}
}
+ if (document.getElementById('confirm_removal_'+remidxs[i])) {
+ if (document.getElementById('confirm_removal_'+remidxs[i]).value == 1) {
+ removalinfo ++;
+ }
+ }
}
}
}
@@ -6551,14 +6663,19 @@ function checkSubmits() {
}
if (doactions == 1) {
if (numchanges > 0) {
- if ((cutwarnings > 0) || (remwarnings > 0)) {
+ if ((cutwarnings > 0) || (remwarnings > 0) || (removalinfo > 0)) {
if (remwarnings > 0) {
- if (!confirm('$lt{"p_rmr1"}\\n\\n$lt{"p_rmr3a"} '+remwarnings+' $lt{"p_rmr3b"}')) {
+ if (!confirm('$js_lt{"p_rmr1"}\\n\\n$js_lt{"p_rmr3a"} '+remwarnings+' $js_lt{"p_rmr3b"}')) {
+ return false;
+ }
+ }
+ if (removalinfo > 0) {
+ if (!confirm('$js_lt{"p_rmr4"}\\n$js_lt{"p_rmr5"}\\n\\n$js_lt{"p_rmr3a"} '+removalinfo+' $js_lt{"p_rmr3b"}')) {
return false;
}
}
if (cutwarnings > 0) {
- if (!confirm('$lt{"p_ctr1a"}\\n$lt{"p_ctr1b"}\\n\\n$lt{"p_ctr3a"} '+cutwarnings+' $lt{"p_ctr3b"}')) {
+ if (!confirm('$js_lt{"p_ctr1a"}\\n$js_lt{"p_ctr1b"}\\n\\n$js_lt{"p_ctr3a"} '+cutwarnings+' $js_lt{"p_ctr3b"}')) {
return false;
}
}
@@ -6574,12 +6691,12 @@ function checkSubmits() {
}
}
if ((dosettings == 1) && (doactions == 1)) {
- alert("$lt{'noor'}");
+ alert("$js_lt{'noor'}");
} else {
if (dosettings == 1) {
- alert("$lt{'noch'}");
+ alert("$js_lt{'noch'}");
} else {
- alert("$lt{'noac'}");
+ alert("$js_lt{'noac'}");
}
}
return false;
@@ -6694,13 +6811,19 @@ ENDINJECT
sub dump_switchserver_js {
my @hosts = @_;
- my %lt = &Apache::lonlocal::texthash(
+ my %js_lt = &Apache::lonlocal::texthash(
dump => 'Copying content to Authoring Space requires switching server.',
swit => 'Switch server?',
+ );
+ my %html_js_lt = &Apache::lonlocal::texthash(
+ swit => 'Switch server?',
duco => 'Copying Content to Authoring Space',
yone => 'You need to switch to a server housing an Authoring Space for which you are author or co-author.',
chos => 'Choose server',
);
+ &js_escape(\%js_lt);
+ &html_escape(\%html_js_lt);
+ &js_escape(\%html_js_lt);
my $role = $env{'request.role'};
my $js = <<"ENDSWJS";