Blame lib/Archive/Zip/FAQ.pod

Packit 0bf95d
=head1 NAME
Packit 0bf95d

Packit 0bf95d
Archive::Zip::FAQ - Answers to a few frequently asked questions about Archive::Zip
Packit 0bf95d

Packit 0bf95d
=head1 DESCRIPTION
Packit 0bf95d

Packit 0bf95d
It seems that I keep answering the same questions over and over again. I
Packit 0bf95d
assume that this is because my documentation is deficient, rather than that
Packit 0bf95d
people don't read the documentation.
Packit 0bf95d

Packit 0bf95d
So this FAQ is an attempt to cut down on the number of personal answers I have
Packit 0bf95d
to give. At least I can now say "You I<did> read the FAQ, right?".
Packit 0bf95d

Packit 0bf95d
The questions are not in any particular order. The answers assume the current
Packit 0bf95d
version of Archive::Zip; some of the answers depend on newly added/fixed
Packit 0bf95d
functionality.
Packit 0bf95d

Packit 0bf95d
=head1 Install problems on RedHat 8 or 9 with Perl 5.8.0
Packit 0bf95d

Packit 0bf95d
B<Q:> Archive::Zip won't install on my RedHat 9 system! It's broke!
Packit 0bf95d

Packit 0bf95d
B<A:> This has become something of a FAQ.
Packit 0bf95d
Basically, RedHat broke some versions of Perl by setting LANG to UTF8.
Packit 0bf95d
They apparently have a fixed version out as an update.
Packit 0bf95d

Packit 0bf95d
You might try running CPAN or creating your Makefile after exporting the LANG
Packit 0bf95d
environment variable as
Packit 0bf95d

Packit 0bf95d
C<LANG=C>
Packit 0bf95d

Packit 0bf95d
L<https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=87682>
Packit 0bf95d

Packit 0bf95d
=head1 Why is my zip file so big?
Packit 0bf95d

Packit 0bf95d
B<Q:> My zip file is actually bigger than what I stored in it! Why?
Packit 0bf95d

Packit 0bf95d
B<A:> Some things to make sure of:
Packit 0bf95d

Packit 0bf95d
=over 4
Packit 0bf95d

Packit 0bf95d
=item Make sure that you are requesting COMPRESSION_DEFLATED if you are storing strings.
Packit 0bf95d

Packit 0bf95d
$member->desiredCompressionMethod( COMPRESSION_DEFLATED );
Packit 0bf95d

Packit 0bf95d
=item Don't make lots of little files if you can help it.
Packit 0bf95d

Packit 0bf95d
Since zip computes the compression tables for each member, small
Packit 0bf95d
members without much entropy won't compress well.  Instead, if you've
Packit 0bf95d
got lots of repeated strings in your data, try to combine them into
Packit 0bf95d
one big member.
Packit 0bf95d

Packit 0bf95d
=item Make sure that you are requesting COMPRESSION_STORED if you are storing things that are already compressed.
Packit 0bf95d

Packit 0bf95d
If you're storing a .zip, .jpg, .mp3, or other compressed file in a zip,
Packit 0bf95d
then don't compress them again. They'll get bigger.
Packit 0bf95d

Packit 0bf95d
=back
Packit 0bf95d

Packit 0bf95d
=head1 Sample code?
Packit 0bf95d

Packit 0bf95d
B<Q:> Can you send me code to do (whatever)?
Packit 0bf95d

Packit 0bf95d
B<A:> Have you looked in the C<examples/> directory yet? It contains:
Packit 0bf95d

Packit 0bf95d
=over 4
Packit 0bf95d

Packit 0bf95d
=item examples/calcSizes.pl    -- How to find out how big a Zip file will be before writing it
Packit 0bf95d

Packit 0bf95d
=item examples/copy.pl         -- Copies one Zip file to another
Packit 0bf95d

Packit 0bf95d
=item examples/extract.pl      -- extract file(s) from a Zip
Packit 0bf95d

Packit 0bf95d
=item examples/mailZip.pl      -- make and mail a zip file
Packit 0bf95d

