Current File : //usr/tmp/par-streamof/cache-019bf52da828c7d4df54624dfe058723871c67b9/105b7f84.pm
#line 1 "/usr/local/lib/perl5/site_perl/5.8.8/Archive/Zip.pm"
package Archive::Zip;

use strict;
BEGIN {
	require 5.003_96;
}
use UNIVERSAL      ();
use Carp           ();
use IO::File       ();
use IO::Seekable   ();
use Compress::Zlib ();
use File::Spec     ();
use File::Temp     ();

use vars qw( $VERSION @ISA );
BEGIN {
	$VERSION = '1.23';

	require Exporter;
	@ISA = qw( Exporter );
}

use vars qw( $ChunkSize $ErrorHandler );
BEGIN {
	# This is the size we'll try to read, write, and (de)compress.
	# You could set it to something different if you had lots of memory
	# and needed more speed.
	$ChunkSize ||= 32768;

	$ErrorHandler = \&Carp::carp;
}

# BEGIN block is necessary here so that other modules can use the constants.
use vars qw( @EXPORT_OK %EXPORT_TAGS );
BEGIN {
	@EXPORT_OK   = ('computeCRC32');
	%EXPORT_TAGS = (
		CONSTANTS => [ qw(
			FA_MSDOS
			FA_UNIX
			GPBF_ENCRYPTED_MASK
			GPBF_DEFLATING_COMPRESSION_MASK
			GPBF_HAS_DATA_DESCRIPTOR_MASK
			COMPRESSION_STORED
			COMPRESSION_DEFLATED
			COMPRESSION_LEVEL_NONE
			COMPRESSION_LEVEL_DEFAULT
			COMPRESSION_LEVEL_FASTEST
			COMPRESSION_LEVEL_BEST_COMPRESSION
			IFA_TEXT_FILE_MASK
			IFA_TEXT_FILE
			IFA_BINARY_FILE
			) ],

		MISC_CONSTANTS => [ qw(
			FA_AMIGA
			FA_VAX_VMS
			FA_VM_CMS
			FA_ATARI_ST
			FA_OS2_HPFS
			FA_MACINTOSH
			FA_Z_SYSTEM
			FA_CPM
			FA_TOPS20
			FA_WINDOWS_NTFS
			FA_QDOS
			FA_ACORN
			FA_VFAT
			FA_MVS
			FA_BEOS
			FA_TANDEM
			FA_THEOS
			GPBF_IMPLODING_8K_SLIDING_DICTIONARY_MASK
			GPBF_IMPLODING_3_SHANNON_FANO_TREES_MASK
			GPBF_IS_COMPRESSED_PATCHED_DATA_MASK
			COMPRESSION_SHRUNK
			DEFLATING_COMPRESSION_NORMAL
			DEFLATING_COMPRESSION_MAXIMUM
			DEFLATING_COMPRESSION_FAST
			DEFLATING_COMPRESSION_SUPER_FAST
			COMPRESSION_REDUCED_1
			COMPRESSION_REDUCED_2
			COMPRESSION_REDUCED_3
			COMPRESSION_REDUCED_4
			COMPRESSION_IMPLODED
			COMPRESSION_TOKENIZED
			COMPRESSION_DEFLATED_ENHANCED
			COMPRESSION_PKWARE_DATA_COMPRESSION_LIBRARY_IMPLODED
			) ],

		ERROR_CODES => [ qw(
			AZ_OK
			AZ_STREAM_END
			AZ_ERROR
			AZ_FORMAT_ERROR
			AZ_IO_ERROR
			) ],

		# For Internal Use Only
		PKZIP_CONSTANTS => [ qw(
			SIGNATURE_FORMAT
			SIGNATURE_LENGTH
			LOCAL_FILE_HEADER_SIGNATURE
			LOCAL_FILE_HEADER_FORMAT
			LOCAL_FILE_HEADER_LENGTH
			CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE
			DATA_DESCRIPTOR_FORMAT
			DATA_DESCRIPTOR_LENGTH
			DATA_DESCRIPTOR_SIGNATURE
			DATA_DESCRIPTOR_FORMAT_NO_SIG
			DATA_DESCRIPTOR_LENGTH_NO_SIG
			CENTRAL_DIRECTORY_FILE_HEADER_FORMAT
			CENTRAL_DIRECTORY_FILE_HEADER_LENGTH
			END_OF_CENTRAL_DIRECTORY_SIGNATURE
			END_OF_CENTRAL_DIRECTORY_SIGNATURE_STRING
			END_OF_CENTRAL_DIRECTORY_FORMAT
			END_OF_CENTRAL_DIRECTORY_LENGTH
			) ],

		# For Internal Use Only
		UTILITY_METHODS => [ qw(
			_error
			_printError
			_ioError
			_formatError
			_subclassResponsibility
			_binmode
			_isSeekable
			_newFileHandle
			_readSignature
			_asZipDirName
			) ],
	);

	# Add all the constant names and error code names to @EXPORT_OK
	Exporter::export_ok_tags( qw(
		CONSTANTS
		ERROR_CODES
		PKZIP_CONSTANTS
		UTILITY_METHODS
		MISC_CONSTANTS
		) );

}

