Annotation of loncom/cgi/archive.pl, revision 1.2

1.1       raeburn     1: #!/usr/bin/perl
                      2: #
1.2     ! raeburn     3: # $Id: archive.pl,v 1.1 2024/05/13 13:55:51 raeburn Exp $
1.1       raeburn     4: #
                      5: # Copyright Michigan State University Board of Trustees
                      6: #
                      7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      8: #
                      9: # LON-CAPA is free software; you can redistribute it and/or modify
                     10: # it under the terms of the GNU General Public License as published by
                     11: # the Free Software Foundation; either version 2 of the License, or
                     12: # (at your option) any later version.
                     13: #
                     14: # LON-CAPA is distributed in the hope that it will be useful,
                     15: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     17: # GNU General Public License for more details.
                     18: #
                     19: # You should have received a copy of the GNU General Public License
                     20: # along with LON-CAPA; if not, write to the Free Software
                     21: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     22: #
                     23: # /home/httpd/cgi-bin/archive.pl
                     24: #
                     25: # http://www.lon-capa.org/
                     26: #
                     27: # The LearningOnline Network with CAPA
                     28: #
                     29: # A CGI script which creates a compressed archive file of the current
                     30: # directory in Authoring Space, with optional (a) recursion into
1.2     ! raeburn    31: # sub-directories, and (b) filtering by filetype.
1.1       raeburn    32: # Supported formats are: tar.gz, tar.bz2, tar.xz and zip.
                     33: ####
                     34: use strict;
                     35: use lib '/home/httpd/lib/perl';
                     36: use File::Find;
                     37: use Apache::lonnet;
                     38: use Apache::loncommon;
                     39: use Apache::lonlocal;
                     40: use LONCAPA::loncgi;
                     41: use Cwd;
                     42: use HTML::Entities;
                     43: 
                     44: $|++;
                     45: 
                     46: my $lock;
                     47: 
                     48: our %excluded = (
                     49:                    bak => 1,
                     50:                    save => 1,
                     51:                    log => 1,
                     52:                 );
                     53: 
                     54: our $maxdepth = 0;
                     55: our %included = ();
                     56: our $alltypes = '';
                     57: our $recurse = '';
                     58: our $includeother = '';
                     59: our $prefix = '';
                     60: our $totalfiles = 0;
                     61: our $totalsize = 0;
                     62: our $totalsubdirs = 0;
                     63: our %subdirs = ();
                     64: our $fh;
                     65: 
                     66: if (!&LONCAPA::loncgi::check_cookie_and_load_env()) {
                     67:     &Apache::lonlocal::get_language_handle();
                     68:     print(&LONCAPA::loncgi::missing_cookie_msg());
                     69: } else {
                     70:     &Apache::lonlocal::get_language_handle();
                     71:     my %lt = &Apache::lonlocal::texthash (
                     72:                                             indi => 'Invalid directory name',
                     73:                                             outo => 'Output of command:',
                     74:                                             comp => 'Archive creation complete.',
                     75:                                             erro => 'An error occurred.',
                     76:                                             cctf  => 'Cannot create tar file',
                     77:                                             dtf  => 'Download tar file',
                     78:                                          );
                     79: # Get the identifier and set a lock
                     80:     my %perlvar=%{&LONCAPA::Configuration::read_conf('loncapa.conf')};
                     81:     my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
                     82:     &Apache::lonlocal::get_language_handle();
                     83:     &Apache::loncommon::content_type(undef,'text/html');
                     84:     my $identifier = $ENV{'QUERY_STRING'};
1.2     ! raeburn    85:     my ($hashref,$dir,$dirurl,$jsdirurl,$auname,$audom,$allowed,$error,
        !            86:         $format,$compress,$fname,$extension,$adload,$url,$mime);
1.1       raeburn    87:     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);
1.2     ! raeburn    88:     if (($identifier =~ /^\d+_\d+_\d+$/) && (exists($env{'cgi.'.$identifier.'.archive'}))) {
1.1       raeburn    89:         $hashref = &Apache::lonnet::thaw_unescape($env{'cgi.'.$identifier.'.archive'});
                     90:         if (ref($hashref) eq 'HASH') {
                     91:             $dir = $hashref->{'dir'};
1.2     ! raeburn    92:             $dir =~ s{\.+}{.}g;
1.1       raeburn    93:             if (-d $dir) {
                     94:                 $dirurl = $dir;
                     95:                 ($auname,$audom) = &Apache::lonnet::constructaccess($dir);
                     96:                 if (($auname ne '') && ($audom ne '')) {
                     97:                     $dirurl =~ s/^\Q$londocroot\E//;
                     98:                     $prefix = $londocroot.$dirurl;
                     99:                     $maxdepth = $prefix =~ tr{/}{};
                    100:                     $jsdirurl = &js_escape($dirurl);
                    101:                     if (($auname eq $env{'user.name'}) && ($audom eq $env{'user.domain'}) &&
1.2     ! raeburn   102:                         ($env{'environment.canarchive'})) {
1.1       raeburn   103:                         $allowed = 1;
                    104:                         if ($hashref->{'recurse'}) {
                    105:                             $recurse = 1;
                    106:                         } else {
                    107:                             $recurse = 0;
                    108:                         }
                    109:                         if ($hashref->{'types'} eq 'all') {
                    110:                             $alltypes = 1;
                    111:                         } else {
                    112:                             $alltypes = 0;
                    113:                             my %possincluded;
                    114:                             map { $possincluded{$_} = 1; } split(/,/,$hashref->{'types'});
                    115:                             $includeother = 0;
                    116:                             foreach my $type (@posstypes) {
                    117:                                 if ($type eq 'other') {
                    118:                                     if ($possincluded{$type}) {
                    119:                                         $includeother = 1;
                    120:                                     } else {
                    121:                                         $includeother = 0;
                    122:                                     }
                    123:                                 } else {
                    124:                                     if ($possincluded{$type}) {
                    125:                                         $included{$type} = 1;
                    126:                                     } else {
                    127:                                         $excluded{$type} = 1;
                    128:                                     }
                    129:                                 }
                    130:                             }
                    131:                         }
                    132:                         if ((exists($hashref->{'format'}) && $hashref->{'format'} =~ /^zip$/i)) {
                    133:                             $format = lc($hashref->{'format'});
                    134:                         } else {
                    135:                             $format = 'tar';
                    136:                         }
                    137:                         unless ($format eq 'zip') { 
                    138:                             if ((exists($hashref->{'compress'})) && ($hashref->{'compress'} =~ /^(xz|bzip2)$/i)) {
                    139:                                 $compress = lc($hashref->{'compress'});
                    140:                             } else {
                    141:                                 $compress = 'gzip';
                    142:                             }
                    143:                         }
1.2     ! raeburn   144:                         if ($hashref->{'adload'}) {
        !           145:                             $adload = $hashref->{'adload'};
        !           146:                         }
        !           147:                         if ($hashref->{'fname'}) {
        !           148:                             $fname = $hashref->{'fname'};
        !           149:                         }
        !           150:                         if ($hashref->{'extension'}) {
        !           151:                             $extension = $hashref->{'extension'};
        !           152:                         }
1.1       raeburn   153:                     }
                    154:                 }
                    155:             } else {
                    156:                 $error = 'indi';
                    157:             }
                    158:         } else {
                    159:             $error = 'nohash';
                    160:         }
1.2     ! raeburn   161: # delete cgi.$identifier.archive from %env if error
        !           162:         if ($error) {
        !           163:             &Apache::lonnet::delenv('cgi.'.$identifier.'.archive');
        !           164:         }
1.1       raeburn   165:     } else {
                    166:         $error = 'noid';
                    167:     }
                    168:     $env{'request.noversionuri'} = '/cgi-bin/archive.pl';
                    169:     my ($brcrum,$title); 
                    170:     if ($error) {
                    171:         $brcrum = [{'href' => '',
                    172:                     'text' => 'Missing information'}];
                    173:     } elsif (!$allowed) {
                    174:         $brcrum = [{'href' => '',
                    175:                     'text' => 'Access denied'}];
                    176:     } else {
                    177: # Breadcrumbs
                    178:         $title = 'Creating archive file';
                    179:         $brcrum = [{'href' => $dirurl,
                    180:                     'text' => 'Authoring Space'},
                    181:                    {'href' => "javascript:gocstr('/adm/cfile?action=archive','$jsdirurl');",
                    182:                     'text' => 'File Operation'},
                    183:                    {'href' => '',
                    184:                     'text' => $title}];
                    185:     }