Packit 0bf95d
=item examples/mfh.pl          -- demo for use of MockFileHandle
Packit 0bf95d

Packit 0bf95d
=item examples/readScalar.pl   -- shows how to use IO::Scalar as the source of a Zip read
Packit 0bf95d

Packit 0bf95d
=item examples/selfex.pl       -- a brief example of a self-extracting Zip
Packit 0bf95d

Packit 0bf95d
=item examples/unzipAll.pl     -- uses Archive::Zip::Tree to unzip an entire Zip
Packit 0bf95d

Packit 0bf95d
=item examples/updateZip.pl    -- shows how to read/modify/write a Zip
Packit 0bf95d

Packit 0bf95d
=item examples/updateTree.pl   -- shows how to update a Zip in place
Packit 0bf95d

Packit 0bf95d
=item examples/writeScalar.pl  -- shows how to use IO::Scalar as the destination of a Zip write
Packit 0bf95d

Packit 0bf95d
=item examples/writeScalar2.pl -- shows how to use IO::String as the destination of a Zip write
Packit 0bf95d

Packit 0bf95d
=item examples/zip.pl          -- Constructs a Zip file
Packit 0bf95d

Packit 0bf95d
=item examples/zipcheck.pl     -- One way to check a Zip file for validity
Packit 0bf95d

Packit 0bf95d
=item examples/zipinfo.pl      -- Prints out information about a Zip archive file
Packit 0bf95d

Packit 0bf95d
=item examples/zipGrep.pl      -- Searches for text in Zip files
Packit 0bf95d

Packit 0bf95d
=item examples/ziptest.pl      -- Lists a Zip file and checks member CRCs
Packit 0bf95d

Packit 0bf95d
=item examples/ziprecent.pl    -- Puts recent files into a zipfile
Packit 0bf95d

Packit 0bf95d
=item examples/ziptest.pl      -- Another way to check a Zip file for validity
Packit 0bf95d

Packit 0bf95d
=back
Packit 0bf95d

Packit 0bf95d
=head1 Can't Read/modify/write same Zip file
Packit 0bf95d

Packit 0bf95d
B<Q:> Why can't I open a Zip file, add a member, and write it back? I get an
Packit 0bf95d
error message when I try.
Packit 0bf95d

Packit 0bf95d
B<A:> Because Archive::Zip doesn't (and can't, generally) read file contents into memory,
Packit 0bf95d
the original Zip file is required to stay around until the writing of the new
Packit 0bf95d
file is completed.
Packit 0bf95d

Packit 0bf95d
The best way to do this is to write the Zip to a temporary file and then
Packit 0bf95d
rename the temporary file to have the old name (possibly after deleting the
Packit 0bf95d
old one).
Packit 0bf95d

Packit 0bf95d
Archive::Zip v1.02 added the archive methods C<overwrite()> and
Packit 0bf95d
C<overwriteAs()> to do this simply and carefully.
Packit 0bf95d

Packit 0bf95d
See C<examples/updateZip.pl> for an example of this technique.
Packit 0bf95d

Packit 0bf95d
=head1 File creation time not set
Packit 0bf95d

Packit 0bf95d
B<Q:> Upon extracting files, I see that their modification (and access) times are
Packit 0bf95d
set to the time in the Zip archive. However, their creation time is not set to
Packit 0bf95d
the same time. Why?
Packit 0bf95d

Packit 0bf95d
B<A:> Mostly because Perl doesn't give cross-platform access to I<creation time>.
Packit 0bf95d
Indeed, many systems (like Unix) don't support such a concept.
Packit 0bf95d
However, if yours does, you can easily set it. Get the modification time from
Packit 0bf95d
the member using C<lastModTime()>.
Packit 0bf95d

Packit 0bf95d
=head1 Can't use Archive::Zip on gzip files
Packit 0bf95d

Packit 0bf95d
B<Q:> Can I use Archive::Zip to extract Unix gzip files?
Packit 0bf95d

Packit 0bf95d
B<A:> No.
Packit 0bf95d

Packit 0bf95d
There is a distinction between Unix gzip files, and Zip archives that 
Packit 0bf95d
also can use the gzip compression.
Packit 0bf95d