# Error codes
use constant AZ_OK           => 0;
use constant AZ_STREAM_END   => 1;
use constant AZ_ERROR        => 2;
use constant AZ_FORMAT_ERROR => 3;
use constant AZ_IO_ERROR     => 4;

# File types
# Values of Archive::Zip::Member->fileAttributeFormat()

use constant FA_MSDOS        => 0;
use constant FA_AMIGA        => 1;
use constant FA_VAX_VMS      => 2;
use constant FA_UNIX         => 3;
use constant FA_VM_CMS       => 4;
use constant FA_ATARI_ST     => 5;
use constant FA_OS2_HPFS     => 6;
use constant FA_MACINTOSH    => 7;
use constant FA_Z_SYSTEM     => 8;
use constant FA_CPM          => 9;
use constant FA_TOPS20       => 10;
use constant FA_WINDOWS_NTFS => 11;
use constant FA_QDOS         => 12;
use constant FA_ACORN        => 13;
use constant FA_VFAT         => 14;
use constant FA_MVS          => 15;
use constant FA_BEOS         => 16;
use constant FA_TANDEM       => 17;
use constant FA_THEOS        => 18;

# general-purpose bit flag masks
# Found in Archive::Zip::Member->bitFlag()

use constant GPBF_ENCRYPTED_MASK             => 1 << 0;
use constant GPBF_DEFLATING_COMPRESSION_MASK => 3 << 1;
use constant GPBF_HAS_DATA_DESCRIPTOR_MASK   => 1 << 3;

# deflating compression types, if compressionMethod == COMPRESSION_DEFLATED
# ( Archive::Zip::Member->bitFlag() & GPBF_DEFLATING_COMPRESSION_MASK )

use constant DEFLATING_COMPRESSION_NORMAL     => 0 << 1;
use constant DEFLATING_COMPRESSION_MAXIMUM    => 1 << 1;
use constant DEFLATING_COMPRESSION_FAST       => 2 << 1;
use constant DEFLATING_COMPRESSION_SUPER_FAST => 3 << 1;

# compression method

# these two are the only ones supported in this module
use constant COMPRESSION_STORED                 => 0; # file is stored (no compression)
use constant COMPRESSION_DEFLATED               => 8; # file is Deflated
use constant COMPRESSION_LEVEL_NONE             => 0;
use constant COMPRESSION_LEVEL_DEFAULT          => -1;
use constant COMPRESSION_LEVEL_FASTEST          => 1;
use constant COMPRESSION_LEVEL_BEST_COMPRESSION => 9;

# internal file attribute bits
# Found in Archive::Zip::Member::internalFileAttributes()

use constant IFA_TEXT_FILE_MASK => 1;
use constant IFA_TEXT_FILE      => 1;
use constant IFA_BINARY_FILE    => 0;