1.2     ! raeburn   186: # Set up files to write two and url
        !           187:     my ($js,%location_of,$suffix,$namesdest,$filesdest,$filesurl);
        !           188:     if ($allowed) {
        !           189:         my @tocheck;
1.1       raeburn   190:         if ($format ne '') {
                    191:             push(@tocheck,$format);
                    192:         }
                    193:         if ($compress ne '') {
                    194:             push(@tocheck,$compress);
1.2     ! raeburn   195:         }
1.1       raeburn   196:         foreach my $program (@tocheck) {
                    197:             foreach my $dir ('/bin/','/usr/bin/','/usr/local/bin/','/sbin/',
                    198:                              '/usr/sbin/') {
                    199:                 if (-x $dir.$program) {
                    200:                     $location_of{$program} = $dir.$program;
                    201:                     last;
                    202:                 }
                    203:             }
                    204:         }
1.2     ! raeburn   205:         if (($format ne '') && (exists($location_of{$format}))) {
1.1       raeburn   206:             if ($format eq 'zip') {
1.2     ! raeburn   207:                 $suffix = '.zip';
        !           208:                 $mime = 'application/x-zip-compressed';
1.1       raeburn   209:             } else {
1.2     ! raeburn   210:                 $suffix = '.tar';
        !           211:                 if (($compress ne '') &&
        !           212:                     (exists($location_of{$compress}))) {
1.1       raeburn   213:                     if ($compress eq 'bzip2') {
1.2     ! raeburn   214:                         $suffix .= '.bz2';
        !           215:                         $mime = 'application/x-bzip2';
1.1       raeburn   216:                     } elsif ($compress eq 'gzip') {
                    217:                         $suffix .= '.gz';
1.2     ! raeburn   218:                         $mime = 'application/x-gzip';
1.1       raeburn   219:                     } elsif ($compress eq 'xz') {
                    220:                         $suffix .= '.xz';
1.2     ! raeburn   221:                         $mime = 'application/x-xz';
1.1       raeburn   222:                     }
                    223:                 }
                    224:             }
1.2     ! raeburn   225:             $namesdest = $perlvar{'lonPrtDir'}.'/'.$env{'user.name'}.'_'.$env{'user.domain'}.'_archive_'.$identifier.'.txt';
        !           226:             $filesdest = $perlvar{'lonPrtDir'}.'/'.$env{'user.name'}.'_'.$env{'user.domain'}.'_archive_'.$identifier.$suffix;
        !           227:             $filesurl = '/prtspool/'.$env{'user.name'}.'_'.$env{'user.domain'}.'_archive_'.$identifier.$suffix;
        !           228:             if ($suffix eq $extension) {
        !           229:                 $fname =~ s{\Q$suffix\E$}{};
        !           230:             }
        !           231:             if ($fname eq '') {
        !           232:                 $fname = $env{'user.name'}.'_'.$env{'user.domain'}.'_archive_'.$identifier.$suffix;
        !           233:             } else {
        !           234:                 $fname .= $suffix;
        !           235:             }
        !           236:             my $downloadurl = &Apache::lonnet::absolute_url().$filesurl;
        !           237:             my $delarchive = $identifier.$suffix;
        !           238:             $js = &js($filesurl,$mime,$fname,$delarchive);
        !           239:         }
        !           240:     }
        !           241:     print &Apache::loncommon::start_page($title,
        !           242:                                          '',
        !           243:                                          {'bread_crumbs' => $brcrum,})."\n".
        !           244:           '<form name="constspace" method="post" action="">'."\n".
        !           245:           '<input type="hidden" name="filename" value="" />'."\n";
        !           246:     if ($error) {
        !           247:         print &mt('Cannot create archive file');
        !           248:     } elsif ($allowed) {
        !           249:         if (-e $filesdest) {
        !           250:             my $mtime = (stat($filesdest))[9];
        !           251:             print '<div id="LC_archive_desc">'."\n";
        !           252:             if ($mtime) {
        !           253:                 print '<p class="LC_warning">'.&mt('Archive file already exists -- created: [_1].',
        !           254:                                                    &Apache::lonlocal::locallocaltime($mtime)).'</p>';
        !           255:             } else {
        !           256:                 print '<p class="LC_warning">'.&mt('Archive file already exists.').'</p>';
        !           257:             }
        !           258:             print '</div>'."\n";
        !           259:             print &archive_link($adload,$filesurl,$suffix);
        !           260:             if ($adload) {
        !           261:                 print $js;
        !           262:             }
        !           263:         } elsif (exists($location_of{$format})) {
        !           264:             unless ($lock) { $lock=&Apache::lonnet::set_lock(&mt('Creating Archive file for [_1]',$dirurl)); }
1.1       raeburn   265:             if (open($fh,'>',$namesdest)) {
                    266:                 find(
                    267:                      {preprocess => \&filter_files,
                    268:                       wanted     => \&store_names,
                    269:                       no_chdir   => 1,
                    270:                      },$dir);
                    271:                 close($fh);
1.2     ! raeburn   272:                 if (ref($hashref) eq 'HASH') {
        !           273:                     $hashref->{'numfiles'} = $totalfiles;
        !           274:                     $hashref->{'numdirs'} = $totalsubdirs;
        !           275:                     $hashref->{'bytes'} = $totalsize;
        !           276:                     my $storestring = &Apache::lonnet::freeze_escape($hashref);
        !           277:                     &Apache::lonnet::appenv({'cgi.'.$identifier.'.archive' => $storestring});
        !           278:                 }
        !           279:                 &Apache::lonnet::thaw_unescape($env{'cgi.'.$identifier.'.archive'});
1.1       raeburn   280:                 if (($totalfiles) || ($totalsubdirs)) {
1.2     ! raeburn   281:                     my $freespace;
        !           282:                     my @dfargs = ('df','-k','--output=avail','/home');
        !           283:                     if (open(my $pipe,'-|',@dfargs)) {
        !           284:                         while (my $line = <$pipe>) {
        !           285:                             chomp($line);
        !           286:                             if ($line =~ /^\d+$/) {
        !           287:                                 $freespace = $line;
        !           288:                                 last;
        !           289:                             }
1.1       raeburn   290:                         }
1.2     ! raeburn   291:                         close($pipe);
1.1       raeburn   292:                     }
1.2     ! raeburn   293:                     if (($freespace ne '') && ($totalsize < $freespace*1024)) {
        !           294:                         my $showsize = $totalsize/(1024*1024);
        !           295:                         if ($showsize <= 0.01) {
        !           296:                             $showsize = sprintf("%.3f",$showsize);
        !           297:                         } elsif ($showsize <= 0.1) {
        !           298:                             $showsize = sprintf("%.2f",$showsize);
        !           299:                         } elsif ($showsize < 10) {
        !           300:                             $showsize = sprintf("%.1f",$showsize);
        !           301:                         } else {
        !           302:                             $showsize = sprintf("%.0f",$showsize);
        !           303:                         }
        !           304:                         print '<div id="LC_archive_desc"><p>'.
        !           305:                               &mt('Creating archive file for [quant,_1,file,files] with total size before compression of [_2] MB.',
        !           306:                                   $totalfiles,$showsize);
        !           307:                         if ($totalsubdirs) {
        !           308:                             print '<br />'.&mt('Archive includes [quant,_1,subdirectory,subdirectories].',
        !           309:                                                $totalsubdirs);
        !           310:                         }
        !           311:                         print '</p></div>';
        !           312:                         my ($cwd,@args);
        !           313:                         if ($format eq 'zip') {
        !           314:                             $cwd = &Cwd::getcwd();
        !           315:                             @args = ('zip',$filesdest,'-v','-r','.','-i@'.$namesdest);
        !           316:                             chdir $prefix;
        !           317:                         } else {
        !           318:                             @args = ('tar',"--create","--verbose");
        !           319:                             if (($compress ne '') && (exists($location_of{$compress}))) {
        !           320:                                 push(@args,"--$compress");
        !           321:                             }
        !           322:                             push(@args,("--file=$filesdest","--directory=$prefix","--files-from=$namesdest"));
        !           323:                         }
        !           324:                         if (open(my $pipe,'-|',@args)) {
        !           325:                             my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin('',$totalfiles); 
        !           326:                             while (<$pipe>) {
        !           327:                                 &Apache::lonhtmlcommon::Increment_PrgWin('',\%prog_state,'last file');
        !           328:                             }
        !           329:                             &Apache::lonhtmlcommon::Close_PrgWin('',\%prog_state);
        !           330:                             close($pipe);
        !           331:                             if (-e $filesdest) {
        !           332:                                 my $size = (stat($filesdest))[7];
        !           333:                                 &Apache::lonnet::authorarchivelog($hashref,$size,$filesdest,'create');
        !           334:                                 print &archive_link($adload,$filesurl,$suffix);
        !           335:                                 if ($adload) {
        !           336:                                     print $js;
        !           337:                                 }
        !           338:                             } else {
        !           339:                                 print '<p>'.&mt('No archive file available for download').'</p>'."\n"; 
        !           340:                             }
        !           341:                         } else {
        !           342:                             print '<p>'.&mt('Could not call [_1] command',$format).'</p>'."\n";
1.1       raeburn   343:                         }
1.2     ! raeburn   344:                         if (($format eq 'zip') && ($cwd ne '')) {
        !           345:                             chdir $cwd;
1.1       raeburn   346:                         }
1.2     ! raeburn   347:                     } elsif ($freespace eq '') {
        !           348:                         print '<p>'.&mt('No archive file created as the available free space could not be determined.').'</p>'."\n";
1.1       raeburn   349:                     } else {
1.2     ! raeburn   350:                         print '<p>'.&mt('No archive file created because there is insufficient free space available.').'</p>'."\n";
1.1       raeburn   351:                     }
                    352:                 } else {
                    353:                     print '<p>'.&mt('No files match the requested types so no archive file was created.').'</p>'."\n";
                    354:                 }
                    355:                 unlink($namesdest);
                    356:             } else {
                    357:                 print '<p>'.&mt('Could not store list of files to archive').'</p>'."\n";
                    358:             }
                    359:             if ($lock) { &Apache::lonnet::remove_lock($lock); }
                    360:         } else {
                    361:             print '<p>'.&mt('Could not find location of [_1] command',$format).'</p>'."\n";
                    362:         }
                    363:     }
                    364:     if ($dirurl) {
1.2     ! raeburn   365:         print '<br />'.
1.1       raeburn   366:               &Apache::lonhtmlcommon::actionbox(['<a href="'.&HTML::Entities::encode($dirurl,'\'"&<>').'">'.
                    367:                                                  &mt('Return to Directory').'</a>']);
                    368:     }
                    369:     print '</form>'.&Apache::loncommon::end_page();
                    370: 
                    371: # Code to delete archive file after successful download
                    372:     %included = ();
                    373:     $alltypes = '';
                    374:     $recurse = '';
                    375:     $includeother = '';
                    376:     $prefix = '';
                    377:     $totalfiles = 0;
                    378:     $totalsize = 0;
                    379:     $totalsubdirs = 0;
                    380:     %excluded = (
                    381:                    bak => 1,
                    382:                    save => 1,
                    383:                    log => 1,
                    384:                 );
                    385: }
                    386: 
                    387: sub filter_files {
                    388:     my @PossibleFiles = @_;
                    389:     my @ChosenFiles;
                    390:     foreach my $file (@PossibleFiles) {
                    391:         if (-d $File::Find::dir."/".$file) {
                    392:             if (!$recurse) {
                    393:                 my $depth = $File::Find::dir =~ tr[/][];
                    394:                 next unless ($depth < $maxdepth-1);
                    395:             }
                    396:             push(@ChosenFiles,$file);
                    397:         } else {
1.2     ! raeburn   398:             next if ($file =~ /^\./);
1.1       raeburn   399:             my ($extension) = ($file =~ /\.([^.]+)$/);
                    400:             if ((!$excluded{$extension}) && ($alltypes || $includeother || $included{$extension})) {
                    401:                 push(@ChosenFiles,$file);
                    402:             }
                    403:         }
                    404:     }
                    405:     return @ChosenFiles;  
                    406: }
                    407: 
                    408: sub store_names {
                    409:     my $filename = $File::Find::name;
                    410:     if (-d $filename) {
                    411:         unless ("$filename/" eq $prefix) {
                    412:             if ($recurse) {
                    413:                 $subdirs{$filename} = 1;
                    414:                 $totalsubdirs ++;
                    415:             }
                    416:         }
                    417:         next;
                    418:     }
                    419:     $totalfiles ++;
                    420:     $totalsize += -s $filename;
                    421:     $filename =~ s{^$prefix}{}; 
                    422:     print $fh "$filename\n";
                    423: }
                    424: 
