Subject: | Properly extract symbolic links (proposed patch included) |
Archives which are created with the "zip -y" command (thus preserving
symbolic links, as opposed to following them and including the
destination file) are not currently (version 1.18) properly extracted
by Archive::Zip. Instead of the symbolic link, Archive::Zip creates a
file that contains the name of the link destination. The attached
patch fixes this problem. However, it would probably be a good idea to
also include a configuration directive (which defaults to off),
enabling the extraction of symlinks, otherwise users can unknowingly
create security holes when unzipping malicious archives. I wasn't sure
how best to add this to the existing interface, which is why I didn't
add it in the patch.
Also, the patch probably breaks on Window systems (don't have one so
can't test that :-)
Subject: | Archive-Zip-1.18-symlink.patch |
--- Archive-Zip-1.18/lib/Archive/Zip/Member.pm 2006-10-25 14:18:49.000000000 +0200
+++ Archive-Zip-new/lib/Archive/Zip/Member.pm 2006-11-10 11:57:08.000000000 +0100
@@ -22,6 +22,7 @@
use Compress::Zlib qw( Z_OK Z_STREAM_END MAX_WBITS );
use File::Path;
use File::Basename;
+use Fcntl ':mode';
use constant ZIPFILEMEMBERCLASS => 'Archive::Zip::ZipFileMember';
use constant NEWFILEMEMBERCLASS => 'Archive::Zip::NewFileMember';
@@ -379,10 +380,20 @@
return $bit == IFA_BINARY_FILE;
}
+sub isSymbolicLink {
+ my $self = shift;
+ return S_ISLNK($self->unixFileAttributes());
+}
+
sub extractToFileNamed {
my $self = shift;
my $name = shift; # local FS name
return _error("encryption unsupported") if $self->isEncrypted();
+ if ($self->isSymbolicLink()) {
+ mkpath( dirname($name) );
+ my $symlink_exists = eval { symlink($self->contents(),$name); 1 };
+ return $symlink_exists ? AZ_OK : AZ_ERROR;
+ }
mkpath( dirname($name) ); # croaks on error
my ( $status, $fh ) = _newFileHandle( $name, 'w' );
return _ioError("Can't open file $name for write") unless $status;