# PKZIP file format miscellaneous constants (for internal use only)
use constant SIGNATURE_FORMAT   => "V";
use constant SIGNATURE_LENGTH   => 4;

# these lengths are without the signature.
use constant LOCAL_FILE_HEADER_SIGNATURE   => 0x04034b50;
use constant LOCAL_FILE_HEADER_FORMAT      => "v3 V4 v2";
use constant LOCAL_FILE_HEADER_LENGTH      => 26;

# PKZIP docs don't mention the signature, but Info-Zip writes it.
use constant DATA_DESCRIPTOR_SIGNATURE     => 0x08074b50;
use constant DATA_DESCRIPTOR_FORMAT        => "V3";
use constant DATA_DESCRIPTOR_LENGTH        => 12;

# but the signature is apparently optional.
use constant DATA_DESCRIPTOR_FORMAT_NO_SIG => "V2";
use constant DATA_DESCRIPTOR_LENGTH_NO_SIG => 8;

use constant CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE  => 0x02014b50;
use constant CENTRAL_DIRECTORY_FILE_HEADER_FORMAT     => "C2 v3 V4 v5 V2";
use constant CENTRAL_DIRECTORY_FILE_HEADER_LENGTH     => 42;

use constant END_OF_CENTRAL_DIRECTORY_SIGNATURE        => 0x06054b50;
use constant END_OF_CENTRAL_DIRECTORY_SIGNATURE_STRING =>
	pack( "V", END_OF_CENTRAL_DIRECTORY_SIGNATURE );
use constant END_OF_CENTRAL_DIRECTORY_FORMAT           => "v4 V2 v";
use constant END_OF_CENTRAL_DIRECTORY_LENGTH           => 18;

use constant GPBF_IMPLODING_8K_SLIDING_DICTIONARY_MASK => 1 << 1;
use constant GPBF_IMPLODING_3_SHANNON_FANO_TREES_MASK  => 1 << 2;
use constant GPBF_IS_COMPRESSED_PATCHED_DATA_MASK      => 1 << 5;

# the rest of these are not supported in this module
use constant COMPRESSION_SHRUNK    => 1;    # file is Shrunk
use constant COMPRESSION_REDUCED_1 => 2;    # file is Reduced CF=1
use constant COMPRESSION_REDUCED_2 => 3;    # file is Reduced CF=2
use constant COMPRESSION_REDUCED_3 => 4;    # file is Reduced CF=3
use constant COMPRESSION_REDUCED_4 => 5;    # file is Reduced CF=4
use constant COMPRESSION_IMPLODED  => 6;    # file is Imploded
use constant COMPRESSION_TOKENIZED => 7;    # reserved for Tokenizing compr.
use constant COMPRESSION_DEFLATED_ENHANCED => 9;   # reserved for enh. Deflating
use constant COMPRESSION_PKWARE_DATA_COMPRESSION_LIBRARY_IMPLODED => 10;

# Load the various required classes
require Archive::Zip::Archive;
require Archive::Zip::Member;
require Archive::Zip::FileMember;
require Archive::Zip::DirectoryMember;
require Archive::Zip::ZipFileMember;
require Archive::Zip::NewFileMember;
require Archive::Zip::StringMember;

use constant ZIPARCHIVECLASS => 'Archive::Zip::Archive';
use constant ZIPMEMBERCLASS  => 'Archive::Zip::Member';

# Convenience functions

sub _ISA ($$) {
	# Can't rely on Scalar::Util, so use the next best way
	!! eval { ref $_[0] and $_[0]->isa($_[1]) };
}

sub _CAN ($$) {
	!! eval { ref $_[0] and $_[0]->can($_[1]) };
}





#####################################################################
# Methods

sub new {
	my $class = shift;
	return $class->ZIPARCHIVECLASS->new(@_);
}

sub computeCRC32 {
	my $data = shift;
	$data = shift if ref($data);    # allow calling as an obj method
	my $crc = shift;
	return Compress::Zlib::crc32( $data, $crc );
}