1.2     ! raeburn   425: sub archive_link {
        !           426:     my ($adload,$filesurl,$suffix) = @_;
        !           427:     if ($adload) {
        !           428:         return
        !           429: '<button id="LC_download_button" onclick="return false">'.&mt('Download').'</button></p>'."\n".
        !           430: '<div style="display:none; width:100%;" id="LC_dload_progress" >'."\n".
        !           431: '<div id="LC_dl_progressbar"></div>'."\n".
        !           432: '</div>'."\n".
        !           433: '<span id="LC_download_result"></span>'."\n";
        !           434:     } else {
        !           435:         return
        !           436: '<p><a href="'.$filesurl.'">'.&mt('Download [_1] file',$suffix).'</a></p>'."\n";
        !           437:     }
        !           438: }
        !           439: 
1.1       raeburn   440: sub js {
1.2     ! raeburn   441:     my ($url,$mime,$fname,$delarchive) = @_;
        !           442:     &js_escape(\$url);
        !           443:     &js_escape(\$mime);
        !           444:     &js_escape(\$fname);
        !           445:     my %js_lt = &Apache::lonlocal::texthash (
        !           446:                                               afdo => 'Archive file download complete.',
        !           447:                                               diun => 'Download is unavailable.',
        !           448:                                               tfbr => 'The archive file has been removed.',
        !           449:                                               ynrd => 'You do not have rights to download the archive file.',
        !           450:     );
        !           451:     &js_escape(\%js_lt);
        !           452:     return <<"END";
        !           453: <script type="text/javascript">
        !           454: // <![CDATA[
        !           455: 
        !           456: function showProgress(event) {
        !           457:     if (event.lengthComputable) {
        !           458:         var complete = 0;
        !           459:         if (event.total > 0) {
        !           460:             complete = Math.round( (event.loaded / event.total) * 100);
        !           461:         }
        !           462:         \$( "#LC_dl_progressbar" ).progressbar({
        !           463:            value: complete
        !           464:         });
        !           465:         if (complete == '100') {
        !           466:             if (document.getElementById('LC_dload_progress')) {
        !           467:                 document.getElementById('LC_dload_progress').style.display = 'none';
        !           468:             }
        !           469:         }
        !           470:     }
        !           471: }
        !           472: 
        !           473: function cleanUp(event) {
        !           474:     showProgress(event);
        !           475:     if (event.lengthComputable) {
        !           476:         var complete = 0;
        !           477:         if (event.total > 0) {
        !           478:             complete = Math.round( (event.loaded / event.total) * 100);
        !           479:         }
        !           480:         if (complete == 100) {
        !           481:             var dbtn = document.querySelector('#LC_download_button');
        !           482:             if (dbtn !== null) {
        !           483:                 dbtn.style.display = 'none';
        !           484:             }
        !           485:             var http = new XMLHttpRequest();
        !           486:             var lcurl = "/adm/cfile";
        !           487:             var params = 'delarchive=$delarchive';
        !           488:             var result;
        !           489:             http.open("POST",lcurl, true);
        !           490:             http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        !           491:             http.onreadystatechange = function() {
        !           492:                 if ((http.readyState == 4) && (http.status == 200)) {
        !           493:                     if (http.responseText.length > 0) {
        !           494:                         if (http.responseText == 1) {
        !           495:                             if (document.getElementById('LC_archive_desc')) {
        !           496:                                 document.getElementById('LC_archive_desc').style.display = 'none';
        !           497:                             }
        !           498:                             if (document.getElementById('LC_download_result')) {
        !           499:                                 document.getElementById('LC_download_result').innerHTML = '$js_lt{afdo}<br />';
        !           500:                             }
        !           501:                         }
        !           502:                     }
        !           503:                 }
        !           504:             }
        !           505:             http.send(params);
        !           506:         }
        !           507:     }
        !           508: }
        !           509: 
        !           510: function filecheck(file, callback) {
        !           511:     const xhr = new XMLHttpRequest();
        !           512:     xhr.open('HEAD',file,true);
        !           513:     xhr.onreadystatechange = function() {
        !           514:         if (this.readyState >= 2) {
        !           515:             callback(this.status);
        !           516:             this.abort();
        !           517:         }
        !           518:     };
        !           519:     xhr.send();
        !           520: }
        !           521: 
        !           522: function download(file,callback) {
        !           523:     if (document.getElementById('LC_dload_progress')) {
        !           524:         document.getElementById('LC_dload_progress').style.display = 'block';
        !           525:     }
        !           526:     const xhr = new XMLHttpRequest();
        !           527:     xhr.responseType = 'blob';
        !           528:     xhr.open('GET', file);
        !           529:     xhr.addEventListener('progress',showProgress);
        !           530:     xhr.addEventListener('load', function () {
        !           531:         callback(xhr.response);
        !           532:     });
        !           533:     xhr.addEventListener("loadend", cleanUp);
        !           534:     xhr.send();
        !           535: }
1.1       raeburn   536: 
1.2     ! raeburn   537: function save(object,mime,name) {
        !           538:     var a = document.createElement('a');
        !           539:     var url = URL.createObjectURL(object);
        !           540:     a.href = url;
        !           541:     a.type = mime;
        !           542:     a.download = name;
        !           543:     a.click();
        !           544: }
1.1       raeburn   545: 
1.2     ! raeburn   546: var dbtn = document.querySelector('#LC_download_button');
        !           547: if (dbtn !== null) {
        !           548:     dbtn.addEventListener('click', function () {
        !           549:         filecheck('$url',function (response) {
        !           550:             if (response == 200) {
        !           551:                 download('$url', function (file) {
        !           552:                     save(file,'$mime','$fname');
        !           553:                 });
        !           554:             } else if ((response == 404) || (response == 403) || (response == 406)) {
        !           555:                 dbtn.style.display = 'none';
        !           556:                 if (document.getElementById('LC_dload_progress')) {
        !           557:                     document.getElementById('LC_dload_progress').style.display = 'none';
        !           558:                 }
        !           559:                 if (document.getElementById('LC_download_result')) {
        !           560:                     if (response == 404) {
        !           561:                         document.getElementById('LC_download_result').innerHTML = '$js_lt{diun} $js_lt{tfbr}<br />';
        !           562:                     } else {
        !           563:                         document.getElementById('LC_download_result').innerHTML = '$js_lt{diun} $js_lt{ynrd}<br />';
        !           564:                     }
        !           565:                 }
        !           566:             }
        !           567:         });
        !           568:     });
1.1       raeburn   569: }
                    570: 
1.2     ! raeburn   571: // ]]>
        !           572: </script>
1.1       raeburn   573: 
1.2     ! raeburn   574: END
        !           575: 
        !           576: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>