5 use Archive
::Zip
qw( :ERROR_CODES :CONSTANTS );
6 use SGN
::Model
::Cvterm
;
8 use File
::Spec
::Functions
qw(splitpath);
10 use IO
::Uncompress
::Unzip
qw($UnzipError);
11 use File::Path qw(mkpath);
13 has
'archived_zipfile_path' => (
19 has
'extract_directory' => (
24 has
'archived_zip' => (
25 isa
=> 'Archive::Zip::Archive',
30 my $archived_zip = Archive
::Zip
->new();
37 #Assuming that zipfile is a flat list of files.
40 unless ( $archived_zip->read( $self->archived_zipfile_path() ) == AZ_OK
) {
41 print STDERR
"cannot read given zipfile\n";
44 $self->archived_zip(Archive
::Zip
->new($self->archived_zipfile_path()));
45 if (!$self->archived_zip){
48 my @file_names = $self->archived_zip()->memberNames();
49 my @file_names_stripped;
51 foreach (@file_names) {
52 my @zip_names_split = split(/\//, $_);
53 if ($zip_names_split[1]) {
54 if ($zip_names_split[1] ne '.DS_Store' && $zip_names_split[1] ne '.fieldbook' && $zip_names_split[1] ne '.thumbnails') {
55 my @zip_names_split_ext = split(/\./, $zip_names_split[1]);
56 push @file_names_stripped, $zip_names_split_ext[0];
57 push @file_names_full, $zip_names_split[1];
61 return (\
@file_names_stripped, \
@file_names_full);
66 unless ( $archived_zip->read( $self->archived_zipfile_path() ) == AZ_OK
) {
67 print STDERR
"cannot read given zipfile\n";
70 $self->archived_zip(Archive
::Zip
->new($self->archived_zipfile_path()));
72 if (!$self->archived_zip){
75 my @file_members = $self->archived_zip()->members();
76 #print STDERR Dumper \@file_members;
78 foreach (@file_members) {
79 if (exists($seen_files{$_->{'fileName'}}) || $_->{'compressedSize'} == 0 || index($_->{'fileName'}, '.DS_Store') != -1 || index($_->{'fileName'}, '.fieldbook') != -1 || index($_->{'fileName'}, '.thumbnails') != -1 || index($_->{'fileName'}, '__MACOSX') != -1) {
82 $seen_files{$_->{'fileName'}} = 1;
83 push @ret_members, $_;
89 #warning: will copy files out of zipfile and file will lose metadata such as EXIF image data. Use something like SGN::Image::upload_drone_imagery_zipfile if metadata needed.
90 sub extract_files_into_tempdir
{
92 my $dest = $self->extract_directory();
93 my $file = $self->archived_zipfile_path();
95 my $u = IO
::Uncompress
::Unzip
->new($file)
96 or die "Cannot open $file: $UnzipError";
100 for ($status = 1; $status > 0; $status = $u->nextStream()) {
101 my $header = $u->getHeaderInfo();
102 my (undef, $path, $name) = splitpath
($header->{Name
});
103 my $destdir = "$dest/$path";
105 unless (-d
$destdir) {
106 mkpath
($destdir) or die "Couldn't mkdir $destdir: $!";
109 if ($name =~ m!/$!) {
114 my $destfile = "$dest/$path/$name";
115 # https://cwe.mitre.org/data/definitions/37.html
116 # CWE-37: Path Traversal
117 die "unsafe $destfile" if $destfile =~ m!\Q..\E(/|\\)!;
120 my $fh = IO
::File
->new($destfile, "w")
121 or die "Couldn't write to $destfile: $!";
122 while (($status = $u->read($buff)) > 0) {
126 push @image_files, $destfile;
127 my $stored_time = $header->{'Time'};
128 utime ($stored_time, $stored_time, $destfile)
129 or die "Couldn't touch $destfile: $!";
132 die "Error processing $file: $!\n"
135 return \
@image_files;