# Report or change chunk size used for reading and writing.
# Also sets Zlib's default buffer size (eventually).
sub setChunkSize {
	my $chunkSize = shift;
	$chunkSize = shift if ref($chunkSize);    # object method on zip?
	my $oldChunkSize = $Archive::Zip::ChunkSize;
	$Archive::Zip::ChunkSize = $chunkSize if ($chunkSize);
	return $oldChunkSize;
}

sub chunkSize {
	return $Archive::Zip::ChunkSize;
}

sub setErrorHandler (&) {
	my $errorHandler = shift;
	$errorHandler = \&Carp::carp unless defined($errorHandler);
	my $oldErrorHandler = $Archive::Zip::ErrorHandler;
	$Archive::Zip::ErrorHandler = $errorHandler;
	return $oldErrorHandler;
}





######################################################################
# Private utility functions (not methods).

sub _printError {
	my $string = join ( ' ', @_, "\n" );
	my $oldCarpLevel = $Carp::CarpLevel;
	$Carp::CarpLevel += 2;
	&{$ErrorHandler} ($string);
	$Carp::CarpLevel = $oldCarpLevel;
}

# This is called on format errors.
sub _formatError {
	shift if ref( $_[0] );
	_printError( 'format error:', @_ );
	return AZ_FORMAT_ERROR;
}

# This is called on IO errors.
sub _ioError {
	shift if ref( $_[0] );
	_printError( 'IO error:', @_, ':', $! );
	return AZ_IO_ERROR;
}

# This is called on generic errors.
sub _error {
	shift if ref( $_[0] );
	_printError( 'error:', @_ );
	return AZ_ERROR;
}

# Called when a subclass should have implemented
# something but didn't
sub _subclassResponsibility {
	Carp::croak("subclass Responsibility\n");
}

# Try to set the given file handle or object into binary mode.
sub _binmode {
	my $fh = shift;
	return _CAN( $fh, 'binmode' ) ? $fh->binmode() : binmode($fh);
}

# Attempt to guess whether file handle is seekable.
# Because of problems with Windows, this only returns true when
# the file handle is a real file.  
sub _isSeekable {
	my $fh = shift;
	return 0 unless ref $fh;
	if ( _ISA($fh, 'IO::Scalar') ) {
		# IO::Scalar objects are brokenly-seekable
		return 0;
	}
	if ( _ISA($fh, 'IO::String') ) {
		return 1;
	}
	if ( _ISA($fh, 'IO::Seekable') ) {
		# Unfortunately, some things like FileHandle objects
		# return true for Seekable, but AREN'T!!!!!
		if ( _ISA($fh, 'FileHandle') ) {
			return 0;
		} else {
			return 1;
		}
	}
	if ( _CAN($fh, 'stat') ) {
		return -f $fh;
	}
	return (
		_CAN($fh, 'seek') and _CAN($fh, 'tell')
		) ? 1 : 0;
}

# Return an opened IO::Handle
# my ( $status, fh ) = _newFileHandle( 'fileName', 'w' );
# Can take a filename, file handle, or ref to GLOB
# Or, if given something that is a ref but not an IO::Handle,
# passes back the same thing.
sub _newFileHandle {
	my $fd     = shift;
	my $status = 1;
	my $handle;

	if ( ref($fd) ) {
		if ( _ISA($fd, 'IO::Scalar') or _ISA($fd, 'IO::String') ) {
			$handle = $fd;
		} elsif ( _ISA($fd, 'IO::Handle') or ref($fd) eq 'GLOB' ) {
			$handle = IO::File->new();
			$status = $handle->fdopen( $fd, @_ );
		} else {
			$handle = $fd;
		}
	} else {
		$handle = IO::File->new();
		$status = $handle->open( $fd, @_ );
	}

	return ( $status, $handle );
}

# Returns next signature from given file handle, leaves
# file handle positioned afterwards.
# In list context, returns ($status, $signature)
# ( $status, $signature) = _readSignature( $fh, $fileName );

