summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/calcSizes.pl31
-rw-r--r--examples/copy.pl17
-rw-r--r--examples/extract.pl39
-rw-r--r--examples/mailZip.pl69
-rw-r--r--examples/mfh.pl28
-rw-r--r--examples/readScalar.pl26
-rw-r--r--examples/selfex.pl66
-rw-r--r--examples/unzipAll.pl29
-rw-r--r--examples/updateTree.pl33
-rw-r--r--examples/updateZip.pl33
-rw-r--r--examples/writeScalar.pl22
-rw-r--r--examples/writeScalar2.pl22
-rw-r--r--examples/zip.pl26
-rw-r--r--examples/zipGrep.pl52
-rw-r--r--examples/zipcheck.pl35
-rw-r--r--examples/zipinfo.pl142
-rw-r--r--examples/ziprecent.pl308
-rw-r--r--examples/ziptest.pl76
18 files changed, 1054 insertions, 0 deletions
diff --git a/examples/calcSizes.pl b/examples/calcSizes.pl
new file mode 100644
index 0000000..9fd9e0b
--- /dev/null
+++ b/examples/calcSizes.pl
@@ -0,0 +1,31 @@
+# Example of how to compute compressed sizes
+# $Revision: 1.2 $
+use strict;
+use Archive::Zip qw(:ERROR_CODES);
+use File::Spec;
+my $zip = Archive::Zip->new();
+my $blackHoleDevice = File::Spec->devnull();
+
+$zip->addFile($_) foreach (<*.pl>);
+
+# Write and throw the data away.
+# after members are written, the writeOffset will be set
+# to the compressed size.
+$zip->writeToFileNamed($blackHoleDevice);
+
+my $totalSize = 0;
+my $totalCompressedSize = 0;
+foreach my $member ($zip->members()) {
+ $totalSize += $member->uncompressedSize;
+ $totalCompressedSize += $member->_writeOffset;
+ print "Member ", $member->externalFileName,
+ " size=", $member->uncompressedSize,
+ ", writeOffset=", $member->_writeOffset,
+ ", compressed=", $member->compressedSize,
+ "\n";
+}
+
+print "Total Size=", $totalSize, ", total compressed=", $totalCompressedSize,
+ "\n";
+
+$zip->writeToFileNamed('test.zip');
diff --git a/examples/copy.pl b/examples/copy.pl
new file mode 100644
index 0000000..47c74e5
--- /dev/null
+++ b/examples/copy.pl
@@ -0,0 +1,17 @@
+# Copies a zip file to another.
+# Usage:
+# perl copy.pl input.zip output.zip
+# $Revision: 1.4 $
+
+use Archive::Zip qw(:ERROR_CODES);
+
+die "usage: perl copy.pl input.zip output.zip\n"
+ if scalar(@ARGV) != 2;
+
+my $zip = Archive::Zip->new();
+
+my $status = $zip->read($ARGV[0]);
+die("read $ARGV[0] failed: $status\n") if $status != AZ_OK;
+
+$status = $zip->writeToFileNamed($ARGV[1]);
+die("writeToFileNamed $ARGV[1] failed: $status\n") if $status != AZ_OK;
diff --git a/examples/extract.pl b/examples/extract.pl
new file mode 100644
index 0000000..528ec5f
--- /dev/null
+++ b/examples/extract.pl
@@ -0,0 +1,39 @@
+#!/bin/perl -w
+# Extracts the named files into 'extractTest' subdir
+# usage:
+# perl extract.pl [-j] zipfile.zip filename [...]
+# if -j option given, discards paths.
+#
+# $Revision: 1.5 $
+#
+use strict;
+
+my $dirName = 'extractTest';
+
+use vars qw( $opt_j );
+use Archive::Zip qw(:ERROR_CODES);
+use Getopt::Std;
+
+$opt_j = 0;
+getopts('j');
+
+if (@ARGV < 2) {
+ die <<EOF
+ usage: perl extract.pl [-j] zipfile.zip filename [...]
+ if -j option given, discards paths.
+EOF
+}
+
+my $zip = Archive::Zip->new();
+my $zipName = shift(@ARGV);
+my $status = $zip->read($zipName);
+die "Read of $zipName failed\n" if $status != AZ_OK;
+
+foreach my $memberName (@ARGV) {
+ print "Extracting $memberName\n";
+ $status =
+ $opt_j
+ ? $zip->extractMemberWithoutPaths($memberName)
+ : $zip->extractMember($memberName);
+ die "Extracting $memberName from $zipName failed\n" if $status != AZ_OK;
+}
diff --git a/examples/mailZip.pl b/examples/mailZip.pl
new file mode 100644
index 0000000..4e043aa
--- /dev/null
+++ b/examples/mailZip.pl
@@ -0,0 +1,69 @@
+#!/usr/bin/perl -w
+# Requires the following to be installed:
+# File::Path
+# File::Spec
+# IO::Scalar, ... from the IO-stringy distribution
+# MIME::Base64
+# MIME::QuotedPrint
+# Net::SMTP
+# Mail::Internet, ... from the MailTools distribution.
+# MIME::Tools
+
+use strict;
+use Archive::Zip qw(:CONSTANTS :ERROR_CODES);
+use IO::Scalar;
+use MIME::Entity; # part of MIME::Tools package
+
+my $zipContents = '';
+my $SH = IO::Scalar->new(\$zipContents);
+
+my $zip = Archive::Zip->new();
+my $member;
+
+# add a string as a member:
+my $stringMember = '<html><head></head><body><h1>Testing</h1></body></html>';
+$member = $zip->addString($stringMember, 'whatever.html');
+
+# $member->desiredCompressionMethod(COMPRESSION_STORED);
+
+# write it to the scalar
+my $status = $zip->writeToFileHandle($SH);
+$SH->close;
+
+print STDERR "zip is " . length($zipContents) . " bytes long\n";
+
+### Create an entity:
+my $top = MIME::Entity->build(
+ Type => 'multipart/mixed',
+ From => 'ned@bike-nomad.com',
+ To => 'billnevin@tricom.net',
+ Subject => "Your zip",
+);
+
+# attach the message
+$top->attach(
+ Encoding => '7bit',
+ Data => "here is the zip you ordered\n"
+);
+
+# attach the zip
+$top->attach(
+ Data => \$zipContents,
+ Type => "application/x-zip",
+ Encoding => "base64",
+ Disposition => 'attachment',
+ Filename => 'your.zip'
+);
+
+# attach this code
+$top->attach(
+ Encoding => '8bit',
+ Type => 'text/plain',
+ Path => $0,
+
+ # Data => 'whatever',
+ Disposition => 'inline'
+);
+
+# and print it out to stdout
+$top->print(\*STDOUT);
diff --git a/examples/mfh.pl b/examples/mfh.pl
new file mode 100644
index 0000000..21ce421
--- /dev/null
+++ b/examples/mfh.pl
@@ -0,0 +1,28 @@
+# Prints messages on every chunk write.
+# Usage:
+# perl mfh.pl zipfile.zip
+# $Revision: 1.4 $
+use strict;
+use Archive::Zip qw(:ERROR_CODES);
+use Archive::Zip::MockFileHandle;
+
+package NedsFileHandle;
+use vars qw(@ISA);
+@ISA = qw( Archive::Zip::MockFileHandle );
+
+sub writeHook {
+ my $self = shift;
+ my $bytes = shift;
+ my $length = length($bytes);
+ printf "write %d bytes (position now %d)\n", $length, $self->tell();
+ return $length;
+}
+
+package main;
+
+my $zip = Archive::Zip->new();
+my $status = $zip->read($ARGV[0]);
+exit $status if $status != AZ_OK;
+
+my $fh = NedsFileHandle->new();
+$zip->writeToFileHandle($fh, 0);
diff --git a/examples/readScalar.pl b/examples/readScalar.pl
new file mode 100644
index 0000000..58dac47
--- /dev/null
+++ b/examples/readScalar.pl
@@ -0,0 +1,26 @@
+#!/usr/bin/perl -w
+# Demonstrates reading a zip from an IO::Scalar
+# $Revision: 1.4 $
+use strict;
+use Archive::Zip qw(:CONSTANTS :ERROR_CODES);
+use IO::Scalar;
+use IO::File;
+
+# test reading from a scalar
+my $file = IO::File->new('testin.zip', 'r');
+my $zipContents;
+binmode($file);
+$file->read($zipContents, 20000);
+$file->close();
+printf "Read %d bytes\n", length($zipContents);
+
+my $SH = IO::Scalar->new(\$zipContents);
+
+my $zip = Archive::Zip->new();
+$zip->readFromFileHandle($SH);
+my $member = $zip->addString('c' x 300, 'bunchOfCs.txt');
+$member->desiredCompressionMethod(COMPRESSION_DEFLATED);
+$member = $zip->addString('d' x 300, 'bunchOfDs.txt');
+$member->desiredCompressionMethod(COMPRESSION_DEFLATED);
+
+$zip->writeToFileNamed('test2.zip');
diff --git a/examples/selfex.pl b/examples/selfex.pl
new file mode 100644
index 0000000..7876a96
--- /dev/null
+++ b/examples/selfex.pl
@@ -0,0 +1,66 @@
+#/usr/bin/perl -w
+#
+# Shows one way to write a self-extracting archive file.
+# This is not intended for production use, and it always extracts to a
+# subdirectory with a fixed name.
+# Plus, it requires Perl and A::Z to be installed first.
+#
+# In general, you want to provide a stub that is platform-specific.
+# You can use 'unzipsfx' that it provided with the Info-Zip unzip program.
+# Get this from http://www.info-zip.org .
+#
+# $Revision: 1.6 $
+#
+use strict;
+
+use Archive::Zip;
+use IO::File;
+
+# Make a self-extracting Zip file.
+
+die "usage: $0 sfxname file [...]\n" unless @ARGV > 1;
+
+my $outputName = shift();
+
+my $zip = Archive::Zip->new();
+
+foreach my $file (@ARGV) {
+ $zip->addFileOrDirectory($file);
+}
+
+my $fh = IO::File->new($outputName, O_CREAT | O_WRONLY | O_TRUNC, 0777)
+ or die "Can't open $outputName\: $!\n";
+binmode($fh);
+
+# add self-extracting Perl code
+
+while (<DATA>) {
+ $fh->print($_)
+}
+
+$zip->writeToFileHandle($fh);
+
+$fh->close();
+
+# below the __DATA__ line is the extraction stub:
+__DATA__
+#!/usr/local/bin/perl
+# Self-extracting Zip file extraction stub
+# Copyright (C) 2002 Ned Konz
+
+use Archive::Zip qw(:ERROR_CODES);
+use IO::File;
+use File::Spec;
+
+my $dir = 'extracted';
+my $zip = Archive::Zip->new();
+my $fh = IO::File->new($0) or die "Can't open $0\: $!\n";
+die "Zip read error\n" unless $zip->readFromFileHandle($fh) == AZ_OK;
+
+(mkdir($dir, 0777) or die "Can't create directory $dir\: $!\n") unless -d $dir;
+
+for my $member ( $zip->members )
+{
+ $member->extractToFileNamed( File::Spec->catfile($dir,$member->fileName) );
+}
+__DATA__
diff --git a/examples/unzipAll.pl b/examples/unzipAll.pl
new file mode 100644
index 0000000..02f35d9
--- /dev/null
+++ b/examples/unzipAll.pl
@@ -0,0 +1,29 @@
+#!/bin/perl -w
+# Extracts all files from the given zip
+# $Revision: 1.3 $
+# usage:
+# perl unzipAll.pl [-j] zipfile.zip
+# if -j option given, discards paths.
+#
+use strict;
+
+use vars qw( $opt_j );
+use Archive::Zip qw(:ERROR_CODES);
+use Getopt::Std;
+
+$opt_j = 0;
+getopts('j');
+
+if (@ARGV < 1) {
+ die <<EOF
+ usage: perl $0 [-j] zipfile.zip
+ if -j option given, discards paths.
+EOF
+}
+
+my $zip = Archive::Zip->new();
+my $zipName = shift(@ARGV);
+my $status = $zip->read($zipName);
+die "Read of $zipName failed\n" if $status != AZ_OK;
+
+$zip->extractTree();
diff --git a/examples/updateTree.pl b/examples/updateTree.pl
new file mode 100644
index 0000000..5ba98c3
--- /dev/null
+++ b/examples/updateTree.pl
@@ -0,0 +1,33 @@
+# Shows how to update a Zip in place using a temp file.
+#
+# usage:
+# perl [-m] examples/updateTree.pl zipfile.zip dirname
+#
+# -m means to mirror
+#
+# $Id: updateTree.pl,v 1.2 2003/11/27 17:03:51 ned Exp $
+#
+use Archive::Zip qw(:ERROR_CODES);
+
+my $mirror = 0;
+if ($ARGV[0] eq '-m') { shift; $mirror = 1; }
+
+my $zipName = shift || die 'must provide a zip name';
+my $dirName = shift || die 'must provide a directory name';
+
+# Read the zip
+my $zip = Archive::Zip->new();
+
+if (-f $zipName) {
+ die "can't read $zipName\n" unless $zip->read($zipName) == AZ_OK;
+
+ # Update the zip
+ $zip->updateTree($dirName, undef, undef, $mirror);
+
+ # Now the zip is updated. Write it back via a temp file.
+ exit($zip->overwrite());
+} else # new zip
+{
+ $zip->addTree($dirName);
+ exit($zip->writeToFileNamed($zipName));
+}
diff --git a/examples/updateZip.pl b/examples/updateZip.pl
new file mode 100644
index 0000000..6b87d23
--- /dev/null
+++ b/examples/updateZip.pl
@@ -0,0 +1,33 @@
+# Shows how to update a Zip in place using a temp file.
+# $Revision: 1.1 $
+#
+use Archive::Zip qw(:ERROR_CODES);
+use File::Copy();
+
+my $zipName = shift || die 'must provide a zip name';
+my @fileNames = @ARGV;
+die 'must provide file names' unless scalar(@fileNames);
+
+# Read the zip
+my $zip = Archive::Zip->new();
+die "can't read $zipName\n" unless $zip->read($zipName) == AZ_OK;
+
+# Update the zip
+foreach my $file (@fileNames) {
+ $zip->removeMember($file);
+ if (-r $file) {
+ if (-f $file) {
+ $zip->addFile($file) or die "Can't add $file to zip!\n";
+ } elsif (-d $file) {
+ $zip->addDirectory($file) or die "Can't add $file to zip!\n";
+ } else {
+ warn "Don't know how to add $file\n";
+ }
+ } else {
+ warn "Can't read $file\n";
+ }
+}
+
+# Now the zip is updated. Write it back via a temp file.
+
+exit($zip->overwrite());
diff --git a/examples/writeScalar.pl b/examples/writeScalar.pl
new file mode 100644
index 0000000..aa1aa98
--- /dev/null
+++ b/examples/writeScalar.pl
@@ -0,0 +1,22 @@
+#!/usr/bin/perl -w
+use strict;
+use Archive::Zip qw(:CONSTANTS :ERROR_CODES);
+use IO::Scalar;
+use IO::File;
+
+# test writing to a scalar
+my $zipContents = '';
+my $SH = IO::Scalar->new(\$zipContents);
+
+my $zip = Archive::Zip->new();
+my $member = $zip->addString('a' x 300, 'bunchOfAs.txt');
+$member->desiredCompressionMethod(COMPRESSION_DEFLATED);
+$member = $zip->addString('b' x 300, 'bunchOfBs.txt');
+$member->desiredCompressionMethod(COMPRESSION_DEFLATED);
+my $status = $zip->writeToFileHandle($SH);
+
+my $file = IO::File->new('test.zip', 'w');
+binmode($file);
+$file->print($zipContents);
+$file->close();
+
diff --git a/examples/writeScalar2.pl b/examples/writeScalar2.pl
new file mode 100644
index 0000000..dab44c5
--- /dev/null
+++ b/examples/writeScalar2.pl
@@ -0,0 +1,22 @@
+#!/usr/bin/perl -w
+use strict;
+use Archive::Zip qw(:CONSTANTS :ERROR_CODES);
+use IO::String;
+use IO::File;
+
+# test writing to a scalar
+my $zipContents = '';
+my $SH = IO::String->new($zipContents);
+
+my $zip = Archive::Zip->new();
+my $member = $zip->addString('a' x 300, 'bunchOfAs.txt');
+$member->desiredCompressionMethod(COMPRESSION_DEFLATED);
+$member = $zip->addString('b' x 300, 'bunchOfBs.txt');
+$member->desiredCompressionMethod(COMPRESSION_DEFLATED);
+my $status = $zip->writeToFileHandle($SH);
+
+my $file = IO::File->new('test.zip', 'w');
+binmode($file);
+$file->print($zipContents);
+$file->close();
+
diff --git a/examples/zip.pl b/examples/zip.pl
new file mode 100644
index 0000000..a3811d1
--- /dev/null
+++ b/examples/zip.pl
@@ -0,0 +1,26 @@
+#!/bin/perl -w
+# Creates a zip file, adding the given directories and files.
+# Usage:
+# perl zip.pl zipfile.zip file [...]
+
+use strict;
+use Archive::Zip qw(:ERROR_CODES :CONSTANTS);
+
+die "usage: $0 zipfile.zip file [...]\n"
+ if (scalar(@ARGV) < 2);
+
+my $zipName = shift(@ARGV);
+my $zip = Archive::Zip->new();
+
+foreach my $memberName (map { glob } @ARGV) {
+ if (-d $memberName) {
+ warn "Can't add tree $memberName\n"
+ if $zip->addTree($memberName, $memberName) != AZ_OK;
+ } else {
+ $zip->addFile($memberName)
+ or warn "Can't add file $memberName\n";
+ }
+}
+
+my $status = $zip->writeToFileNamed($zipName);
+exit $status;
diff --git a/examples/zipGrep.pl b/examples/zipGrep.pl
new file mode 100644
index 0000000..b9f07b8
--- /dev/null
+++ b/examples/zipGrep.pl
@@ -0,0 +1,52 @@
+#!/usr/bin/perl -w
+# This program searches for the given Perl regular expression in a Zip archive.
+# Archive is assumed to contain text files.
+# By Ned Konz, perl@bike-nomad.com
+# Usage:
+# perl zipGrep.pl 'pattern' myZip.zip
+#
+use strict;
+use Archive::Zip qw(:CONSTANTS :ERROR_CODES);
+
+if (@ARGV != 2) {
+ print <<EOF;
+This program searches for the given Perl regular expression in a Zip archive.
+Archive is assumed to contain text files.
+Usage:
+ perl $0 'pattern' myZip.zip
+EOF
+ exit 1;
+}
+
+my $pattern = shift;
+$pattern = qr{$pattern}; # compile the regular expression
+my $zipName = shift;
+
+my $zip = Archive::Zip->new();
+if ($zip->read($zipName) != AZ_OK) {
+ die "Read error reading $zipName\n";
+}
+
+foreach my $member ($zip->members()) {
+ my ($bufferRef, $status, $lastChunk);
+ my $memberName = $member->fileName();
+ my $lineNumber = 1;
+ $lastChunk = '';
+ $member->desiredCompressionMethod(COMPRESSION_STORED);
+ $status = $member->rewindData();
+ die "rewind error $status" if $status != AZ_OK;
+
+ while (!$member->readIsDone()) {
+ ($bufferRef, $status) = $member->readChunk();
+ die "readChunk error $status"
+ if $status != AZ_OK && $status != AZ_STREAM_END;
+
+ my $buffer = $lastChunk . $$bufferRef;
+ while ($buffer =~ m{(.*$pattern.*\n)}mg) {
+ print "$memberName:$1";
+ }
+ ($lastChunk) = $$bufferRef =~ m{([^\n\r]+)\z};
+ }
+
+ $member->endRead();
+}
diff --git a/examples/zipcheck.pl b/examples/zipcheck.pl
new file mode 100644
index 0000000..3d7dccc
--- /dev/null
+++ b/examples/zipcheck.pl
@@ -0,0 +1,35 @@
+#!/bin/perl -w
+# usage: valid zipname.zip
+# exits with non-zero status if invalid zip
+# status = 1: invalid arguments
+# status = 2: generic error somewhere
+# status = 3: format error
+# status = 4: IO error
+use strict;
+use Archive::Zip qw(:ERROR_CODES);
+use IO::Handle;
+use File::Spec;
+
+# instead of stack dump:
+Archive::Zip::setErrorHandler(sub { warn shift() });
+
+my $nullFileName = File::Spec->devnull();
+my $zip = Archive::Zip->new();
+my $zipName = shift(@ARGV) || exit 1;
+eval {
+ my $status = $zip->read($zipName);
+ exit $status if $status != AZ_OK;
+};
+if ($@) { warn 'error reading zip:', $@, "\n"; exit 2 }
+
+eval {
+ foreach my $member ($zip->members) {
+ my $fh = IO::File->new();
+ $fh->open(">$nullFileName") || die "can't open $nullFileName\: $!\n";
+ my $status = $member->extractToFileHandle($fh);
+ if ($status != AZ_OK) {
+ warn "Extracting ", $member->fileName(), " from $zipName failed\n";
+ exit $status;
+ }
+ }
+}
diff --git a/examples/zipinfo.pl b/examples/zipinfo.pl
new file mode 100644
index 0000000..8433493
--- /dev/null
+++ b/examples/zipinfo.pl
@@ -0,0 +1,142 @@
+#! /usr/bin/perl -w
+# Print out information about a ZIP file.
+# Note that this buffers the entire file into memory!
+# usage:
+# perl examples/zipinfo.pl zipfile.zip
+
+use strict;
+
+use Data::Dumper ();
+use FileHandle;
+use Archive::Zip qw(:ERROR_CODES :CONSTANTS :PKZIP_CONSTANTS);
+use Archive::Zip::BufferedFileHandle;
+
+$| = 1;
+
+### Workaround for a bug in version of Data::Dumper bundled
+### with some versions of Perl, which causes warnings when
+### calling ->Seen below.
+if (defined &Data::Dumper::init_refaddr_format) {
+ Data::Dumper::init_refaddr_format();
+}
+
+# use constant END_OF_CENTRAL_DIRECTORY_SIGNATURE_STRING;
+use constant CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE_STRING =>
+ pack(SIGNATURE_FORMAT, CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE);
+use constant LOCAL_FILE_HEADER_SIGNATURE_STRING =>
+ pack(SIGNATURE_FORMAT, LOCAL_FILE_HEADER_SIGNATURE);
+
+$Data::Dumper::Useqq = 1; # enable double-quotes for string values
+$Data::Dumper::Indent = 1;
+
+my $zip = Archive::Zip->new();
+my $zipFileName = shift(@ARGV);
+
+my $fh = Archive::Zip::BufferedFileHandle->new();
+$fh->readFromFile($zipFileName) or exit($!);
+
+my $status = $zip->_findEndOfCentralDirectory($fh);
+die("can't find EOCD\n") if $status != AZ_OK;
+
+my $eocdPosition = $fh->tell();
+
+$status = $zip->_readEndOfCentralDirectory($fh);
+die("can't read EOCD\n") if $status != AZ_OK;
+
+my $zipDumper = Data::Dumper->new([$zip], ['ZIP']);
+$zipDumper->Seen({ref($fh), $fh});
+print $zipDumper->Dump(), "\n";
+
+my $expectedEOCDPosition =
+ $zip->centralDirectoryOffsetWRTStartingDiskNumber() +
+ $zip->centralDirectorySize();
+
+my $eocdOffset = $zip->{eocdOffset} = $eocdPosition - $expectedEOCDPosition;
+
+if ($eocdOffset) {
+ printf "Expected EOCD at %d (0x%x) but found it at %d (0x%x)\n",
+ ($expectedEOCDPosition) x 2, ($eocdPosition) x 2;
+} else {
+ printf("Found EOCD at %d (0x%x)\n\n", ($eocdPosition) x 2);
+}
+
+my $contents = $fh->contents();
+my $offset = $eocdPosition + $eocdOffset - 1;
+my $cdPos;
+my @members;
+my $numberOfMembers = $zip->numberOfCentralDirectoriesOnThisDisk();
+foreach my $n (0 .. $numberOfMembers - 1) {
+ my $index = $numberOfMembers - $n;
+ $cdPos = rindex($contents,
+ CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE_STRING, $offset);
+ if ($cdPos < 0) {
+ print "No central directory found for member #$index\n";
+ last;
+ } else {
+ print "Found central directory for member #$index at $cdPos\n";
+ $fh->seek($cdPos + SIGNATURE_LENGTH, 0); # SEEK_SET
+ my $newMember =
+ Archive::Zip::Member->_newFromZipFile($fh, "($zipFileName)");
+ $status = $newMember->_readCentralDirectoryFileHeader();
+ if ($status != AZ_OK and $status != AZ_STREAM_END) {
+ printf "read CD header status=%d\n", $status;
+ last;
+ }
+ unshift(@members, $newMember);
+
+ my $memberDumper =
+ Data::Dumper->new([$newMember], ['CDMEMBER' . $index]);
+ $memberDumper->Seen({ref($fh), $fh});
+ print $memberDumper->Dump(), "\n";
+ }
+ $offset = $cdPos - 1;
+}
+
+if ( $cdPos >= 0
+ and $cdPos != $zip->centralDirectoryOffsetWRTStartingDiskNumber()) {
+ printf
+ "Expected to find central directory at %d (0x%x), but found it at %d (0x%x)\n",
+ ($zip->centralDirectoryOffsetWRTStartingDiskNumber()) x 2,
+ ($cdPos) x 2;
+}
+
+print "\n";
+
+# Now read the local headers
+
+foreach my $n (0 .. $#members) {
+ my $member = $members[$n];
+ $fh->seek(
+ $member->localHeaderRelativeOffset() + $eocdOffset + SIGNATURE_LENGTH,
+ 0);
+ $status = $member->_readLocalFileHeader();
+ if ($status != AZ_OK and $status != AZ_STREAM_END) {
+ printf "member %d read header status=%d\n", $n + 1, $status;
+ last;
+ }
+
+ my $memberDumper = Data::Dumper->new([$member], ['LHMEMBER' . ($n + 1)]);
+ $memberDumper->Seen({ref($fh), $fh});
+ print $memberDumper->Dump(), "\n";
+
+ my $endOfMember =
+ $member->localHeaderRelativeOffset() +
+ $member->_localHeaderSize() +
+ $member->compressedSize();
+
+ if (
+ $endOfMember > $cdPos
+ or ( $n < $#members
+ and $endOfMember > $members[$n + 1]->localHeaderRelativeOffset())
+ ) {
+ print "Error: ";
+ }
+ printf("End of member: %d, CD at %d", $endOfMember, $cdPos);
+ if ($n < $#members) {
+ printf(", next member starts at %d",
+ $members[$n + 1]->localHeaderRelativeOffset());
+ }
+ print("\n\n");
+}
+
+# vim: ts=4 sw=4
diff --git a/examples/ziprecent.pl b/examples/ziprecent.pl
new file mode 100644
index 0000000..9345349
--- /dev/null
+++ b/examples/ziprecent.pl
@@ -0,0 +1,308 @@
+#!/usr/bin/perl -w
+# Makes a zip file of the most recent files in a specified directory.
+# By Rudi Farkas, rudif@bluemail.ch, 9 December 2000
+# Usage:
+# ziprecent <dir> -d <ageDays> [-e <ext> ...]> [-h] [-msvc] [-q] [<zippath>]
+# Zips files in source directory and its subdirectories
+# whose file extension is in specified extensions (default: any extension).
+# -d <days> max age (days) for files to be zipped (default: 1 day)
+# <dir> source directory
+# -e <ext> one or more space-separated extensions
+# -h print help text and exit
+# -msvc may be given instead of -e and will zip all msvc source files
+# -q query only (list files but don't zip)
+# <zippath>.zip path to zipfile to be created (or updated if it exists)
+#
+# $Revision: 1.2 $
+
+use strict;
+
+use Archive::Zip qw(:ERROR_CODES :CONSTANTS);
+use Cwd;
+use File::Basename;
+use File::Copy;
+use File::Find;
+use File::Path;
+
+# argument and variable defaults
+#
+my $maxFileAgeDays = 1;
+my $defaultzipdir = 'h:/zip/_homework';
+my ($sourcedir, $zipdir, $zippath, @extensions, $query);
+
+# usage
+#
+my $scriptname = basename $0;
+my $usage = <<ENDUSAGE;
+$scriptname <dir> -d <ageDays> [-e <ext> ...]> [-h] [-msvc] [-q] [<zippath>]
+Zips files in source directory and its subdirectories
+whose file extension is in specified extensions (default: any extension).
+ -d <days> max age (days) for files to be zipped (default: 1 day)
+ <dir> source directory
+ -e <ext> one or more space-separated extensions
+ -h print help text and exit
+ -msvc may be given instead of -e and will zip all msvc source files
+ -q query only (list files but don't zip)
+ <zippath>.zip path to zipfile to be created (or updated if it exists)
+ENDUSAGE
+
+# parse arguments
+#
+while (@ARGV) {
+ my $arg = shift;
+
+ if ($arg eq '-d') {
+ $maxFileAgeDays = shift;
+ $maxFileAgeDays = 0.0 if $maxFileAgeDays < 0.0;
+ } elsif ($arg eq '-e') {
+ while ($ARGV[0] && $ARGV[0] !~ /^-/) {
+ push @extensions, shift;
+ }
+ } elsif ($arg eq '-msvc') {
+ push @extensions,
+ qw / bmp c cpp def dlg dsp dsw h ico idl mak odl rc rc2 rgs /;
+ } elsif ($arg eq '-q') {
+ $query = 1;
+ } elsif ($arg eq '-h') {
+ print STDERR $usage;
+ exit;
+ } elsif (-d $arg) {
+ $sourcedir = $arg;
+ } elsif ($arg eq '-z') {
+ if ($ARGV[0]) {
+ $zipdir = shift;
+ }
+ } elsif ($arg =~ /\.zip$/) {
+ $zippath = $arg;
+ } else {
+ errorExit("Unknown option or argument: $arg");
+ }
+}
+
+# process arguments
+#
+errorExit("Please specify an existing source directory")
+ unless defined($sourcedir) && -d $sourcedir;
+
+my $extensions;
+if (@extensions) {
+ $extensions = join "|", @extensions;
+} else {
+ $extensions = ".*";
+}
+
+# change '\' to '/' (avoids trouble in substitution on Win2k)
+#
+$sourcedir =~ s|\\|/|g;
+$zippath =~ s|\\|/|g if defined($zippath);
+
+# find files
+#
+my @files;
+cwd $sourcedir;
+find(\&listFiles, $sourcedir);
+printf STDERR "Found %d file(s)\n", scalar @files;
+
+# exit ?
+#
+exit if $query;
+exit if @files <= 0;
+
+# prepare zip directory
+#
+if (defined($zippath)) {
+
+ # deduce directory from zip path
+ $zipdir = dirname($zippath);
+ $zipdir = '.' unless length $zipdir;
+} else {
+ $zipdir = $defaultzipdir;
+}
+
+# make sure that zip directory exists
+#
+mkpath $zipdir unless -d $zipdir;
+-d $zipdir or die "Can't find/make directory $zipdir\n";
+
+# create the zip object
+#
+my $zip = Archive::Zip->new();
+
+# read-in the existing zip file if any
+#
+if (defined $zippath && -f $zippath) {
+ my $status = $zip->read($zippath);
+ warn "Read $zippath failed\n" if $status != AZ_OK;
+}
+
+# add files
+#
+foreach my $memberName (@files) {
+ if (-d $memberName) {
+ warn "Can't add tree $memberName\n"
+ if $zip->addTree($memberName, $memberName) != AZ_OK;
+ } else {
+ $zip->addFile($memberName)
+ or warn "Can't add file $memberName\n";
+ }
+}
+
+# prepare the new zip path
+#
+my $newzipfile = genfilename();
+my $newzippath = "$zipdir/$newzipfile";
+
+# write the new zip file
+#
+my $status = $zip->writeToFileNamed($newzippath);
+if ($status == AZ_OK) {
+
+ # rename (and overwrite the old zip file if any)?
+ #
+ if (defined $zippath) {
+ my $res = rename $newzippath, $zippath;
+ if ($res) {
+ print STDERR "Updated file $zippath\n";
+ } else {
+ print STDERR
+ "Created file $newzippath, failed to rename to $zippath\n";
+ }
+ } else {
+ print STDERR "Created file $newzippath\n";
+ }
+} else {
+ print STDERR "Failed to create file $newzippath\n";
+}
+
+# subroutines
+#
+
+sub listFiles {
+ if (/\.($extensions)$/) {
+ cwd $File::Find::dir;
+ return if -d $File::Find::name; # skip directories
+ my $fileagedays = fileAgeDays($_);
+ if ($fileagedays < $maxFileAgeDays) {
+ printf STDERR "$File::Find::name (%.3g)\n", $fileagedays;
+ (my $filename = $File::Find::name) =~
+ s/^[a-zA-Z]://; # remove the leading drive letter:
+ push @files, $filename;
+ }
+ }
+}
+
+sub errorExit {
+ printf STDERR "*** %s ***\n$usage\n", shift;
+ exit;
+}
+
+sub mtime {
+ (stat shift)[9];
+}
+
+sub fileAgeDays {
+ (time() - mtime(shift)) / 86400;
+}
+
+sub genfilename {
+ my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) =
+ localtime(time);
+ sprintf "%04d%02d%02d-%02d%02d%02d.zip", $year + 1900, $mon + 1, $mday,
+ $hour, $min, $sec;
+}
+
+__END__
+
+=head1 NAME
+
+ziprecent.pl
+
+=head1 SYNOPSIS
+
+ ziprecent h:/myperl
+
+ ziprecent h:/myperl -e pl pm -d 365
+
+ ziprecent h:/myperl -q
+
+ ziprecent h:/myperl h:/temp/zip/file1.zip
+
+
+=head1 DESCRIPTION
+
+This script helps to collect recently modified files in a source directory
+into a zip file (new or existing).
+
+It uses Archive::Zip.
+
+=over 4
+
+=item C< ziprecent h:/myperl >
+
+Lists and zips all files more recent than 1 day (24 hours)
+in directory h:/myperl and it's subdirectories,
+and places the zip file into default zip directory.
+The generated zip file name is based on local time (e.g. 20001208-231237.zip).
+
+
+=item C< ziprecent h:/myperl -e pl pm -d 365 >
+
+Zips only .pl and .pm files more recent than one year.
+
+
+=item C< ziprecent h:/myperl -msvc >
+
+Zips source files found in a typical MSVC project.
+
+
+=item C< ziprecent h:/myperl -q >
+
+Lists files that should be zipped.
+
+
+=item C< ziprecent h:/myperl h:/temp/zip/file1.zip >
+
+Updates file named h:/temp/zip/file1.zip
+(overwrites an existing file if writable).
+
+
+=item C< ziprecent -h >
+
+Prints the help text and exits.
+
+ ziprecent.pl <dir> -d <days> [-e <ext> ...]> [-h] [-msvc] [-q] [<zippath>]
+ Zips files in source directory and its subdirectories
+ whose file extension is in specified extensions (default: any extension).
+ -d <days> max age (days) for files to be zipped (default: 1 day)
+ <dir> source directory
+ -e <ext> one or more space-separated extensions
+ -h print help text and exit
+ -msvc may be given instead of -e and will zip all msvc source files
+ -q query only (list files but don't zip)
+ <zippath>.zip path to zipfile to be created (or updated if it exists)
+
+=back
+
+
+=head1 BUGS
+
+Tested only on Win2k.
+
+Does not handle filenames without extension.
+
+Does not accept more than one source directory (workaround: invoke separately
+for each directory, specifying the same zip file).
+
+
+=head1 AUTHOR
+
+Rudi Farkas rudif@lecroy.com rudif@bluemail.ch
+
+=head1 SEE ALSO
+
+perl ;-)
+
+=cut
+
+
+
diff --git a/examples/ziptest.pl b/examples/ziptest.pl
new file mode 100644
index 0000000..662adcc
--- /dev/null
+++ b/examples/ziptest.pl
@@ -0,0 +1,76 @@
+#!/bin/perl -w
+# $Revision: 1.7 $
+# Lists the zipfile given as a first argument and tests CRC's.
+# Usage:
+# perl ziptest.pl zipfile.zip
+
+use strict;
+
+use Archive::Zip qw(:ERROR_CODES :CONSTANTS);
+
+package CRCComputingFileHandle;
+use Archive::Zip::MockFileHandle;
+
+use vars qw( @ISA );
+@ISA = qw( Archive::Zip::MockFileHandle );
+
+my $crc;
+
+sub writeHook {
+ my $self = shift;
+ my $bytes = shift;
+ my $length = length($bytes);
+ $crc = Archive::Zip::computeCRC32($bytes, $crc);
+}
+
+sub resetCRC { $crc = 0 }
+
+sub crc { $crc }
+
+package main;
+
+die "usage: $0 zipfile.zip\n"
+ if (scalar(@ARGV) != 1);
+
+my $zip = Archive::Zip->new();
+my $status = $zip->read($ARGV[0]);
+exit $status if $status != AZ_OK;
+
+print " Length Size Last Modified CRC-32 Name\n";
+print "-------- -------- ------------------------ -------- ----\n";
+
+my $fh = CRCComputingFileHandle->new();
+my @errors;
+
+foreach my $member ($zip->members()) {
+ my $compressedSize = $member->compressedSize();
+ $fh->resetCRC();
+ $member->desiredCompressionMethod(COMPRESSION_STORED);
+ $status = $member->extractToFileHandle($fh);
+ exit $status if $status != AZ_OK;
+ my $crc = $fh->crc();
+
+ my $ct = scalar(localtime($member->lastModTime()));
+ chomp($ct);
+
+ printf(
+ "%8d %8d %s %08x %s\n",
+ $member->uncompressedSize(),
+ $compressedSize, $ct, $member->crc32(), $member->fileName());
+
+ if ($member->crc32() != $crc) {
+ push(
+ @errors,
+ sprintf(
+ "Member %s CRC error: file says %08x computed: %08x\n",
+ $member->fileName(), $member->crc32(), $crc
+ ));
+ }
+}
+
+if (scalar(@errors)) {
+ print join("\n", @errors);
+ die "CRC errors found\n";
+} else {
+ print "All CRCs check OK\n";
+}