Packit 0bf95d
Depending on the format of the gzip file, you can use L<Compress::Raw::Zlib>, or
Packit 0bf95d
L<Archive::Tar> to decompress it (and de-archive it in the case of Tar files).
Packit 0bf95d

Packit 0bf95d
You can unzip PKZIP/WinZip/etc/ archives using Archive::Zip (that's what 
Packit 0bf95d
it's for) as long as any compressed members are compressed using 
Packit 0bf95d
Deflate compression.
Packit 0bf95d

Packit 0bf95d
=head1 Add a directory/tree to a Zip
Packit 0bf95d

Packit 0bf95d
B<Q:> How can I add a directory (or tree) full of files to a Zip?
Packit 0bf95d

Packit 0bf95d
B<A:> You can use the Archive::Zip::addTree*() methods:
Packit 0bf95d

Packit 0bf95d
   use Archive::Zip;
Packit 0bf95d
   my $zip = Archive::Zip->new();
Packit 0bf95d
   # add all readable files and directories below . as xyz/*
Packit 0bf95d
   $zip->addTree( '.', 'xyz' );	
Packit 0bf95d
   # add all readable plain files below /abc as def/*
Packit 0bf95d
   $zip->addTree( '/abc', 'def', sub { -f && -r } );	
Packit 0bf95d
   # add all .c files below /tmp as stuff/*
Packit 0bf95d
   $zip->addTreeMatching( '/tmp', 'stuff', '\.c$' );
Packit 0bf95d
   # add all .o files below /tmp as stuff/* if they aren't writable
Packit 0bf95d
   $zip->addTreeMatching( '/tmp', 'stuff', '\.o$', sub { ! -w } );
Packit 0bf95d
   # add all .so files below /tmp that are smaller than 200 bytes as stuff/*
Packit 0bf95d
   $zip->addTreeMatching( '/tmp', 'stuff', '\.o$', sub { -s < 200 } );
Packit 0bf95d
   # and write them into a file
Packit 0bf95d
   $zip->writeToFileNamed('xxx.zip');
Packit 0bf95d

Packit 0bf95d
=head1 Extract a directory/tree
Packit 0bf95d

Packit 0bf95d
B<Q:> How can I extract some (or all) files from a Zip into a different
Packit 0bf95d
directory?
Packit 0bf95d

Packit 0bf95d
B<A:> You can use the Archive::Zip::extractTree() method:
Packit 0bf95d
??? ||
Packit 0bf95d

Packit 0bf95d
   # now extract the same files into /tmpx
Packit 0bf95d
   $zip->extractTree( 'stuff', '/tmpx' );
Packit 0bf95d

Packit 0bf95d
=head1 Update a directory/tree
Packit 0bf95d

Packit 0bf95d
B<Q:> How can I update a Zip from a directory tree, adding or replacing only
Packit 0bf95d
the newer files?
Packit 0bf95d

Packit 0bf95d
B<A:> You can use the Archive::Zip::updateTree() method that was added in version 1.09.
Packit 0bf95d

Packit 0bf95d
=head1 Zip times might be off by 1 second
Packit 0bf95d

Packit 0bf95d
B<Q:> It bothers me greatly that my file times are wrong by one second about half
Packit 0bf95d
the time. Why don't you do something about it?
Packit 0bf95d

Packit 0bf95d
B<A:> Get over it. This is a result of the Zip format storing times in DOS
Packit 0bf95d
format, which has a resolution of only two seconds.
Packit 0bf95d

Packit 0bf95d
=head1 Zip times don't include time zone information
Packit 0bf95d

Packit 0bf95d
B<Q:> My file times don't respect time zones. What gives?
Packit 0bf95d

Packit 0bf95d
B<A:> If this is important to you, please submit patches to read the various
Packit 0bf95d
Extra Fields that encode times with time zones. I'm just using the DOS
Packit 0bf95d
Date/Time, which doesn't have a time zone.
Packit 0bf95d

Packit 0bf95d
=head1 How do I make a self-extracting Zip
Packit 0bf95d

Packit 0bf95d
B<Q:> I want to make a self-extracting Zip file. Can I do this?
Packit 0bf95d

Packit 0bf95d
B<A:> Yes. You can write a self-extracting archive stub (that is, a version of
Packit 0bf95d
unzip) to the output filehandle that you pass to writeToFileHandle(). See
Packit 0bf95d
examples/selfex.pl for how to write a self-extracting archive.
Packit 0bf95d

Packit 0bf95d
However, you should understand that this will only work on one kind of
Packit 0bf95d
platform (the one for which the stub was compiled).
Packit 0bf95d

Packit 0bf95d
=head1 How can I deal with Zips with prepended garbage (i.e. from Sircam)
Packit 0bf95d

Packit 0bf95d
B<Q:> How can I tell if a Zip has been damaged by adding garbage to the
Packit 0bf95d
beginning or inside the file?
Packit 0bf95d

Packit 0bf95d
B<A:> I added code for this for the Amavis virus scanner. You can query archives
Packit 0bf95d
for their 'eocdOffset' property, which should be 0:
Packit 0bf95d

Packit 0bf95d
  if ($zip->eocdOffset > 0)
Packit 0bf95d
    { warn($zip->eocdOffset . " bytes of garbage at beginning or within Zip") }
Packit 0bf95d

Packit 0bf95d
When members are extracted, this offset will be used to adjust the start of
Packit 0bf95d
the member if necessary.
Packit 0bf95d

Packit 0bf95d
=head1 Can't extract Shrunk files
Packit 0bf95d

Packit 0bf95d
B<Q:> I'm trying to extract a file out of a Zip produced by PKZIP, and keep
Packit 0bf95d
getting this error message:
Packit 0bf95d

Packit 0bf95d
  error: Unsupported compression combination: read 6, write 0
Packit 0bf95d

Packit 0bf95d
B<A:> You can't uncompress this archive member. Archive::Zip only supports uncompressed
Packit 0bf95d
members, and compressed members that are compressed using the compression
Packit 0bf95d
supported by Compress::Raw::Zlib. That means only Deflated and Stored members.
Packit 0bf95d

Packit 0bf95d
Your file is compressed using the Shrink format, which is not supported by
Packit 0bf95d
Compress::Raw::Zlib.
Packit 0bf95d

Packit 0bf95d
You could, perhaps, use a command-line UnZip program (like the Info-Zip
Packit 0bf95d
one) to extract this.
Packit 0bf95d

Packit 0bf95d
=head1 Can't do decryption
Packit 0bf95d

Packit 0bf95d
B<Q:> How do I decrypt encrypted Zip members?
Packit 0bf95d

Packit 0bf95d
B<A:> With some other program or library. Archive::Zip doesn't support decryption,
Packit 0bf95d
and probably never will (unless I<you> write it).
Packit 0bf95d

Packit 0bf95d
=head1 How to test file integrity?
Packit 0bf95d

Packit 0bf95d
B<Q:> How can Archive::Zip can test the validity of a Zip file?
Packit 0bf95d

Packit 0bf95d
B<A:> If you try to decompress the file, the gzip streams will report errors 
Packit 0bf95d
if you have garbage. Most of the time.
Packit 0bf95d

Packit 0bf95d
If you try to open the file and a central directory structure can't be 
Packit 0bf95d
found, an error will be reported.
Packit 0bf95d

Packit 0bf95d
When a file is being read, if we can't find a proper PK.. signature in 
Packit 0bf95d
the right places we report a format error.
Packit 0bf95d

Packit 0bf95d
If there is added garbage at the beginning of a Zip file (as inserted 
Packit 0bf95d
by some viruses), you can find out about it, but Archive::Zip will ignore it, 
Packit 0bf95d
and you can still use the archive. When it gets written back out the 
Packit 0bf95d
added stuff will be gone.
Packit 0bf95d

Packit 0bf95d
There are two ready-to-use utilities in the examples directory that can
Packit 0bf95d
be used to test file integrity, or that you can use as examples
Packit 0bf95d
for your own code:
Packit 0bf95d

Packit 0bf95d
=over 4
Packit 0bf95d

Packit 0bf95d
=item examples/zipcheck.pl shows how to use an attempted extraction to test a file.
Packit 0bf95d

Packit 0bf95d
=item examples/ziptest.pl shows how to test CRCs in a file.
Packit 0bf95d

Packit 0bf95d
=back
Packit 0bf95d

Packit 0bf95d
=head1 Duplicate files in Zip?
Packit 0bf95d

Packit 0bf95d
B<Q:> Archive::Zip let me put the same file in my Zip twice! Why don't you prevent this?
Packit 0bf95d

Packit 0bf95d
B<A:> As far as I can tell, this is not disallowed by the Zip spec. If you
Packit 0bf95d
think it's a bad idea, check for it yourself:
Packit 0bf95d

Packit 0bf95d
  $zip->addFile($someFile, $someName) unless $zip->memberNamed($someName);
Packit 0bf95d

Packit 0bf95d
I can even imagine cases where this might be useful (for instance, multiple
Packit 0bf95d
versions of files).
Packit 0bf95d

Packit 0bf95d
=head1 File ownership/permissions/ACLS/etc
Packit 0bf95d

Packit 0bf95d
B<Q:> Why doesn't Archive::Zip deal with file ownership, ACLs, etc.?
Packit 0bf95d

Packit 0bf95d
B<A:> There is no standard way to represent these in the Zip file format. If
Packit 0bf95d
you want to send me code to properly handle the various extra fields that
Packit 0bf95d
have been used to represent these through the years, I'll look at it.
Packit 0bf95d

Packit 0bf95d
=head1 I can't compile but ActiveState only has an old version of Archive::Zip
Packit 0bf95d

Packit 0bf95d
B<Q:> I've only installed modules using ActiveState's PPM program and
Packit 0bf95d
repository. But they have a much older version of Archive::Zip than is in CPAN. Will
Packit 0bf95d
you send me a newer PPM?
Packit 0bf95d

Packit 0bf95d
B<A:> Probably not, unless I get lots of extra time. But there's no reason you
Packit 0bf95d
can't install the version from CPAN. Archive::Zip is pure Perl, so all you need is
Packit 0bf95d
NMAKE, which you can get for free from Microsoft (see the FAQ in the
Packit 0bf95d
ActiveState documentation for details on how to install CPAN modules).
Packit 0bf95d

Packit 0bf95d
=head1 My JPEGs (or MP3's) don't compress when I put them into Zips!
Packit 0bf95d

Packit 0bf95d
B<Q:> How come my JPEGs and MP3's don't compress much when I put them into Zips?
Packit 0bf95d

Packit 0bf95d
B<A:> Because they're already compressed.
Packit 0bf95d

Packit 0bf95d
=head1 Under Windows, things lock up/get damaged
Packit 0bf95d

Packit 0bf95d
B<Q:> I'm using Windows. When I try to use Archive::Zip, my machine locks up/makes
Packit 0bf95d
funny sounds/displays a BSOD/corrupts data. How can I fix this?
Packit 0bf95d

Packit 0bf95d
B<A:> First, try the newest version of Compress::Raw::Zlib. I know of
Packit 0bf95d
Windows-related problems prior to v1.14 of that library.
Packit 0bf95d

Packit 0bf95d
=head1 Zip contents in a scalar
Packit 0bf95d

Packit 0bf95d
B<Q:> I want to read a Zip file from (or write one to) a scalar variable instead
Packit 0bf95d
of a file. How can I do this?
Packit 0bf95d

Packit 0bf95d
B<A:> Use C<IO::String> and the C<readFromFileHandle()> and
Packit 0bf95d
C<writeToFileHandle()> methods.
Packit 0bf95d
See C<examples/readScalar.pl> and C<examples/writeScalar.pl>.
Packit 0bf95d

Packit 0bf95d
=head1 Reading from streams
Packit 0bf95d

Packit 0bf95d
B<Q:> How do I read from a stream (like for the Info-Zip C<funzip> program)?
Packit 0bf95d

Packit 0bf95d
B<A:> This is not currently supported, though writing to a stream is.