Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to using Archive::Zip and Archive::Tar to extract archives. #49

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion bin/check_modules.pl
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ =head1 DESCRIPTION
);

my @modulesList = qw(
Archive::Extract
Archive::Zip
Archive::Zip::SimpleZip
Array::Utils
Expand Down
81 changes: 74 additions & 7 deletions lib/WeBWorK/ContentGenerator/Instructor/FileManager.pm
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ WeBWorK::ContentGenerator::Instructor::FileManager.pm -- simple directory manage

=cut

use Mojo::File;
use File::Path;
use File::Copy;
use File::Spec;
use String::ShellQuote;
use Archive::Extract;
use Archive::Tar;
use Archive::Zip qw(:ERROR_CODES);
use Archive::Zip::SimpleZip qw($SimpleZipError);

use WeBWorK::Utils qw(readDirectory readFile sortByName listFilesRecursive);
Expand Down Expand Up @@ -446,14 +447,80 @@ sub UnpackArchive ($c) {
}

sub unpack_archive ($c, $archive) {
my $dir = "$c->{courseRoot}/$c->{pwd}";
my $arch = Archive::Extract->new(archive => "$dir/$archive");
my $dir = Mojo::File->new($c->{courseRoot}, $c->{pwd});

if ($arch->extract(to => $dir)) {
$c->addgoodmessage($c->maketext('[quant,_1,file] unpacked successfully', scalar(@{ $arch->files })));
return 1;
if ($archive =~ m/\.zip$/) {
my $zip = Archive::Zip->new($dir->child($archive)->to_string);
unless ($zip) {
$c->addbadmessage($c->maketext(q{Unable to read zip archive file "[_1]".}, $dir->child($archive)));
return 0;
}

Archive::Zip::setErrorHandler(sub ($error) {
chomp $error;
$c->addbadmessage($error);
});

my $num_extracted = 0;
my @members = $zip->members;
for (@members) {
my $out_file = $dir->child($_->fileName)->realpath;
if ($out_file !~ /^$dir/) {
$c->addbadmessage($c->maketext(
'The file "[_1]" can not be safely unpacked as it is outside the current working directory.',
$_->fileName
));
next;
}

if (!$c->param('overwrite') && -e $out_file) {
$c->addbadmessage($c->maketext(
'The file "[_1]" already exists. '
. 'Check "Overwrite existing files silently" to unpack this file.',
$_->fileName
));
next;
}
++$num_extracted if $zip->extractMember($_ => $out_file->to_string) == AZ_OK;
}

Archive::Zip::setErrorHandler();

$c->addgoodmessage($c->maketext('[quant,_1,file] unpacked successfully', $num_extracted)) if $num_extracted;
return $num_extracted == @members;
} elsif ($archive =~ m/\.(tar(\.gz)?|tgz)$/) {
local $Archive::Tar::WARN = 0;

my $tar = Archive::Tar->new($dir->child($archive)->to_string);
unless ($tar) {
$c->addbadmessage($c->maketext(q{Unable to read tar archive file "[_1]".}, $dir->child($archive)));
return 0;
}

$tar->setcwd($dir->to_string);

my $num_extracted = 0;
my @members = $tar->list_files;
for (@members) {
if (!$c->param('overwrite') && -e $dir->child($_)) {
$c->addbadmessage($c->maketext(
'The file "[_1]" already exists. '
. 'Check "Overwrite existing files silently" to unpack this file.',
$_
));
next;
}
unless ($tar->extract_file($_)) {
$c->addbadmessage($tar->error);
next;
}
++$num_extracted;
}

$c->addgoodmessage($c->maketext('[quant,_1,file] unpacked successfully', $num_extracted)) if $num_extracted;
return $num_extracted == @members;
} else {
$c->addbadmessage($c->maketext(q{Can't unpack "[_1]": command returned [_2]}, $archive, $arch->error));
$c->addbadmessage($c->maketext('Unsupported archive type in file "[_1]"', $archive));
return 0;
}
}
Expand Down
21 changes: 10 additions & 11 deletions templates/HelpFiles/InstructorFileManager.html.ep
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
%
<p>
<%= maketext('This allows for the viewing, downloading, uploading and other management '
. 'of files in the course. Select a file or set of files (using CTRL or SHIFT) and click '
. 'the desired button on the right. Many actions can only be done with a single file (like '
. 'of files in the course. Select a file or set of files (using CTRL or SHIFT) and click '
. 'the desired button on the right. Many actions can only be done with a single file (like '
. 'view). Selecting a directory or set of files and clicking "Make Archive" allows the creation '
. 'of a compressed tar or zip file.') =%>
</p>
Expand All @@ -29,14 +29,13 @@
</p>
<p>
<%= maketext('Below the file list is a button and options for uploading files. Click the "Choose File" '
. 'button, select the file, then click "Upload". '
. 'A single file or a compressed tar (.tgz) file can be uploaded and if the option is selected, '
. 'the archive is automatically unpacked and deleted. Generally the "automatic" option on Format '
. 'will correctly pick the correct type of file.') =%>
. 'button, select the file, then click "Upload". Generally the "automatic" option on Format will '
. 'correctly pick the correct type of file. A single file or a compressed tar (.tgz) file can be '
. 'uploaded and if the options are selected, the archive is automatically unpacked and deleted.') =%>
</p>
<p>
<%= maketext('WeBWorK expects many files to be in certain locations. The following describe this. '
. 'Note that by default the File Manager shows the "templates" directory. Other directories mentioned '
<%= maketext('WeBWorK expects many files to be in certain locations. The following describe this. '
. 'Note that by default the File Manager shows the "templates" directory. Other directories mentioned '
. 'below are at the same level and need to be accessed by going up a directory by clicking the "^" button '
. 'above the file list.') =%>
</p>
Expand All @@ -48,7 +47,7 @@
. '<strong>Set Definition files</strong> is described in the <a [_1]>Set Definition specification</a>. '
. 'Set definition files are mainly useful for '
. 'transferring set assignments from one course to another and are created when exporting a problem '
. 'set from the "Hmwk Sets Editor". Each set defintion file contains a list of problems used and the '
. 'set from the "Hmwk Sets Editor". Each set defintion file contains a list of problems used and the '
. 'dates and times. These definitions can be imported into the current course.',
'href="https://webwork.maa.org/wiki/Set_Definition_Files" target="Webworkdocs"') =%>
</dd>
Expand All @@ -58,10 +57,10 @@
. 'a large number of students into your class. To view the format for <strong>ClassList files</strong> see '
. 'the <a [_1]>ClassList specification</a> or download the [_2] file and use it as a model. '
. 'ClassList files can be prepared using a spreadsheet and then saved as [_3] (comma separated values) '
. 'text files. However, to access as a classlist file, the file suffix needs to be changed to [_4], '
. 'text files. However, to access as a classlist file, the file suffix needs to be changed to [_4], '
. 'which can be done with the "Rename" button.',
'href="http://webwork.maa.org/wiki/Classlist_Files#Format_of_classlist_files" target="Webworkdocs"',
'<code>demoCourse.lst</code>','<code>.csv</code>','<code>.lst</code>') =%>
'<code>demoCourse.lst</code>', '<code>.csv</code>', '<code>.lst</code>') =%>
</dd>
<dt><%= maketext('Scoring (".csv") files') %></dt>
<dd>
Expand Down