sub _readSignature {
	my $fh                = shift;
	my $fileName          = shift;
	my $expectedSignature = shift;    # optional

	my $signatureData;
	my $bytesRead = $fh->read( $signatureData, SIGNATURE_LENGTH );
	if ( $bytesRead != SIGNATURE_LENGTH ) {
		return _ioError("reading header signature");
	}
	my $signature = unpack( SIGNATURE_FORMAT, $signatureData );
	my $status    = AZ_OK;

	# compare with expected signature, if any, or any known signature.
	if ( ( defined($expectedSignature) && $signature != $expectedSignature )
		|| ( !defined($expectedSignature)
			&& $signature != CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE
			&& $signature != LOCAL_FILE_HEADER_SIGNATURE
			&& $signature != END_OF_CENTRAL_DIRECTORY_SIGNATURE
			&& $signature != DATA_DESCRIPTOR_SIGNATURE ) )
	{
		my $errmsg = sprintf( "bad signature: 0x%08x", $signature );
		if ( _isSeekable($fh) )
		{
			$errmsg .=
			  sprintf( " at offset %d", $fh->tell() - SIGNATURE_LENGTH );
		}

		$status = _formatError("$errmsg in file $fileName");
	}

	return ( $status, $signature );
}

# Utility method to make and open a temp file.
# Will create $temp_dir if it doesn't exist.
# Returns file handle and name:
#
# my ($fh, $name) = Archive::Zip::tempFile();
# my ($fh, $name) = Archive::Zip::tempFile('mytempdir');
#

sub tempFile {
	my $dir = shift;
	my ( $fh, $filename ) = File::Temp::tempfile(
		SUFFIX => '.zip',
		UNLINK => 0,        # we will delete it!
		$dir ? ( DIR => $dir ) : ()
	);
	return ( undef, undef ) unless $fh;
	my ( $status, $newfh ) = _newFileHandle( $fh, 'w+' );
	return ( $newfh, $filename );
}

# Return the normalized directory name as used in a zip file (path
# separators become slashes, etc.). 
# Will translate internal slashes in path components (i.e. on Macs) to
# underscores.  Discards volume names.
# When $forceDir is set, returns paths with trailing slashes (or arrays
# with trailing blank members).
#
# If third argument is a reference, returns volume information there.
#
# input         output
# .				('.')	'.'
# ./a			('a')	a
# ./a/b			('a','b')	a/b
# ./a/b/		('a','b')	a/b
# a/b/			('a','b')	a/b
# /a/b/			('','a','b')	/a/b
# c:\a\b\c.doc	('','a','b','c.doc')	/a/b/c.doc		# on Windoze
# "i/o maps:whatever"	('i_o maps', 'whatever')  "i_o maps/whatever"	# on Macs
sub _asZipDirName    
{
	my $name      = shift;
	my $forceDir  = shift;
	my $volReturn = shift;
	my ( $volume, $directories, $file ) =
	  File::Spec->splitpath( File::Spec->canonpath($name), $forceDir );
	$$volReturn = $volume if ( ref($volReturn) );
	my @dirs = map { $_ =~ s{/}{_}g; $_ } File::Spec->splitdir($directories);
	if ( @dirs > 0 ) { pop (@dirs) unless $dirs[-1] }   # remove empty component
	push ( @dirs, defined($file) ? $file : '' );
	#return wantarray ? @dirs : join ( '/', @dirs );
    return join ( '/', @dirs );
}

# Return an absolute local name for a zip name.
# Assume a directory if zip name has trailing slash.
# Takes an optional volume name in FS format (like 'a:').
#
sub _asLocalName    
{
	my $name   = shift;    # zip format
	my $volume = shift;
	$volume = '' unless defined($volume);    # local FS format

	my @paths = split ( /\//, $name );
	my $filename = pop (@paths);
	$filename = '' unless defined($filename);
	my $localDirs = @paths?File::Spec->catdir(@paths):'';
	my $localName = File::Spec->catpath( $volume, $localDirs, $filename );
	$localName = File::Spec->rel2abs($localName) unless $volume;
	return $localName;
}

1;

__END__

#line 2030