[LON-CAPA-cvs] cvs: loncom /cgi archive.pl /interface domainprefs.pm loncommon.pm loncreateuser.pm lonmenu.pm /lonnet/perl lonnet.pm /publisher loncfile.pm
raeburn
raeburn at source.lon-capa.org
Mon May 20 22:57:17 EDT 2024
raeburn Tue May 21 02:57:17 2024 EDT
Modified files:
/loncom/interface domainprefs.pm loncreateuser.pm loncommon.pm
lonmenu.pm
/loncom/lonnet/perl lonnet.pm
/loncom/publisher loncfile.pm
/loncom/cgi archive.pl
Log:
- Bug 6990. Ability to download tarball of Authoring Space's files/directories.
- Support use of domain default and also override for individual author(s).
- Check if there is sufficient disk space to create archive file
- Each author may only have one archive request in process at a time
- Remove archive file after download
- Log archive creation and deletion actions in nohist_archivelog.db in
author's data directory.
-------------- next part --------------
Index: loncom/interface/domainprefs.pm
diff -u loncom/interface/domainprefs.pm:1.440 loncom/interface/domainprefs.pm:1.441
--- loncom/interface/domainprefs.pm:1.440 Wed May 1 15:18:58 2024
+++ loncom/interface/domainprefs.pm Tue May 21 02:57:15 2024
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Handler to set domain-wide configuration settings
#
-# $Id: domainprefs.pm,v 1.440 2024/05/01 15:18:58 raeburn Exp $
+# $Id: domainprefs.pm,v 1.441 2024/05/21 02:57:15 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -13637,6 +13637,7 @@
$shown = $titles{'none'};
}
} elsif ($key eq 'archive') {
+ $domdefaults{$key} = $confhash{$key};
$shown = ($confhash{$key} ? &mt('Yes') : &mt('No'));
}
$resulttext .= '<li>'.&mt('[_1] set to: [_2]',$titles{$key},$shown).'</li>';
Index: loncom/interface/loncreateuser.pm
diff -u loncom/interface/loncreateuser.pm:1.479 loncom/interface/loncreateuser.pm:1.480
--- loncom/interface/loncreateuser.pm:1.479 Wed May 1 21:23:20 2024
+++ loncom/interface/loncreateuser.pm Tue May 21 02:57:15 2024
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Create a user
#
-# $Id: loncreateuser.pm,v 1.479 2024/05/01 21:23:20 raeburn Exp $
+# $Id: loncreateuser.pm,v 1.480 2024/05/21 02:57:15 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -3378,7 +3378,7 @@
$changed{'webdav'} = &tool_admin('webdav',$newcustom{'webdav'},
\%changeHash,'authordefaults');
}
- if ($env{'for.customarchive'} == 1) {
+ if ($env{'form.customarchive'} == 1) {
$newcustom{'archive'} = $env{'form.authordefaults_archive'};
$changed{'archive'} = &tool_admin('archive',$newcustom{'archive'},
\%changeHash,'authordefaults');
@@ -3867,6 +3867,21 @@
$newenvhash{'environment.editors'} = 'edit,xml';
}
}
+ } elsif ($key eq 'archive') {
+ $newenvhash{'environment.author.'.$key} =
+ $changeHash{'author.'.$key};
+ if ($changeHash{'author.'.$key} ne '') {
+ $newenvhash{'environment.canarchive'} =
+ $changeHash{'author.'.$key};
+ } else {
+ unless ($got_domdefs) {
+ %domdefaults =
+ &Apache::lonnet::get_domain_defaults($env{'user.domain'});
+ $got_domdefs = 1;
+ }
+ $newenvhash{'environment.canarchive'} =
+ $domdefaults{'archive'};
+ }
} elsif ($key ne 'quota') {
$newenvhash{'environment.tools.'.$key} =
$changeHash{'tools.'.$key};
Index: loncom/interface/loncommon.pm
diff -u loncom/interface/loncommon.pm:1.1430 loncom/interface/loncommon.pm:1.1431
--- loncom/interface/loncommon.pm:1.1430 Sun Apr 14 18:45:57 2024
+++ loncom/interface/loncommon.pm Tue May 21 02:57:15 2024
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.1430 2024/04/14 18:45:57 raeburn Exp $
+# $Id: loncommon.pm,v 1.1431 2024/05/21 02:57:15 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -18072,6 +18072,12 @@
} else {
$userenv{'editors'} = 'edit,xml';
}
+ if ($userenv{'authorarchive'}) {
+ $userenv{'canarchive'} = 1;
+ } elsif (($userenv{'authorarchive'} eq '') &&
+ ($domdef{'archive'})) {
+ $userenv{'canarchive'} = 1;
+ }
}
$userenv{'canrequest.author'} =
Index: loncom/interface/lonmenu.pm
diff -u loncom/interface/lonmenu.pm:1.553 loncom/interface/lonmenu.pm:1.554
--- loncom/interface/lonmenu.pm:1.553 Tue May 14 15:53:17 2024
+++ loncom/interface/lonmenu.pm Tue May 21 02:57:16 2024
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Routines to control the menu
#
-# $Id: lonmenu.pm,v 1.553 2024/05/14 15:53:17 raeburn Exp $
+# $Id: lonmenu.pm,v 1.554 2024/05/21 02:57:16 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -1262,7 +1262,7 @@
s&7&1&del.png&Delete&dir[_3]&gocstr('/adm/cfile?action=delete','$esc_currdir')&Delete this Directory
ENDMENUITEMS
unless ($crsauthor_cstr) {
- if ($env{'environment.authorarchive'}) {
+ if ($env{'environment.canarchive'}) {
$menuitems .= (<<ENDMENUITEMS);
s&7&7&archive.png&Export&dir[_1]&gocstr('/adm/cfile?action=archive','$esc_currdir')&Export Authoring Space Archive
ENDMENUITEMS
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.1526 loncom/lonnet/perl/lonnet.pm:1.1527
--- loncom/lonnet/perl/lonnet.pm:1.1526 Wed May 1 12:06:25 2024
+++ loncom/lonnet/perl/lonnet.pm Tue May 21 02:57:16 2024
@@ -1,7 +1,7 @@
# The LearningOnline Network
# TCP networking package
#
-# $Id: lonnet.pm,v 1.1526 2024/05/01 12:06:25 raeburn Exp $
+# $Id: lonnet.pm,v 1.1527 2024/05/21 02:57:16 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -2802,7 +2802,7 @@
$domdefaults{'requestauthor'} = $domconfig{'requestauthor'};
}
if (ref($domconfig{'authordefaults'}) eq 'HASH') {
- foreach my $item ('nocodemirror','copyright','sourceavail','domcoordacc','editors') {
+ foreach my $item ('nocodemirror','copyright','sourceavail','domcoordacc','editors','archive') {
if ($item eq 'editors') {
if (ref($domconfig{'authordefaults'}{'editors'}) eq 'ARRAY') {
$domdefaults{$item} = join(',',@{$domconfig{'authordefaults'}{'editors'}});
@@ -5623,6 +5623,39 @@
return;
}
+sub authorarchivelog {
+ my ($hashref,$size,$filesdest,$action) = @_;
+ my $lonprtdir = $Apache::lonnet::perlvar{'lonPrtDir'};
+ my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
+ $filesdest =~ s{^\Q$lonprtdir/\E}{};
+ if ($filesdest =~ m{^($match_username)_($match_domain)_archive_(\d+_\d+_\d+(|[.\w]+))$}) {
+ my ($auname,$audom,$id) = ($1,$2,$3);
+ if (ref($hashref) eq 'HASH') {
+ my $namespace = 'archivelog';
+ my $dir;
+ if ($hashref->{dir} =~ m{^\Q$londocroot/priv/$audom/$auname\E(.*)$}) {
+ $dir = $1;
+ }
+ my $delflag = 0;
+ my %storehash = (
+ id => $id,
+ dir => $dir,
+ files => $hashref->{numfiles},
+ subdirs => $hashref->{numdirs},
+ bytes => $hashref->{bytes},
+ size => $size,
+ action => $action,
+ );
+ if ($action eq 'delete') {
+ $delflag = 1;
+ }
+ &write_log('author',$namespace,\%storehash,$delflag,$auname,
+ $audom,$auname,$audom);
+ }
+ }
+ return;
+}
+
sub get_course_adv_roles {
my ($cid,$codes) = @_;
$cid=$env{'request.course.id'} unless (defined($cid));
Index: loncom/publisher/loncfile.pm
diff -u loncom/publisher/loncfile.pm:1.128 loncom/publisher/loncfile.pm:1.129
--- loncom/publisher/loncfile.pm:1.128 Mon May 13 13:55:50 2024
+++ loncom/publisher/loncfile.pm Tue May 21 02:57:16 2024
@@ -9,7 +9,7 @@
# and displays a page showing the results of the action.
#
#
-# $Id: loncfile.pm,v 1.128 2024/05/13 13:55:50 raeburn Exp $
+# $Id: loncfile.pm,v 1.129 2024/05/21 02:57:16 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -822,42 +822,19 @@
sub Archive1 {
my ($request,$fn) = @_;
my @posstypes = qw(problem library sty sequence page task rights meta xml html xhtml htm xhtm css js tex txt gif jpg jpeg png svg other);
- my (%location_of,%default,$compstyle);
- foreach my $program ('tar','gzip','bzip2','xz','zip') {
- foreach my $dir ('/bin/','/usr/bin/','/usr/local/bin/','/sbin/',
- '/usr/sbin/') {
- if (-x $dir.$program) {
- $location_of{$program} = $dir.$program;
- last;
- }
- }
- }
- my (%defaults,$cancompress,$canarchive);
- if (exists($location_of{'tar'})) {
- $default{'tar'} = ' checked="checked"';
- $canarchive = 1;
- $compstyle = 'block';
- } elsif (exists($location_of{'zip'})) {
- $default{'zip'} = ' checked="checked"';
- $canarchive = 1;
- $compstyle = 'none';
- }
- foreach my $compress ('gzip','bzip2','xz') {
- if (exists($location_of{$compress})) {
- $default{$compress} = ' checked="checked"';
- $cancompress = 1;
- last;
- }
- }
+ my (%location_of,%defaults);
+ my ($compstyle,$canarchive,$cancompress,$numformat,$numcompress,$defext) =
+ &archive_tools(\%location_of,\%defaults);
if (!$canarchive) {
$request->print('<p class="LC_error">'.
- &mt('This LON-CAPA instance does not seem to have either tar or zip installed.').'</p>'.
+ &mt('This LON-CAPA instance does not seem to have either tar or zip installed.').'</p>'."\n".
'<span class="LC_warning">'.
&mt('At least one of the two is needed in order to be able to create an archive file for: [_1].',
- &display($fn)).
+ &display($fn))."\n".
'</span></form>');
} elsif (-e $fn) {
- $request->print(&Apache::lonhtmlcommon::start_pick_box().
+ $request->print('<input type="hidden" name="adload" value="" />'."\n".
+ &Apache::lonhtmlcommon::start_pick_box().
&Apache::lonhtmlcommon::row_title(&mt('Directory')).
&display($fn).
&Apache::lonhtmlcommon::row_closure().
@@ -909,7 +886,7 @@
if (exists($location_of{$possfmt})) {
$request->print('<span class="LC_nobreak">'.
'<label><input type="radio" name="format" value="'.$possfmt.'"'.
- $default{$possfmt}.' onclick="toggleCompression(this.form);" /> '.
+ $defaults{$possfmt}.' onclick="toggleCompression(this.form);" /> '.
$possfmt.'</label></span> ');
}
}
@@ -921,7 +898,8 @@
foreach my $compress ('gzip','bzip2','xz') {
if (exists($location_of{$compress})) {
$request->print('<label><input type="radio" name="compress" value="'.$compress.'"'.
- $default{$compress}.' />'.$compress.'</label> ');
+ $defaults{$compress}.' onclick="setArchiveExt(this.form);" />'.
+ $compress.'</label> ');
}
}
} else {
@@ -929,9 +907,16 @@
&mt('This LON-CAPA instance does not seem to have gzip, bzip2 or xz installed.').
'<br />'.&mt('No compression will be used.').'</span>');
}
- $request->print('</fieldset>'.
+ $request->print('</fieldset>'."\n".
+ '<fieldset style="display:none" id="archive_saveas">'.
+ '<legend>'.&mt('Filename to download').'</legend>'.
+ '<table style="border-spacing:0"><tr><td style="padding:0;">'.&mt('Name').'<br />'."\n".
+ '<input type="text" name="archivefname" value="" size="8" /></td><td style="padding:0;">'.
+ &mt('Extension').'<br />'."\n".
+ '<input type="text" name="archiveext" id="archiveext" value="" size="4" readonly="readonly" />'.
+ '</td></tr></table></fieldset>'."\n".
&Apache::lonhtmlcommon::row_closure(1).
- &Apache::lonhtmlcommon::end_pick_box()
+ &Apache::lonhtmlcommon::end_pick_box().'<br />'."\n"
);
&CloseForm1($request, $fn);
} else {
@@ -941,6 +926,110 @@
.'</p></form>'
);
}
+ return;
+}
+
+sub archive_tools {
+ my ($location_of,$defaults) = @_;
+ my ($compstyle,$canarchive,$cancompress,$numformat,$numcompress,$defext);
+ ($numformat,$numcompress) = (0,0);
+ if ((ref($location_of) eq 'HASH') && (ref($defaults) eq 'HASH')) {
+ foreach my $program ('tar','gzip','bzip2','xz','zip') {
+ foreach my $dir ('/bin/','/usr/bin/','/usr/local/bin/','/sbin/',
+ '/usr/sbin/') {
+ if (-x $dir.$program) {
+ $location_of->{$program} = $dir.$program;
+ last;
+ }
+ }
+ }
+ foreach my $format ('tar','zip') {
+ if (exists($location_of->{$format})) {
+ unless ($canarchive) {
+ $defext = $format;
+ $defaults->{$format} = ' checked="checked"';
+ if ($format eq 'tar') {
+ $compstyle = 'block';
+ } else {
+ $compstyle = 'none';
+ }
+ }
+ $canarchive = 1;
+ $numformat ++;
+ }
+ }
+ foreach my $compress ('gzip','bzip2','xz') {
+ if (exists($location_of->{$compress})) {
+ $numcompress ++;
+ unless ($cancompress) {
+ if ($defext eq 'tar') {
+ if ($compress eq 'gzip') {
+ $defext .= '.gz';
+ } elsif ($compress eq 'bzip2') {
+ $defext .= '.bz2';
+ } else {
+ $defext .= ".$compress";
+ }
+ }
+ $defaults->{$compress} = ' checked="checked"';
+ $cancompress = 1;
+ }
+ }
+ }
+ }
+ if (wantarray) {
+ return ($compstyle,$canarchive,$cancompress,$numformat,$numcompress,$defext);
+ } else {
+ return $defext;
+ }
+}
+
+sub archive_in_progress {
+ my ($earlyout,$idnum);
+ if ($env{'cgi.author.archive'} =~ /^(\d+)_\d+_\d+$/) {
+ my $timestamp = $1;
+ $idnum = $env{'cgi.author.archive'};
+ if (exists($env{'cgi.'.$idnum.'.archive'})) {
+ my $hashref = &Apache::lonnet::thaw_unescape($env{'cgi.'.$idnum.'.archive'});
+ my $lonprtdir = $Apache::lonnet::perlvar{'lonPrtDir'};
+ if (-e $lonprtdir.'/'.$env{'user.name'}.'_'.$env{'user.domain'}.'_archive_'.$idnum.'.txt') {
+ $earlyout = $timestamp;
+ } elsif (ref($hashref) eq 'HASH') {
+ my $suffix = $hashref->{'extension'};
+ if (-e $lonprtdir.'/'.$env{'user.name'}.'_'.$env{'user.domain'}.'_archive_'.$idnum.$suffix) {
+ $earlyout = $timestamp;
+ }
+ }
+ unless ($earlyout) {
+ &Apache::lonnet::delenv('cgi.'.$idnum.'.archive');
+ &Apache::lonnet::delenv('cgi.author.archive');
+ }
+ } else {
+ &Apache::lonnet::delenv('cgi.author.archive');
+ }
+ }
+ return ($earlyout,$idnum);
+}
+
+sub cancel_archive_form {
+ my ($r,$title,$fname,$earlyout,$idnum) = @_;
+ $r->print('<h2>'.$title.'</h2>'."\n".
+ '<form action="/adm/cfile" method="post" onsubmit="return confirmation(this);">'."\n".
+ '<input type="hidden" name="filename" value="'.$fname.'" />'."\n".
+ '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />'."\n".
+ '<p>'.&mt('Each author may only have one archive request in process at a time.')."\n".'<ul>'.
+ '<li>'.&mt('An incomplete archive request was begun: [_1].',
+ &Apache::lonlocal::locallocaltime($earlyout)).
+ '</li>'."\n".
+ '<li>'.&mt('An archive request is considered complete when the archive file has been successfully downloaded.').'</li>'."\n".
+ '<li>'.
+ &mt('To submit a new archive request, either wait for the existing request (e.g., in another tab/window) to complete, or remove it.').'</li>'."\n".
+ '</ul></p>'."\n".
+ '<p><span class="LC_nobreak">'.&mt('Remove existing archive request?').' '."\n".
+ '<label><input type="radio" name="remove_archive_request" value="'.$idnum.'" />'.&mt('Yes').'</label>'.
+ (' 'x2)."\n".
+ '<label><input type="radio" name="remove_archive_request" value="" checked="checked" />'.&mt('No').'</label></span></p>'."\n".
+ '<br />');
}
=pod
@@ -1118,10 +1207,10 @@
'</a></p>');
return;
}
- $r->print('<form action="/adm/cfile" method="post" name="phaseone">'.
- '<input type="hidden" name="qualifiedfilename" value="'.$fn.'" />'.
- '<input type="hidden" name="phase" value="two" />'.
- '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />');
+ $r->print('<form action="/adm/cfile" method="post" name="phaseone">'."\n".
+ '<input type="hidden" name="qualifiedfilename" value="'.$fn.'" />'."\n".
+ '<input type="hidden" name="phase" value="two" />'."\n".
+ '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />'."\n");
if ($env{'form.action'} eq 'newfile' ||
$env{'form.action'} eq 'newhtmlfile' ||
@@ -1437,10 +1526,22 @@
}
sub Archive2 {
- my ($r,$name,$udom,$fn,$identifier) = @_;
+ my ($r,$uname,$udom,$fn,$identifier) = @_;
my %options = (
dir => $fn,
+ uname => $uname,
+ udom => $udom,
);
+ if ($env{'form.adload'}) {
+ $options{'adload'} = 1;
+ if ($env{'form.archivefname'} ne '') {
+ $env{'form.archivefname'} =~ s{\.+}{.}g;
+ $options{'fname'} = $env{'form.archivefname'};
+ }
+ if ($env{'form.archiveext'} ne '') {
+ $options{'extension'} = $env{'form.archiveext'};
+ }
+ }
my @filetypes = qw(problem library sty sequence page task rights meta xml html xhtml htm xhtm css js tex txt gif jpg jpeg png svg other);
my (@include,%oktypes);
map { $oktypes{$_} = 1; } @filetypes;
@@ -1473,10 +1574,40 @@
}
my $key = 'cgi.'.$identifier.'.archive';
my $storestring = &Apache::lonnet::freeze_escape(\%options);
- &Apache::lonnet::appenv({$key => $storestring});
+ &Apache::lonnet::appenv({$key => $storestring,
+ 'cgi.author.archive' => $identifier});
return 1;
}
+sub Archive3 {
+ my ($hashref) = @_;
+ if (ref($hashref) eq 'HASH') {
+ if (($hashref->{'uname'} eq $env{'user.name'}) &&
+ ($hashref->{'udom'} eq $env{'user.domain'}) &&
+ ($env{'environment.canarchive'}) &&
+ ($env{'form.delarchive'})) {
+ my $filesdest = $Apache::lonnet::perlvar{'lonPrtDir'}.'/'.$env{'user.name'}.'_'.$env{'user.domain'}.'_archive_'.$env{'form.delarchive'};
+ if (-e $filesdest) {
+ my $size = (stat($filesdest))[7];
+ if (unlink($filesdest)) {
+ my ($identifier,$suffix) = split(/\./,$env{'form.delarchive'},2);
+ if (($identifier) && (exists($env{'cgi.'.$identifier.'.archive'}))) {
+ my $delres = &Apache::lonnet::delenv('cgi.'.$identifier.'.archive');
+ if (($delres eq 'ok') &&
+ (exists($env{'cgi.author.archive'})) &&
+ ($env{'cgi.author.archive'} eq $identifier)) {
+ &Apache::lonnet::authorarchivelog($hashref,$size,$filesdest,'delete');
+ &Apache::lonnet::delenv('cgi.author.archive');
+ }
+ }
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
=pod
=item phasetwo($r, $fn, $uname, $udom,$identifier)
@@ -1624,14 +1755,26 @@
#
# Determine the root filename
# This could come in as "filename", which actually is a URL, or
-# as "qualifiedfilename", which is indeed a real filename in filesystem
+# as "qualifiedfilename", which is indeed a real filename in filesystem,
+# or in value of decompress form element, or need to be extracted
+# from %env from hashref retrieved for cgi.<id>.archive key, where id
+# is a unique cgi_id created when an Author creates an archive of
+# Authoring Space for download.
#
- my $fn;
+ my ($fn,$archiveref);
if ($env{'form.filename'}) {
&Debug($r, "test: $env{'form.filename'}");
$fn=&unescape($env{'form.filename'});
$fn=&URLToPath($fn);
+ } elsif ($env{'form.delarchive'}) {
+ my ($delarchive,$suffix) = split(/\./,$env{'form.delarchive'});
+ if (($delarchive) && (exists($env{'cgi.'.$delarchive.'.archive'}))) {
+ $archiveref = &Apache::lonnet::thaw_unescape($env{'cgi.'.$delarchive.'.archive'});
+ if (ref($archiveref) eq 'HASH') {
+ $fn = $archiveref->{'dir'};
+ }
+ }
} elsif($ENV{'QUERY_STRING'} && $env{'form.phase'} ne 'two') {
#Just hijack the script only the first time around to inject the
#correct information for further processing
@@ -1666,12 +1809,19 @@
$r->filename);
return HTTP_NOT_ACCEPTABLE;
}
-
+ if (($env{'form.delarchive'}) &&
+ ($env{'environment.canarchive'})) {
+ &Apache::loncommon::content_type($r,'text/plain');
+ $r->send_http_header;
+ $r->print(&Archive3($archiveref));
+ return OK;
+ }
&Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;
- my ($js,$identifier);
+# Declarations for items used for directory archive requests
+ my ($js,$identifier,$defext,$archive_earlyout,$archive_idnum);
my $args = {};
if (($env{'form.action'} eq 'newdir') && ($env{'form.phase'} eq 'two') &&
@@ -1691,15 +1841,60 @@
ENDJS
$args->{'add_entries'} = { onload => "writeDone()" };
} elsif (($env{'form.action'} eq 'archive') &&
- ($env{'environment.authorarchive'})) {
- if ($env{'form.phase'} eq 'two') {
- $identifier = &Apache::loncommon::get_cgi_id();
- $args->{'redirect'} = [0,"/cgi-bin/archive.pl?$identifier"];
- } else {
- my $check_uncheck_js = &Apache::loncommon::check_uncheck_jscript();
+ ($env{'environment.canarchive'})) {
+# Check if author already has an archive request in process
+ ($archive_earlyout,$archive_idnum) = &archive_in_progress();
+# Check if archive request was in process which author wishes to terminate
+ if ($env{'form.remove_archive_request'}) {
+ if ($env{'form.remove_archive_request'} eq $archive_idnum) {
+ if (exists($env{'cgi.'.$archive_idnum.'.archive'})) {
+ my $archiveref = &Apache::lonnet::thaw_unescape($env{'cgi.'.$archive_idnum.'.archive'});
+ if (ref($archiveref) eq 'HASH') {
+ $env{'form.delarchive'} = $archive_idnum.$archiveref->{'extension'};
+ if (&Archive3($archiveref)) {
+ ($archive_earlyout,$archive_idnum) = &archive_in_progress();
+ }
+ delete($env{'form.delarchive'});
+ }
+ }
+ }
+ }
+ if ($archive_earlyout) {
+ my $conftext =
+ &mt('Removing an existing request will terminate an active download of the archive file.');
+ &js_escape(\$conftext);
$js = <<"ENDJS";
<script type="text/javascript">
// <![CDATA[
+function confirmation(form) {
+ if (form.remove_archive_request.length) {
+ for (var i=0; i<form.remove_archive_request.length; i++) {
+ if (form.remove_archive_request[i].checked) {
+ if (form.remove_archive_request[i].value == '$archive_idnum') {
+ if (!confirm('$conftext')) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+// ]]>
+</script>
+
+ENDJS
+ } else {
+ if ($env{'form.phase'} eq 'two') {
+ $identifier = &Apache::loncommon::get_cgi_id();
+ $args->{'redirect'} = [0.1,"/cgi-bin/archive.pl?$identifier"];
+ } else {
+ my (%location_of,%defaults);
+ $defext = &archive_tools(\%location_of,\%defaults);
+ my $check_uncheck_js = &Apache::loncommon::check_uncheck_jscript();
+ $js = <<"ENDJS";
+<script type="text/javascript">
+// <![CDATA[
function toggleCompression(form) {
if (document.getElementById('tar_compression')) {
if (form.format.length > 1) {
@@ -1715,9 +1910,57 @@
}
}
}
+ setArchiveExt(form);
return;
}
+function setArchiveExt(form) {
+ var newfmt;
+ var newcomp;
+ var newdef;
+ if (document.getElementById('archiveext')) {
+ if (form.format.length) {
+ for (var i=0; i<form.format.length; i++) {
+ if (form.format[i].checked) {
+ newfmt = form.format[i].value;
+ break;
+ }
+ }
+ } else {
+ newfmt = form.format[0];
+ }
+ if (newfmt == 'tar') {
+ if (document.getElementById('tar_compression')) {
+ if (form.compress.length) {
+ for (var i=0; i<form.compress.length; i++) {
+ if (form.compress[i].checked) {
+ newcomp = form.compress[i].value;
+ break;
+ }
+ }
+ } else {
+ newcomp = form.compress[0];
+ }
+ }
+ if (newcomp == 'gzip') {
+ newdef = newfmt+'.gz';
+ } else if (newcomp == 'bzip2') {
+ newdef = newfmt+'.bz2';
+ } else if (newcomp == 'xz') {
+ newdef = newfmt+'.'+newcomp;
+ } else {
+ newdef = newfmt;
+ }
+ } else if (newfmt == 'zip') {
+ newdef = newfmt;
+ }
+ if ((newdef == '') || (newdef == undefined) || (newdef == null)) {
+ newdef = '.$defext';
+ }
+ document.getElementById('archiveext').value = newdef;
+ }
+}
+
function resetForm() {
if (document.phaseone.filetype.length) {
for (var i=0; i<document.phaseone.filetype.length; i++) {
@@ -1746,6 +1989,27 @@
}
}
document.phaseone.recurse.checked = false;
+ var a = document.createElement('a');
+ var vis;
+ if (typeof a.download != "undefined") {
+ document.phaseone.adload.value = '1';
+ if (document.getElementById('archive_saveas')) {
+ document.getElementById('archive_saveas').style.display = 'block';
+ vis = '1';
+ }
+ }
+ if (vis == '1') {
+ if (document.getElementById('archiveext')) {
+ document.getElementById('archiveext').value='.$defext';
+ }
+ } else {
+ if (document.getElementById('archive_saveas')) {
+ document.getElementById('archive_saveas').style.display = 'none';
+ }
+ if (document.getElementById('archiveext')) {
+ document.getElementById('archiveext').value='';
+ }
+ }
}
$check_uncheck_js
@@ -1754,7 +2018,8 @@
</script>
ENDJS
- $args->{'add_entries'} = { onload => "resetForm()" };
+ $args->{'add_entries'} = { onload => "resetForm()" };
+ }
}
}
my $londocroot = $r->dir_config('lonDocRoot');
@@ -1854,7 +2119,16 @@
return OK;
}
} elsif ($env{'form.action'} eq 'archive') {
- unless ($env{'environment.authorarchive'}) {
+ if ($env{'environment.canarchive'}) {
+ if ($archive_earlyout) {
+ my $fname = &url($fn);
+ my $title = $action{$env{'form.action'}};
+ &cancel_archive_form($r,$title,$fname,$archive_earlyout,$archive_idnum);
+ &CloseForm1($r,$fn);
+ $r->print(&Apache::loncommon::end_page());
+ return OK;
+ }
+ } else {
$r->print('<p>'.&mt('Location').': '.&display($fn).'</p>'."\n".
'<p class="LC_error">'.
&mt('You do not have permission to export to an archive file in this Authoring Space').
@@ -1863,7 +2137,7 @@
return OK;
}
}
- $r->print('<h2>'.$action{$env{'form.action'}}.'</h2>');
+ $r->print('<h2>'.$action{$env{'form.action'}}.'</h2>'."\n");
} else {
$r->print('<p class="LC_error">'
.&mt('Unknown Action: [_1]',$env{'form.action'})
Index: loncom/cgi/archive.pl
diff -u loncom/cgi/archive.pl:1.1 loncom/cgi/archive.pl:1.2
--- loncom/cgi/archive.pl:1.1 Mon May 13 13:55:51 2024
+++ loncom/cgi/archive.pl Tue May 21 02:57:17 2024
@@ -1,6 +1,6 @@
#!/usr/bin/perl
#
-# $Id: archive.pl,v 1.1 2024/05/13 13:55:51 raeburn Exp $
+# $Id: archive.pl,v 1.2 2024/05/21 02:57:17 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -28,7 +28,7 @@
#
# A CGI script which creates a compressed archive file of the current
# directory in Authoring Space, with optional (a) recursion into
-# sub-directories, (b) filtering by filetype and (c) encryption.
+# sub-directories, and (b) filtering by filetype.
# Supported formats are: tar.gz, tar.bz2, tar.xz and zip.
####
use strict;
@@ -82,13 +82,14 @@
&Apache::lonlocal::get_language_handle();
&Apache::loncommon::content_type(undef,'text/html');
my $identifier = $ENV{'QUERY_STRING'};
- my ($hashref,$dir,$dirurl,$jsdirurl,$auname,$audom,$allowed,$error,$encrypt,$enckey,$format,$compress);
+ my ($hashref,$dir,$dirurl,$jsdirurl,$auname,$audom,$allowed,$error,
+ $format,$compress,$fname,$extension,$adload,$url,$mime);
my @posstypes = qw(problem library sty sequence page task rights meta xml html xhtml htm xhtm css js tex txt gif jpg jpeg png svg other);
- if (($identifier) && (exists($env{'cgi.'.$identifier.'.archive'}))) {
+ if (($identifier =~ /^\d+_\d+_\d+$/) && (exists($env{'cgi.'.$identifier.'.archive'}))) {
$hashref = &Apache::lonnet::thaw_unescape($env{'cgi.'.$identifier.'.archive'});
if (ref($hashref) eq 'HASH') {
$dir = $hashref->{'dir'};
- # check for traversal
+ $dir =~ s{\.+}{.}g;
if (-d $dir) {
$dirurl = $dir;
($auname,$audom) = &Apache::lonnet::constructaccess($dir);
@@ -98,7 +99,7 @@
$maxdepth = $prefix =~ tr{/}{};
$jsdirurl = &js_escape($dirurl);
if (($auname eq $env{'user.name'}) && ($audom eq $env{'user.domain'}) &&
- ($env{'environment.authorarchive'})) {
+ ($env{'environment.canarchive'})) {
$allowed = 1;
if ($hashref->{'recurse'}) {
$recurse = 1;
@@ -128,10 +129,6 @@
}
}
}
- if ((exists($hashref->{'encrypt'}) && $hashref->{'encrypt'} ne '')) {
- $encrypt = 1;
- $enckey = $hashref->{'encrypt'};
- }
if ((exists($hashref->{'format'}) && $hashref->{'format'} =~ /^zip$/i)) {
$format = lc($hashref->{'format'});
} else {
@@ -144,6 +141,15 @@
$compress = 'gzip';
}
}
+ if ($hashref->{'adload'}) {
+ $adload = $hashref->{'adload'};
+ }
+ if ($hashref->{'fname'}) {
+ $fname = $hashref->{'fname'};
+ }
+ if ($hashref->{'extension'}) {
+ $extension = $hashref->{'extension'};
+ }
}
}
} else {
@@ -152,8 +158,10 @@
} else {
$error = 'nohash';
}
-# delete cgi.$identifier.archive from %env
- &Apache::lonnet::delenv('cgi.'.$identifier.'.archive');
+# delete cgi.$identifier.archive from %env if error
+ if ($error) {
+ &Apache::lonnet::delenv('cgi.'.$identifier.'.archive');
+ }
} else {
$error = 'noid';
}
@@ -175,22 +183,16 @@
{'href' => '',
'text' => $title}];
}
- my $js;
- print &Apache::loncommon::start_page($title,
- $js,
- {'bread_crumbs' => $brcrum,})."\n".
- '<form name="constspace" method="post" action="">'."\n".
- '<input type="hidden" name="filename" value="" />'."\n";
- if ($error) {
- print "&mt('Cannot create archive file -- \n";
- } elsif ($allowed) {
- my (%location_of, at tocheck);
+# Set up files to write two and url
+ my ($js,%location_of,$suffix,$namesdest,$filesdest,$filesurl);
+ if ($allowed) {
+ my @tocheck;
if ($format ne '') {
push(@tocheck,$format);
}
if ($compress ne '') {
push(@tocheck,$compress);
- }
+ }
foreach my $program (@tocheck) {
foreach my $dir ('/bin/','/usr/bin/','/usr/local/bin/','/sbin/',
'/usr/sbin/') {
@@ -200,26 +202,66 @@
}
}
}
- if (exists($location_of{$format})) {
- my $suffix;
+ if (($format ne '') && (exists($location_of{$format}))) {
if ($format eq 'zip') {
- $suffix = 'zip';
+ $suffix = '.zip';
+ $mime = 'application/x-zip-compressed';
} else {
- $suffix = 'tar';
- if (exists($location_of{$compress})) {
+ $suffix = '.tar';
+ if (($compress ne '') &&
+ (exists($location_of{$compress}))) {
if ($compress eq 'bzip2') {
- $suffix .= '.bz2';
+ $suffix .= '.bz2';
+ $mime = 'application/x-bzip2';
} elsif ($compress eq 'gzip') {
$suffix .= '.gz';
+ $mime = 'application/x-gzip';
} elsif ($compress eq 'xz') {
$suffix .= '.xz';
+ $mime = 'application/x-xz';
}
}
}
- my $namesdest = $perlvar{'lonPrtDir'}.'/'.$env{'user.name'}.'_'.$env{'user.domain'}.'_archive_'.$identifier.'.txt';
- my $filesdest = $perlvar{'lonPrtDir'}.'/'.$env{'user.name'}.'_'.$env{'user.domain'}.'_archive_'.$identifier.'.'.$suffix;
- my $filesurl = '/prtspool/'.$env{'user.name'}.'_'.$env{'user.domain'}.'_archive_'.$identifier.'.'.$suffix;
- unless ($lock) { $lock=&Apache::lonnet::set_lock(&mt('Archiving [_1]',$dirurl)); }
+ $namesdest = $perlvar{'lonPrtDir'}.'/'.$env{'user.name'}.'_'.$env{'user.domain'}.'_archive_'.$identifier.'.txt';
+ $filesdest = $perlvar{'lonPrtDir'}.'/'.$env{'user.name'}.'_'.$env{'user.domain'}.'_archive_'.$identifier.$suffix;
+ $filesurl = '/prtspool/'.$env{'user.name'}.'_'.$env{'user.domain'}.'_archive_'.$identifier.$suffix;
+ if ($suffix eq $extension) {
+ $fname =~ s{\Q$suffix\E$}{};
+ }
+ if ($fname eq '') {
+ $fname = $env{'user.name'}.'_'.$env{'user.domain'}.'_archive_'.$identifier.$suffix;
+ } else {
+ $fname .= $suffix;
+ }
+ my $downloadurl = &Apache::lonnet::absolute_url().$filesurl;
+ my $delarchive = $identifier.$suffix;
+ $js = &js($filesurl,$mime,$fname,$delarchive);
+ }
+ }
+ print &Apache::loncommon::start_page($title,
+ '',
+ {'bread_crumbs' => $brcrum,})."\n".
+ '<form name="constspace" method="post" action="">'."\n".
+ '<input type="hidden" name="filename" value="" />'."\n";
+ if ($error) {
+ print &mt('Cannot create archive file');
+ } elsif ($allowed) {
+ if (-e $filesdest) {
+ my $mtime = (stat($filesdest))[9];
+ print '<div id="LC_archive_desc">'."\n";
+ if ($mtime) {
+ print '<p class="LC_warning">'.&mt('Archive file already exists -- created: [_1].',
+ &Apache::lonlocal::locallocaltime($mtime)).'</p>';
+ } else {
+ print '<p class="LC_warning">'.&mt('Archive file already exists.').'</p>';
+ }
+ print '</div>'."\n";
+ print &archive_link($adload,$filesurl,$suffix);
+ if ($adload) {
+ print $js;
+ }
+ } elsif (exists($location_of{$format})) {
+ unless ($lock) { $lock=&Apache::lonnet::set_lock(&mt('Creating Archive file for [_1]',$dirurl)); }
if (open($fh,'>',$namesdest)) {
find(
{preprocess => \&filter_files,
@@ -227,38 +269,85 @@
no_chdir => 1,
},$dir);
close($fh);
+ if (ref($hashref) eq 'HASH') {
+ $hashref->{'numfiles'} = $totalfiles;
+ $hashref->{'numdirs'} = $totalsubdirs;
+ $hashref->{'bytes'} = $totalsize;
+ my $storestring = &Apache::lonnet::freeze_escape($hashref);
+ &Apache::lonnet::appenv({'cgi.'.$identifier.'.archive' => $storestring});
+ }
+ &Apache::lonnet::thaw_unescape($env{'cgi.'.$identifier.'.archive'});
if (($totalfiles) || ($totalsubdirs)) {
- print '<p>'.
- &mt('Archiving: [quant,_1,file,files] with total size: [_2] bytes in [quant,_3,subdirectory,subdirectories] ...',
- $totalfiles,$totalsize,$totalsubdirs).
- '</p>';
- my ($cwd, at args);
- if ($format eq 'zip') {
- $cwd = &Cwd::getcwd();
- @args = ('zip',$filesdest,'-v','-r','.','-i@'.$namesdest);
- chdir $prefix;
- } else {
- @args = ('tar',"--create","--verbose");
- if (($compress ne '') && (exists($location_of{$compress}))) {
- push(@args,"--$compress");
+ my $freespace;
+ my @dfargs = ('df','-k','--output=avail','/home');
+ if (open(my $pipe,'-|', at dfargs)) {
+ while (my $line = <$pipe>) {
+ chomp($line);
+ if ($line =~ /^\d+$/) {
+ $freespace = $line;
+ last;
+ }
}
- push(@args,("--file=$filesdest","--directory=$prefix","--files-from=$namesdest"));
+ close($pipe);
}
- if (open(my $pipe,'-|', at args)) {
- my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin('',$totalfiles);
- while (<$pipe>) {
- &Apache::lonhtmlcommon::Increment_PrgWin('',\%prog_state,'last file');
+ if (($freespace ne '') && ($totalsize < $freespace*1024)) {
+ my $showsize = $totalsize/(1024*1024);
+ if ($showsize <= 0.01) {
+ $showsize = sprintf("%.3f",$showsize);
+ } elsif ($showsize <= 0.1) {
+ $showsize = sprintf("%.2f",$showsize);
+ } elsif ($showsize < 10) {
+ $showsize = sprintf("%.1f",$showsize);
+ } else {
+ $showsize = sprintf("%.0f",$showsize);
}
- &Apache::lonhtmlcommon::Close_PrgWin('',\%prog_state);
- close($pipe);
- if (!-e $filesdest) {
- print '<p>'.&mt('No archive file available for download').'</p>'."\n";
+ print '<div id="LC_archive_desc"><p>'.
+ &mt('Creating archive file for [quant,_1,file,files] with total size before compression of [_2] MB.',
+ $totalfiles,$showsize);
+ if ($totalsubdirs) {
+ print '<br />'.&mt('Archive includes [quant,_1,subdirectory,subdirectories].',
+ $totalsubdirs);
+ }
+ print '</p></div>';
+ my ($cwd, at args);
+ if ($format eq 'zip') {
+ $cwd = &Cwd::getcwd();
+ @args = ('zip',$filesdest,'-v','-r','.','-i@'.$namesdest);
+ chdir $prefix;
+ } else {
+ @args = ('tar',"--create","--verbose");
+ if (($compress ne '') && (exists($location_of{$compress}))) {
+ push(@args,"--$compress");
+ }
+ push(@args,("--file=$filesdest","--directory=$prefix","--files-from=$namesdest"));
+ }
+ if (open(my $pipe,'-|', at args)) {
+ my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin('',$totalfiles);
+ while (<$pipe>) {
+ &Apache::lonhtmlcommon::Increment_PrgWin('',\%prog_state,'last file');
+ }
+ &Apache::lonhtmlcommon::Close_PrgWin('',\%prog_state);
+ close($pipe);
+ if (-e $filesdest) {
+ my $size = (stat($filesdest))[7];
+ &Apache::lonnet::authorarchivelog($hashref,$size,$filesdest,'create');
+ print &archive_link($adload,$filesurl,$suffix);
+ if ($adload) {
+ print $js;
+ }
+ } else {
+ print '<p>'.&mt('No archive file available for download').'</p>'."\n";
+ }
+ } else {
+ print '<p>'.&mt('Could not call [_1] command',$format).'</p>'."\n";
+ }
+ if (($format eq 'zip') && ($cwd ne '')) {
+ chdir $cwd;
}
+ } elsif ($freespace eq '') {
+ print '<p>'.&mt('No archive file created as the available free space could not be determined.').'</p>'."\n";
} else {
- print '<p>'.&mt('Could not call [_1] command',$format).'</p>'."\n";
- }
- if (($format eq 'zip') && ($cwd ne '')) {
- chdir $cwd;
+ print '<p>'.&mt('No archive file created because there is insufficient free space available.').'</p>'."\n";
}
} else {
print '<p>'.&mt('No files match the requested types so no archive file was created.').'</p>'."\n";
@@ -273,7 +362,7 @@
}
}
if ($dirurl) {
- print '<br /><br />'.
+ print '<br />'.
&Apache::lonhtmlcommon::actionbox(['<a href="'.&HTML::Entities::encode($dirurl,'\'"&<>').'">'.
&mt('Return to Directory').'</a>']);
}
@@ -306,6 +395,7 @@
}
push(@ChosenFiles,$file);
} else {
+ next if ($file =~ /^\./);
my ($extension) = ($file =~ /\.([^.]+)$/);
if ((!$excluded{$extension}) && ($alltypes || $includeother || $included{$extension})) {
push(@ChosenFiles,$file);
@@ -332,54 +422,155 @@
print $fh "$filename\n";
}
+sub archive_link {
+ my ($adload,$filesurl,$suffix) = @_;
+ if ($adload) {
+ return
+'<button id="LC_download_button" onclick="return false">'.&mt('Download').'</button></p>'."\n".
+'<div style="display:none; width:100%;" id="LC_dload_progress" >'."\n".
+'<div id="LC_dl_progressbar"></div>'."\n".
+'</div>'."\n".
+'<span id="LC_download_result"></span>'."\n";
+ } else {
+ return
+'<p><a href="'.$filesurl.'">'.&mt('Download [_1] file',$suffix).'</a></p>'."\n";
+ }
+}
+
sub js {
- my $output = <<'END';
-const xhrButtonSuccess = document.querySelector(".xhr.success");
-const xhrButtonError = document.querySelector(".xhr.error");
-const xhrButtonAbort = document.querySelector(".xhr.abort");
-const log = document.querySelector(".event-log");
-
-function handleEvent(e) {
- log.textContent = `${log.textContent}${e.type}: ${e.loaded} bytes transferred\n`;
-}
-
-function addListeners(xhr) {
- xhr.addEventListener("loadstart", handleEvent);
- xhr.addEventListener("load", handleEvent);
- xhr.addEventListener("loadend", handleEvent);
- xhr.addEventListener("progress", handleEvent);
- xhr.addEventListener("error", handleEvent);
- xhr.addEventListener("abort", handleEvent);
-}
-
-function runXHR(url) {
- log.textContent = "";
-
- const xhr = new XMLHttpRequest();
- addListeners(xhr);
- xhr.open("GET", url);
- xhr.send();
- return xhr;
-}
-
-xhrButtonSuccess.addEventListener("click", () => {
- runXHR(
- "https://somewhere",
- );
-});
-
-xhrButtonError.addEventListener("click", () => {
- runXHR("http://i-dont-exist");
-});
-
-xhrButtonAbort.addEventListener("click", () => {
- runXHR(
- "https://somewhere",
- ).abort();
-});
+ my ($url,$mime,$fname,$delarchive) = @_;
+ &js_escape(\$url);
+ &js_escape(\$mime);
+ &js_escape(\$fname);
+ my %js_lt = &Apache::lonlocal::texthash (
+ afdo => 'Archive file download complete.',
+ diun => 'Download is unavailable.',
+ tfbr => 'The archive file has been removed.',
+ ynrd => 'You do not have rights to download the archive file.',
+ );
+ &js_escape(\%js_lt);
+ return <<"END";
+<script type="text/javascript">
+// <![CDATA[
+
+function showProgress(event) {
+ if (event.lengthComputable) {
+ var complete = 0;
+ if (event.total > 0) {
+ complete = Math.round( (event.loaded / event.total) * 100);
+ }
+ \$( "#LC_dl_progressbar" ).progressbar({
+ value: complete
+ });
+ if (complete == '100') {
+ if (document.getElementById('LC_dload_progress')) {
+ document.getElementById('LC_dload_progress').style.display = 'none';
+ }
+ }
+ }
+}
-END
+function cleanUp(event) {
+ showProgress(event);
+ if (event.lengthComputable) {
+ var complete = 0;
+ if (event.total > 0) {
+ complete = Math.round( (event.loaded / event.total) * 100);
+ }
+ if (complete == 100) {
+ var dbtn = document.querySelector('#LC_download_button');
+ if (dbtn !== null) {
+ dbtn.style.display = 'none';
+ }
+ var http = new XMLHttpRequest();
+ var lcurl = "/adm/cfile";
+ var params = 'delarchive=$delarchive';
+ var result;
+ http.open("POST",lcurl, true);
+ http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+ http.onreadystatechange = function() {
+ if ((http.readyState == 4) && (http.status == 200)) {
+ if (http.responseText.length > 0) {
+ if (http.responseText == 1) {
+ if (document.getElementById('LC_archive_desc')) {
+ document.getElementById('LC_archive_desc').style.display = 'none';
+ }
+ if (document.getElementById('LC_download_result')) {
+ document.getElementById('LC_download_result').innerHTML = '$js_lt{afdo}<br />';
+ }
+ }
+ }
+ }
+ }
+ http.send(params);
+ }
+ }
+}
+
+function filecheck(file, callback) {
+ const xhr = new XMLHttpRequest();
+ xhr.open('HEAD',file,true);
+ xhr.onreadystatechange = function() {
+ if (this.readyState >= 2) {
+ callback(this.status);
+ this.abort();
+ }
+ };
+ xhr.send();
+}
+
+function download(file,callback) {
+ if (document.getElementById('LC_dload_progress')) {
+ document.getElementById('LC_dload_progress').style.display = 'block';
+ }
+ const xhr = new XMLHttpRequest();
+ xhr.responseType = 'blob';
+ xhr.open('GET', file);
+ xhr.addEventListener('progress',showProgress);
+ xhr.addEventListener('load', function () {
+ callback(xhr.response);
+ });
+ xhr.addEventListener("loadend", cleanUp);
+ xhr.send();
+}
+function save(object,mime,name) {
+ var a = document.createElement('a');
+ var url = URL.createObjectURL(object);
+ a.href = url;
+ a.type = mime;
+ a.download = name;
+ a.click();
}
+var dbtn = document.querySelector('#LC_download_button');
+if (dbtn !== null) {
+ dbtn.addEventListener('click', function () {
+ filecheck('$url',function (response) {
+ if (response == 200) {
+ download('$url', function (file) {
+ save(file,'$mime','$fname');
+ });
+ } else if ((response == 404) || (response == 403) || (response == 406)) {
+ dbtn.style.display = 'none';
+ if (document.getElementById('LC_dload_progress')) {
+ document.getElementById('LC_dload_progress').style.display = 'none';
+ }
+ if (document.getElementById('LC_download_result')) {
+ if (response == 404) {
+ document.getElementById('LC_download_result').innerHTML = '$js_lt{diun} $js_lt{tfbr}<br />';
+ } else {
+ document.getElementById('LC_download_result').innerHTML = '$js_lt{diun} $js_lt{ynrd}<br />';
+ }
+ }
+ }
+ });
+ });
+}
+
+// ]]>
+</script>
+END
+
+}
More information about the LON-CAPA-cvs
mailing list