diff options
author | Paul Marquess <paul.marquess@btinternet.com> | 2006-05-17 14:45:16 +0100 |
---|---|---|
committer | Steve Peters <steve@fisharerojo.org> | 2006-05-17 15:02:45 +0000 |
commit | c70c17014268a520cc228ac35b4f4bb6b1372ee7 (patch) | |
tree | 7c6a565909b2ce8734d8a76c39ff1ebc990ce1e5 /ext/Compress | |
parent | 8d962fa19aed5e09e2a40f248faf69d89e34ac51 (diff) | |
download | perl-c70c17014268a520cc228ac35b4f4bb6b1372ee7.tar.gz |
IO::Compress* 2.000_12
From: "Paul Marquess" <paul.marquess@ntlworld.com>
Message-ID: <00c101c679af$c0305af0$2405140a@myopwv.com>
p4raw-id: //depot/perl@28214
Diffstat (limited to 'ext/Compress')
33 files changed, 736 insertions, 420 deletions
diff --git a/ext/Compress/IO/Base/README b/ext/Compress/IO/Base/README index cef35988e4..f6fea3d96d 100644 --- a/ext/Compress/IO/Base/README +++ b/ext/Compress/IO/Base/README @@ -1,9 +1,9 @@ IO::Compress::Base - Version 2.000_10 + Version 2.000_12 - 13 Mar 2006 + 17 May 2006 Copyright (c) 2005-2006 Paul Marquess. All rights reserved. diff --git a/ext/Compress/IO/Base/lib/IO/Compress/Base.pm b/ext/Compress/IO/Base/lib/IO/Compress/Base.pm index 14363bce67..952fd6c5b6 100644 --- a/ext/Compress/IO/Base/lib/IO/Compress/Base.pm +++ b/ext/Compress/IO/Base/lib/IO/Compress/Base.pm @@ -20,7 +20,7 @@ use bytes; our (@ISA, $VERSION, $got_encode); #@ISA = qw(Exporter IO::File); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; #Can't locate object method "SWASHNEW" via package "utf8" (perhaps you forgot to load "utf8"?) at .../ext/Compress-Zlib/Gzip/blib/lib/Compress/Zlib/Common.pm line 16. diff --git a/ext/Compress/IO/Base/lib/IO/Compress/Base/Common.pm b/ext/Compress/IO/Base/lib/IO/Compress/Base/Common.pm index f17fe47689..0e1ffa0111 100644 --- a/ext/Compress/IO/Base/lib/IO/Compress/Base/Common.pm +++ b/ext/Compress/IO/Base/lib/IO/Compress/Base/Common.pm @@ -11,7 +11,7 @@ use File::GlobMapper; require Exporter; our ($VERSION, @ISA, @EXPORT, %EXPORT_TAGS); @ISA = qw(Exporter); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; @EXPORT = qw( isaFilehandle isaFilename whatIsInput whatIsOutput isaFileGlobString cleanFileGlobString oneTarget diff --git a/ext/Compress/IO/Base/lib/IO/Uncompress/AnyUncompress.pm b/ext/Compress/IO/Base/lib/IO/Uncompress/AnyUncompress.pm index b73396552b..54ec62158f 100644 --- a/ext/Compress/IO/Base/lib/IO/Uncompress/AnyUncompress.pm +++ b/ext/Compress/IO/Base/lib/IO/Uncompress/AnyUncompress.pm @@ -26,7 +26,7 @@ require Exporter ; our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $AnyUncompressError); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; $AnyUncompressError = ''; @ISA = qw( Exporter IO::Uncompress::Base ); @@ -387,9 +387,13 @@ If the C<$output> parameter is any other type, C<undef> will be returned. =head2 Notes -When C<$input> maps to multiple files/buffers and C<$output> is a single -file/buffer the uncompressed input files/buffers will all be stored -in C<$output> as a single uncompressed stream. + +When C<$input> maps to multiple compressed files/buffers and C<$output> is +a single file/buffer, after uncompression C<$output> will contain a +concatenation of all the uncompressed data from each of the input +files/buffers. + + diff --git a/ext/Compress/IO/Base/lib/IO/Uncompress/Base.pm b/ext/Compress/IO/Base/lib/IO/Uncompress/Base.pm index 2580191105..157926d7d0 100644 --- a/ext/Compress/IO/Base/lib/IO/Uncompress/Base.pm +++ b/ext/Compress/IO/Base/lib/IO/Uncompress/Base.pm @@ -10,7 +10,7 @@ our (@ISA, $VERSION, @EXPORT_OK, %EXPORT_TAGS); @ISA = qw(Exporter ); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; use constant G_EOF => 0 ; use constant G_ERR => -1 ; diff --git a/ext/Compress/IO/Base/t/01misc.t b/ext/Compress/IO/Base/t/01misc.t index dd8c1fbc90..6613fa31f1 100644 --- a/ext/Compress/IO/Base/t/01misc.t +++ b/ext/Compress/IO/Base/t/01misc.t @@ -19,7 +19,7 @@ BEGIN { $extra = 1 if eval { require Test::NoWarnings ; import Test::NoWarnings; 1 }; - plan tests => 29 + $extra ; + plan tests => 33 + $extra ; use_ok('IO::Compress::Base::Common'); @@ -67,6 +67,16 @@ sub My::testParseParameters() $got = ParseParameters(1, {'Fred' => [1, 1, 0x1000000, 0]}, Fred => 'abc') ; is $got->value('Fred'), "abc", "other" ; + $got = ParseParameters(1, {'Fred' => [0, 1, Parse_any, undef]}, Fred => +undef) ; + ok $got->parsed('Fred'), "undef" ; + ok ! defined $got->value('Fred'), "undef" ; + + $got = ParseParameters(1, {'Fred' => [0, 1, Parse_string, undef]}, Fred => +undef) ; + ok $got->parsed('Fred'), "undef" ; + is $got->value('Fred'), "", "empty string" ; + } My::testParseParameters(); diff --git a/ext/Compress/IO/Zlib/Changes b/ext/Compress/IO/Zlib/Changes index cc27f44619..fd928ca490 100644 --- a/ext/Compress/IO/Zlib/Changes +++ b/ext/Compress/IO/Zlib/Changes @@ -1,6 +1,29 @@ CHANGES ------- + 2.000_12 3 May 2006 + + * Moved the code for creating and parsing the gzip extra field into + IO::Compress::Zlib::Extra.pm so that IO::Compress::Zip & + IO::Uncompress::Unzip can use it as well. + + * Added ExtraFieldLocal & ExtraFieldCentral options to IO::Compress::Zip. + These allow the creation of user-defined extra fields in the local + and central headers, just like the ExtraField option in + IO::Compress::Gzip. + + * Moved the zip constants into IO::Compress::Zip::Constants + + * Added exTime option to IO::Compress::Zip. + This allows creation of the extended timestamp extra field. + + * Added Minimal option to IO::Compress::Zip. + This disables the creation of all extended fields. + + * Added TextFlag option to IO::Compress::Zip. + + * Documented Comment and ZipComment options in IO::Compress::Zip. + 2.000_11 10 April 2006 * Updated Documentation for zip modules. diff --git a/ext/Compress/IO/Zlib/README b/ext/Compress/IO/Zlib/README index 6d323cb0e7..fdeadaa385 100644 --- a/ext/Compress/IO/Zlib/README +++ b/ext/Compress/IO/Zlib/README @@ -1,9 +1,9 @@ IO::Compress::Zlib - Version 2.000_11 + Version 2.000_12 - 10 April 2006 + 17 May 2006 Copyright (c) 2005-2006 Paul Marquess. All rights reserved. diff --git a/ext/Compress/IO/Zlib/lib/IO/Compress/Adapter/Deflate.pm b/ext/Compress/IO/Zlib/lib/IO/Compress/Adapter/Deflate.pm index 454689e043..07a84fa892 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Compress/Adapter/Deflate.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Compress/Adapter/Deflate.pm @@ -9,7 +9,7 @@ use IO::Compress::Base::Common qw(:Status); use Compress::Raw::Zlib qw(Z_OK Z_FINISH MAX_WBITS) ; our ($VERSION); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; sub mkCompObject { diff --git a/ext/Compress/IO/Zlib/lib/IO/Compress/Adapter/Identity.pm b/ext/Compress/IO/Zlib/lib/IO/Compress/Adapter/Identity.pm index 72f6efce1d..e253d4330f 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Compress/Adapter/Identity.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Compress/Adapter/Identity.pm @@ -7,7 +7,7 @@ use bytes; use IO::Compress::Base::Common qw(:Status); our ($VERSION); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; sub mkCompObject { diff --git a/ext/Compress/IO/Zlib/lib/IO/Compress/Deflate.pm b/ext/Compress/IO/Zlib/lib/IO/Compress/Deflate.pm index df4af0cf4f..9ef3ebcbc4 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Compress/Deflate.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Compress/Deflate.pm @@ -15,7 +15,7 @@ use IO::Compress::Base::Common qw(createSelfTiedObject); our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $DeflateError); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; $DeflateError = ''; @ISA = qw(Exporter IO::Compress::RawDeflate); @@ -378,9 +378,14 @@ If the C<$output> parameter is any other type, C<undef> will be returned. =head2 Notes + + When C<$input> maps to multiple files/buffers and C<$output> is a single -file/buffer the compressed input files/buffers will all be stored -in C<$output> as a single compressed stream. +file/buffer the input files/buffers will be stored +in C<$output> as a concatenated series of compressed data streams. + + + diff --git a/ext/Compress/IO/Zlib/lib/IO/Compress/Gzip.pm b/ext/Compress/IO/Zlib/lib/IO/Compress/Gzip.pm index 4d4c2d2516..ce3a903547 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Compress/Gzip.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Compress/Gzip.pm @@ -13,6 +13,7 @@ use IO::Compress::RawDeflate; use Compress::Raw::Zlib ; use IO::Compress::Base::Common qw(:Status :Parse createSelfTiedObject); use IO::Compress::Gzip::Constants; +use IO::Compress::Zlib::Extra; BEGIN { @@ -26,7 +27,7 @@ require Exporter ; our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $GzipError); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; $GzipError = '' ; @ISA = qw(Exporter IO::Compress::RawDeflate); @@ -74,7 +75,7 @@ sub getExtraParams 'TextFlag' => [0, 1, Parse_boolean, 0], 'HeaderCRC' => [0, 1, Parse_boolean, 0], 'OS_Code' => [0, 1, Parse_unsigned, $Compress::Raw::Zlib::gzip_os_code], - 'ExtraField'=> [0, 1, Parse_string, undef], + 'ExtraField'=> [0, 1, Parse_any, undef], 'ExtraFlags'=> [0, 1, Parse_any, undef], ); @@ -92,7 +93,7 @@ sub ckParams return 1 if $got->value('Merge') ; - my $lax = ! $got->value('Strict') ; + my $strict = $got->value('Strict') ; { @@ -108,11 +109,11 @@ sub ckParams return $self->saveErrorString(undef, "Null Character found in Name", Z_DATA_ERROR) - if ! $lax && $name =~ /\x00/ ; + if $strict && $name =~ /\x00/ ; return $self->saveErrorString(undef, "Non ISO 8859-1 Character found in Name", Z_DATA_ERROR) - if ! $lax && $name =~ /$GZIP_FNAME_INVALID_CHAR_RE/o ; + if $strict && $name =~ /$GZIP_FNAME_INVALID_CHAR_RE/o ; } if ($got->parsed('Comment') && defined $got->value('Comment')) { @@ -120,11 +121,11 @@ sub ckParams return $self->saveErrorString(undef, "Null Character found in Comment", Z_DATA_ERROR) - if ! $lax && $comment =~ /\x00/ ; + if $strict && $comment =~ /\x00/ ; return $self->saveErrorString(undef, "Non ISO 8859-1 Character found in Comment", Z_DATA_ERROR) - if ! $lax && $comment =~ /$GZIP_FCOMMENT_INVALID_CHAR_RE/o; + if $strict && $comment =~ /$GZIP_FCOMMENT_INVALID_CHAR_RE/o; } if ($got->parsed('OS_Code') ) { @@ -145,16 +146,13 @@ sub ckParams if $got->value('Level') == Z_BEST_COMPRESSION ; } - if ($got->parsed('ExtraField')) { - - my $bad = $self->parseExtraField($got, $lax) ; - return $self->saveErrorString(undef, $bad, Z_DATA_ERROR) + my $data = $got->value('ExtraField') ; + if (defined $data) { + my $bad = IO::Compress::Zlib::Extra::parseExtraField($data, $strict, 1) ; + return $self->saveErrorString(undef, "Error with ExtraField Parameter: $bad", Z_DATA_ERROR) if $bad ; - my $len = length $got->value('ExtraField') ; - return $self->saveErrorString(undef, ExtraFieldError("Too Large"), - Z_DATA_ERROR) - if $len > GZIP_FEXTRA_MAX_SIZE; + $got->value('ExtraField', $data) ; } } @@ -265,158 +263,6 @@ sub mkHeader return $out ; } -sub ExtraFieldError -{ - return "Error with ExtraField Parameter: $_[0]" ; -} - -sub validateExtraFieldPair -{ - my $pair = shift ; - my $lax = shift ; - - return ExtraFieldError("Not an array ref") - unless ref $pair && ref $pair eq 'ARRAY'; - - return ExtraFieldError("SubField must have two parts") - unless @$pair == 2 ; - - return ExtraFieldError("SubField ID is a reference") - if ref $pair->[0] ; - - return ExtraFieldError("SubField Data is a reference") - if ref $pair->[1] ; - - # ID is exactly two chars - return ExtraFieldError("SubField ID not two chars long") - unless length $pair->[0] == GZIP_FEXTRA_SUBFIELD_ID_SIZE ; - - # Check that the 2nd byte of the ID isn't 0 - return ExtraFieldError("SubField ID 2nd byte is 0x00") - if ! $lax && substr($pair->[0], 1, 1) eq "\x00" ; - - return ExtraFieldError("SubField Data too long") - if length $pair->[1] > GZIP_FEXTRA_SUBFIELD_MAX_SIZE ; - - - return undef ; -} - -sub parseExtra -{ - my $data = shift ; - my $lax = shift ; - - return undef - if $lax ; - - my $XLEN = length $data ; - - return ExtraFieldError("Too Large") - if $XLEN > GZIP_FEXTRA_MAX_SIZE; - - my $offset = 0 ; - while ($offset < $XLEN) { - - return ExtraFieldError("FEXTRA Body") - if $offset + GZIP_FEXTRA_SUBFIELD_HEADER_SIZE > $XLEN ; - - my $id = substr($data, $offset, GZIP_FEXTRA_SUBFIELD_ID_SIZE); - $offset += GZIP_FEXTRA_SUBFIELD_ID_SIZE; - - my $subLen = unpack("v", substr($data, $offset, - GZIP_FEXTRA_SUBFIELD_LEN_SIZE)); - $offset += GZIP_FEXTRA_SUBFIELD_LEN_SIZE ; - - return ExtraFieldError("FEXTRA Body") - if $offset + $subLen > $XLEN ; - - my $bad = validateExtraFieldPair( [$id, - substr($data, $offset, $subLen)], $lax ); - return $bad if $bad ; - - $offset += $subLen ; - } - - return undef ; -} - -sub parseExtraField -{ - my $self = shift ; - my $got = shift ; - my $lax = shift ; - - # ExtraField can be any of - # - # -ExtraField => $data - # -ExtraField => [$id1, $data1, - # $id2, $data2] - # ... - # ] - # -ExtraField => [ [$id1 => $data1], - # [$id2 => $data2], - # ... - # ] - # -ExtraField => { $id1 => $data1, - # $id2 => $data2, - # ... - # } - - - return undef - unless $got->parsed('ExtraField') ; - - return parseExtra($got->value('ExtraField'), $lax) - unless ref $got->value('ExtraField') ; - - my $data = $got->value('ExtraField'); - my $out = '' ; - - if (ref $data eq 'ARRAY') { - if (ref $data->[0]) { - - foreach my $pair (@$data) { - return ExtraFieldError("Not list of lists") - unless ref $pair eq 'ARRAY' ; - - my $bad = validateExtraFieldPair($pair, $lax) ; - return $bad if $bad ; - - $out .= $pair->[0] . pack("v", length $pair->[1]) . - $pair->[1] ; - } - } - else { - return ExtraFieldError("Not even number of elements") - unless @$data % 2 == 0; - - for (my $ix = 0; $ix <= length(@$data) -1 ; $ix += 2) { - my $bad = validateExtraFieldPair([$data->[$ix], $data->[$ix+1]], $lax) ; - return $bad if $bad ; - - $out .= $data->[$ix] . pack("v", length $data->[$ix+1]) . - $data->[$ix+1] ; - } - } - } - elsif (ref $data eq 'HASH') { - while (my ($id, $info) = each %$data) { - my $bad = validateExtraFieldPair([$id, $info], $lax); - return $bad if $bad ; - - $out .= $id . pack("v", length $info) . $info ; - } - } - else { - return ExtraFieldError("Not a scalar, array ref or hash ref") ; - } - - $got->value('ExtraField' => $out); - - return undef; -} - sub mkFinalTrailer { return ''; @@ -651,9 +497,14 @@ If the C<$output> parameter is any other type, C<undef> will be returned. =head2 Notes + + When C<$input> maps to multiple files/buffers and C<$output> is a single -file/buffer the compressed input files/buffers will all be stored -in C<$output> as a single compressed stream. +file/buffer the input files/buffers will be stored +in C<$output> as a concatenated series of compressed data streams. + + + diff --git a/ext/Compress/IO/Zlib/lib/IO/Compress/Gzip/Constants.pm b/ext/Compress/IO/Zlib/lib/IO/Compress/Gzip/Constants.pm index 024c443f32..9c671b58d6 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Compress/Gzip/Constants.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Compress/Gzip/Constants.pm @@ -9,7 +9,7 @@ require Exporter; our ($VERSION, @ISA, @EXPORT, %GZIP_OS_Names); our ($GZIP_FNAME_INVALID_CHAR_RE, $GZIP_FCOMMENT_INVALID_CHAR_RE); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; @ISA = qw(Exporter); diff --git a/ext/Compress/IO/Zlib/lib/IO/Compress/RawDeflate.pm b/ext/Compress/IO/Zlib/lib/IO/Compress/RawDeflate.pm index fc195e7e9e..0f917e238c 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Compress/RawDeflate.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Compress/RawDeflate.pm @@ -16,7 +16,7 @@ require Exporter ; our ($VERSION, @ISA, @EXPORT_OK, %DEFLATE_CONSTANTS, %EXPORT_TAGS, $RawDeflateError); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; $RawDeflateError = ''; @ISA = qw(Exporter IO::Compress::Base); @@ -462,9 +462,14 @@ If the C<$output> parameter is any other type, C<undef> will be returned. =head2 Notes + + When C<$input> maps to multiple files/buffers and C<$output> is a single -file/buffer the compressed input files/buffers will all be stored -in C<$output> as a single compressed stream. +file/buffer the input files/buffers will be stored +in C<$output> as a concatenated series of compressed data streams. + + + diff --git a/ext/Compress/IO/Zlib/lib/IO/Compress/Zip.pm b/ext/Compress/IO/Zlib/lib/IO/Compress/Zip.pm index 444180932e..ea189b03f9 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Compress/Zip.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Compress/Zip.pm @@ -8,14 +8,16 @@ use IO::Compress::Base::Common qw(:Status createSelfTiedObject); use IO::Compress::RawDeflate; use IO::Compress::Adapter::Deflate; use IO::Compress::Adapter::Identity; +use IO::Compress::Zip::Constants; + use Compress::Raw::Zlib qw(crc32) ; BEGIN { eval { require IO::Compress::Adapter::Bzip2; - import IO::Compress::Adapter::Bzip2; + import IO::Compress::Adapter::Bzip2; require IO::Compress::Bzip2; - import IO::Compress::Bzip2; + import IO::Compress::Bzip2; } ; } @@ -24,7 +26,7 @@ require Exporter ; our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $ZipError); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; $ZipError = ''; @ISA = qw(Exporter IO::Compress::RawDeflate); @@ -37,23 +39,6 @@ push @{ $EXPORT_TAGS{all} }, @{ $EXPORT_TAGS{zip_method} }; Exporter::export_ok_tags('all'); -use constant ZIP_CM_STORE => 0 ; -use constant ZIP_CM_DEFLATE => 8 ; -use constant ZIP_CM_BZIP2 => 12 ; - -use constant ZIP_LOCAL_HDR_SIG => 0x04034b50; -use constant ZIP_DATA_HDR_SIG => 0x08074b50; -use constant ZIP_CENTRAL_HDR_SIG => 0x02014b50; -use constant ZIP_END_CENTRAL_HDR_SIG => 0x06054b50; - - -our (%ZIP_CM_MIN_VERSIONS); -%ZIP_CM_MIN_VERSIONS = ( - ZIP_CM_STORE() => 20, - ZIP_CM_DEFLATE() => 20, - ZIP_CM_BZIP2() => 46, - ); - sub new { my $class = shift ; @@ -137,6 +122,8 @@ sub mkHeader my $self = shift; my $param = shift ; + *$self->{ZipData}{StartOffset} = *$self->{ZipData}{Offset} ; + my $filename = ''; $filename = $param->value('Name') || ''; @@ -146,52 +133,89 @@ sub mkHeader my $hdr = ''; my $time = _unixToDosTime($param->value('Time')); - *$self->{ZipData}{StartOffset} = *$self->{ZipData}{Offset} ; - my $strm = *$self->{ZipData}{Stream} ? 8 : 0 ; - # bzip2 is 12, deflate is 8 + my $extra = ''; + my $ctlExtra = ''; + + if (! $param->value('Minimal')) { + if (defined $param->value('exTime')) + { + $extra .= mkExtendedTime($param->value('MTime'), + $param->value('ATime'), + $param->value('CTime')); + + $ctlExtra .= mkExtendedTime($param->value('MTime')); + } + + # if ( $param->value('UID')) + # { + # $extra .= mkUnixExtra( $param->value('UID'), $param->value('GID')); + # $ctlExtra .= mkUnixExtra(); + # } + + $extra .= $param->value('ExtraFieldLocal') + if defined $param->value('ExtraFieldLocal'); + + $ctlExtra .= $param->value('ExtraFieldCentral') + if defined $param->value('ExtraFieldCentral'); + } + + my $extAttr = 0; + $extAttr = $param->value('Mode') << 16 + if defined $param->value('Mode') ; + + my $gpFlag = 0 ; + $gpFlag |= ZIP_GP_FLAG_STREAMING_MASK + if *$self->{ZipData}{Stream} ; + my $method = *$self->{ZipData}{Method} ; # deflate is 20 # bzip2 is 46 - my $extract = $param->value('OS_Code') << 8 + + my $madeBy = ($param->value('OS_Code') << 8) + $ZIP_CM_MIN_VERSIONS{$method}; + my $extract = $ZIP_CM_MIN_VERSIONS{$method}; + + my $ifa = 0; + $ifa |= ZIP_IFA_TEXT_MASK + if $param->value('TextFlag'); $hdr .= pack "V", ZIP_LOCAL_HDR_SIG ; # signature $hdr .= pack 'v', $extract ; # extract Version & OS - $hdr .= pack 'v', $strm ; # general purpose flag (set streaming mode) + $hdr .= pack 'v', $gpFlag ; # general purpose flag (set streaming mode) $hdr .= pack 'v', $method ; # compression method (deflate) $hdr .= pack 'V', $time ; # last mod date/time $hdr .= pack 'V', 0 ; # crc32 - 0 when streaming $hdr .= pack 'V', 0 ; # compressed length - 0 when streaming $hdr .= pack 'V', 0 ; # uncompressed length - 0 when streaming $hdr .= pack 'v', length $filename ; # filename length - $hdr .= pack 'v', 0 ; # extra length + $hdr .= pack 'v', length $extra ; # extra length $hdr .= $filename ; + $hdr .= $extra ; my $ctl = ''; $ctl .= pack "V", ZIP_CENTRAL_HDR_SIG ; # signature - $ctl .= pack 'v', $extract ; # version made by + $ctl .= pack 'v', $madeBy ; # version made by $ctl .= pack 'v', $extract ; # extract Version - $ctl .= pack 'v', $strm ; # general purpose flag (streaming mode) + $ctl .= pack 'v', $gpFlag ; # general purpose flag (streaming mode) $ctl .= pack 'v', $method ; # compression method (deflate) $ctl .= pack 'V', $time ; # last mod date/time $ctl .= pack 'V', 0 ; # crc32 $ctl .= pack 'V', 0 ; # compressed length $ctl .= pack 'V', 0 ; # uncompressed length $ctl .= pack 'v', length $filename ; # filename length - $ctl .= pack 'v', 0 ; # extra length + $ctl .= pack 'v', length $ctlExtra ; # extra length $ctl .= pack 'v', length $comment ; # file comment length $ctl .= pack 'v', 0 ; # disk number start - $ctl .= pack 'v', 0 ; # internal file attributes - $ctl .= pack 'V', 0 ; # external file attributes + $ctl .= pack 'v', $ifa ; # internal file attributes + $ctl .= pack 'V', $extAttr ; # external file attributes $ctl .= pack 'V', *$self->{ZipData}{Offset} ; # offset to local header $ctl .= $filename ; - #$ctl .= $extra ; + $ctl .= $ctlExtra ; $ctl .= $comment ; *$self->{ZipData}{Offset} += length $hdr ; @@ -234,9 +258,6 @@ sub mkTrailer my $ctl = *$self->{ZipData}{CentralHeader} ; substr($ctl, 16, 12) = $data ; - #substr($ctl, 16, 4) = pack "V", $crc32 ; # CRC32 - #substr($ctl, 20, 4) = pack "V", $compressedBytes ; # Compressed Size - #substr($ctl, 24, 4) = pack "V", $uncompressedBytes ; # Uncompressed Size *$self->{ZipData}{Offset} += length($hdr) + $compressedBytes; push @{ *$self->{ZipData}{CentralDir} }, $ctl ; @@ -280,11 +301,21 @@ sub ckParams $got->value('Time' => time) ; } + if (! $got->parsed('exTime') ) { + my $timeRef = $got->value('exTime'); + if ( defined $timeRef) { + return $self->saveErrorString(undef, "exTime not a 3-element array ref") + if ref $timeRef ne 'ARRAY' || @$timeRef != 3; + } + + $got->value("MTime", $timeRef->[1]); + $got->value("ATime", $timeRef->[0]); + $got->value("CTime", $timeRef->[2]); + } + *$self->{ZipData}{Stream} = $got->value('Stream'); - #*$self->{ZipData}{Store} = $got->value('Store'); my $method = $got->value('Method'); - #if ($method != 0 && $method != 8 && $method != 12) { return $self->saveErrorString(undef, "Unknown Method '$method'") if ! defined $ZIP_CM_MIN_VERSIONS{$method}; @@ -296,6 +327,18 @@ sub ckParams *$self->{ZipData}{ZipComment} = $got->value('ZipComment') ; + for my $name (qw( ExtraFieldLocal ExtraFieldCentral )) + { + my $data = $got->value($name) ; + if (defined $data) { + my $bad = IO::Compress::Zlib::Extra::parseExtraField($data, 1, 0) ; + return $self->saveErrorString(undef, "Error with $name Parameter: $bad") + if $bad ; + + $got->value($name, $data) ; + } + } + return undef if defined $IO::Compress::Bzip2::VERSION and ! IO::Compress::Bzip2::ckParams($self, $got); @@ -331,15 +374,17 @@ sub getExtraParams 'Method' => [0, 1, Parse_unsigned, ZIP_CM_DEFLATE], # # Zip header fields -# 'Minimal' => [0, 1, Parse_boolean, 0], + 'Minimal' => [0, 1, Parse_boolean, 0], 'Comment' => [0, 1, Parse_any, ''], 'ZipComment'=> [0, 1, Parse_any, ''], 'Name' => [0, 1, Parse_any, ''], 'Time' => [0, 1, Parse_any, undef], + 'exTime' => [0, 1, Parse_any, undef], 'OS_Code' => [0, 1, Parse_unsigned, $Compress::Raw::Zlib::gzip_os_code], -# 'TextFlag' => [0, 1, Parse_boolean, 0], -# 'ExtraField'=> [0, 1, Parse_string, ''], + 'TextFlag' => [0, 1, Parse_boolean, 0], + 'ExtraFieldLocal' => [0, 1, Parse_any, undef], + 'ExtraFieldCentral'=> [0, 1, Parse_any, undef], @Bzip2, ); @@ -357,17 +402,66 @@ sub getFileInfo my $params = shift; my $filename = shift ; - my $defaultTime = (stat($filename))[9] ; + my ($mode, $uid, $gid, $atime, $mtime, $ctime) + = (stat($filename))[2, 4,5, 8,9,10] ; $params->value('Name' => $filename) if ! $params->parsed('Name') ; - $params->value('Time' => $defaultTime) + $params->value('Time' => $mtime) if ! $params->parsed('Time') ; + if ( ! $params->parsed('exTime')) + { + $params->value('MTime' => $mtime) ; + $params->value('ATime' => $atime) ; + $params->value('CTime' => $ctime) ; + } + + $params->value('Mode' => $mode) ; + + $params->value('UID' => $uid) ; + $params->value('GID' => $gid) ; } +sub mkExtendedTime +{ + # order expected is m, a, c + + my $times = ''; + my $bit = 1 ; + my $flags = 0; + + for my $time (@_) + { + if (defined $time) + { + $flags |= $bit; + $times .= pack("V", $time); + } + + $bit <<= 1 ; + } + + #return "UT" . pack("v C", length($times) + 1, $flags) . $times; + return IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_EXT_TIMESTAMP, + pack("C", $flags) . $times); +} + +sub mkUnixExtra +{ + my $ids = ''; + for my $id (@_) + { + $ids .= pack("v", $id); + } + + #return "Ux" . pack("v", length $ids) . $ids; + return IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_INFO_ZIP_UNIX, $ids); +} + + # from Archive::Zip sub _unixToDosTime # Archive::Zip::Member { @@ -559,10 +653,10 @@ If the C<$input> parameter is any other type, C<undef> will be returned. In addition, if C<$input> is a simple filename, the default values for -the C<Name> and C<Time> options will be sourced from that file. +the C<Name>, C<Time> and C<exTime> options will be sourced from that file. If you do not want to use these defaults they can be overridden by -explicitly setting the C<Name> and C<Time> options or by setting the +explicitly setting the C<Name>, C<Time> and C<exTime> options or by setting the C<Minimal> parameter. @@ -616,9 +710,14 @@ If the C<$output> parameter is any other type, C<undef> will be returned. =head2 Notes + + When C<$input> maps to multiple files/buffers and C<$output> is a single -file/buffer the compressed input files/buffers will all be stored -in C<$output> as a single compressed stream. +file/buffer the input files/buffers will each be stored +in C<$output> as a distinct entry. + + + @@ -823,6 +922,34 @@ Sets the last modified time field in the zip header to $number. This field defaults to the time the C<IO::Compress::Zip> object was created if this option is not specified. +=item -exTime =E<gt> [$atime, $mtime, $ctime] + +This option expects an array reference with exactly three elements: +C<$atime>, C<mtime> and C<$ctime>. These correspond to the last access +time, last modification time and creation time respectively. + +It uses these values to set the extended timestamp field in the local zip +header to the three values, $atime, $mtime, $ctime and sets the extended +timestamp field in the central zip header to C<$mtime>. + +If the C<Minimal> option is set to true, this option will be ignored. + +By default no extended time field is created. + +=item -Comment =E<gt> $comment + +Stores the contents of C<$comment> in the Central File Header of +the zip file. + +By default, no comment field is written to the zip file. + +=item -ZipComment =E<gt> $comment + +Stores the contents of C<$comment> in the End of Central Directory record +of the zip file. + +By default, no comment field is written to the zip file. + =item Method =E<gt> $method Controls which compression method is used. At present three compression @@ -844,13 +971,73 @@ content when C<IO::Compress::Bzip2> is not available. The default method is ZIP_CM_DEFLATE. -=item -Stream =E<gt> 0|1 +=item Stream =E<gt> 0|1 This option controls whether the zip file/buffer output is created in streaming mode. +Note that when outputting to a file with streaming mode disabled (C<Stream> +is 0), the output file must be seekable. + The default is 1. +=item -TextFlag =E<gt> 0|1 + +This parameter controls the setting of a bit in the zip central header. It +is used to signal that the data stored in the zip file/buffer is probably +text. + +The default is 0. + +=item ExtraFieldLocal =E<gt> $data +=item ExtraFieldCentral =E<gt> $data + +These options allows additional metadata to be stored in the local and +central headers in the zip file/buffer. + +An extra field consists of zero or more subfields. Each subfield consists +of a two byte header followed by the subfield data. + +The list of subfields can be supplied in any of the following formats + + ExtraFieldLocal => [$id1, $data1, + $id2, $data2, + ... + ] + + ExtraFieldLocal => [ [$id1 => $data1], + [$id2 => $data2], + ... + ] + + ExtraFieldLocal => { $id1 => $data1, + $id2 => $data2, + ... + } + +Where C<$id1>, C<$id2> are two byte subfield ID's. + +If you use the hash syntax, you have no control over the order in which +the ExtraSubFields are stored, plus you cannot have SubFields with +duplicate ID. + +Alternatively the list of subfields can by supplied as a scalar, thus + + ExtraField => $rawdata + + + +If the C<Minimal> option is set to true, this option will be ignored. + +The maximum size of an extra field 65535 bytes. + +=item Minimal =E<gt> 1|0 + +If specified, this option will disable the creation of all extended fields +in the zip local and central headers. + +This parameter defaults to 0. + =item BlockSize100K =E<gt> number Specify the number of 100K blocks bzip2 uses during compression. diff --git a/ext/Compress/IO/Zlib/lib/IO/Compress/Zip/Constants.pm b/ext/Compress/IO/Zlib/lib/IO/Compress/Zip/Constants.pm index 9761b8286b..952a3b34de 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Compress/Zip/Constants.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Compress/Zip/Constants.pm @@ -5,130 +5,64 @@ use warnings; require Exporter; -our ($VERSION, @ISA, @EXPORT, %GZIP_OS_Names); +our ($VERSION, @ISA, @EXPORT, %ZIP_CM_MIN_VERSIONS); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; @ISA = qw(Exporter); @EXPORT= qw( - ZIP_ID_SIZE - GZIP_ID1 - GZIP_ID2 - - GZIP_FLG_DEFAULT - GZIP_FLG_FTEXT - GZIP_FLG_FHCRC - GZIP_FLG_FEXTRA - GZIP_FLG_FNAME - GZIP_FLG_FCOMMENT - GZIP_FLG_RESERVED - ZIP_CM_STORE - ZIP_CM_DEFLATED + ZIP_CM_DEFLATE ZIP_CM_BZIP2 + + ZIP_LOCAL_HDR_SIG + ZIP_DATA_HDR_SIG + ZIP_CENTRAL_HDR_SIG + ZIP_END_CENTRAL_HDR_SIG - GZIP_MIN_HEADER_SIZE - GZIP_TRAILER_SIZE - - GZIP_MTIME_DEFAULT - GZIP_FEXTRA_DEFAULT - GZIP_FEXTRA_HEADER_SIZE - GZIP_FEXTRA_MAX_SIZE - GZIP_FEXTRA_SUBFIELD_HEADER_SIZE - GZIP_FEXTRA_SUBFIELD_ID_SIZE - GZIP_FEXTRA_SUBFIELD_LEN_SIZE - GZIP_FEXTRA_SUBFIELD_MAX_SIZE - - GZIP_FNAME_INVALID_CHAR_RE - GZIP_FCOMMENT_INVALID_CHAR_RE - - GZIP_FHCRC_SIZE + ZIP_GP_FLAG_STREAMING_MASK - GZIP_ISIZE_MAX - GZIP_ISIZE_MOD_VALUE + ZIP_EXTRA_ID_EXT_TIMESTAMP + ZIP_EXTRA_ID_INFO_ZIP_UNIX + ZIP_IFA_TEXT_MASK - GZIP_NULL_BYTE - - GZIP_OS_DEFAULT - - %GZIP_OS_Names - - GZIP_MINIMUM_HEADER + %ZIP_CM_MIN_VERSIONS ); +# Compression types supported +use constant ZIP_CM_STORE => 0 ; +use constant ZIP_CM_DEFLATE => 8 ; +use constant ZIP_CM_BZIP2 => 12 ; -# Constants for the Zip Local Header - -use constant ZIP_ID_SIZE => 4 ; -use constant ZIP_LOCAL_ID => 0x02014B50; -use constant ZIP_LOCAL_ID1 => 0x04; -use constant ZIP_LOCAL_ID2 => 0x03; -use constant ZIP_LOCAL_ID3 => 0x4B; -use constant ZIP_LOCAL_ID4 => 0x50; - -use constant ZIP_MIN_HEADER_SIZE => 30 ; -use constant ZIP_TRAILER_SIZE => 0 ; +# General Purpose Flag +use constant ZIP_GP_FLAG_ENCRYPTED_MASK => 1 ; +use constant ZIP_GP_FLAG_STREAMING_MASK => 8 ; +# Internal File Attributes +use constant ZIP_IFA_TEXT_MASK => 1; -use constant GZIP_FLG_DEFAULT => 0x00 ; -use constant GZIP_FLG_FTEXT => 0x01 ; -use constant GZIP_FLG_FHCRC => 0x02 ; # called CONTINUATION in gzip -use constant GZIP_FLG_FEXTRA => 0x04 ; -use constant GZIP_FLG_FNAME => 0x08 ; -use constant GZIP_FLG_FCOMMENT => 0x10 ; -#use constant GZIP_FLG_ENCRYPTED => 0x20 ; # documented in gzip sources -use constant GZIP_FLG_RESERVED => (0x20 | 0x40 | 0x80) ; +# Signatures for each of the headers +use constant ZIP_LOCAL_HDR_SIG => 0x04034b50; +use constant ZIP_DATA_HDR_SIG => 0x08074b50; +use constant ZIP_CENTRAL_HDR_SIG => 0x02014b50; +use constant ZIP_END_CENTRAL_HDR_SIG => 0x06054b50; -use constant GZIP_MTIME_DEFAULT => 0x00 ; -use constant GZIP_FEXTRA_DEFAULT => 0x00 ; -use constant GZIP_FEXTRA_HEADER_SIZE => 2 ; -use constant GZIP_FEXTRA_MAX_SIZE => 0xFFFF ; -use constant GZIP_FEXTRA_SUBFIELD_HEADER_SIZE => 4 ; -use constant GZIP_FEXTRA_SUBFIELD_ID_SIZE => 2 ; -use constant GZIP_FEXTRA_SUBFIELD_LEN_SIZE => 2 ; -use constant GZIP_FEXTRA_SUBFIELD_MAX_SIZE => 0xFFFF ; +# Extra Field ID's +use constant ZIP_EXTRA_ID_EXT_TIMESTAMP => "UT"; +use constant ZIP_EXTRA_ID_INFO_ZIP_UNIX => "Ux"; -use constant GZIP_FNAME_INVALID_CHAR_RE => qr/[\x00-\x1F\x7F-\x9F]/; -use constant GZIP_FCOMMENT_INVALID_CHAR_RE => qr/[\x00-\x09\x11-\x1F\x7F-\x9F]/; +%ZIP_CM_MIN_VERSIONS = ( + ZIP_CM_STORE() => 20, + ZIP_CM_DEFLATE() => 20, + ZIP_CM_BZIP2() => 46, + ); -use constant GZIP_FHCRC_SIZE => 2 ; # aka CONTINUATION in gzip -use constant ZIP_CM_STORE => 0 ; -use constant ZIP_CM_DEFLATE => 8 ; -use constant ZIP_CM_BZIP2 => 12 ; +1; -use constant GZIP_NULL_BYTE => "\x00"; -use constant GZIP_ISIZE_MAX => 0xFFFFFFFF ; -use constant GZIP_ISIZE_MOD_VALUE => GZIP_ISIZE_MAX + 1 ; - -# OS Names sourced from http://www.gzip.org/format.txt - -use constant GZIP_OS_DEFAULT=> 0xFF ; -%ZIP_OS_Names = ( - 0 => 'MS-DOS', - 1 => 'Amiga', - 2 => 'VMS', - 3 => 'Unix', - 4 => 'VM/CMS', - 5 => 'Atari TOS', - 6 => 'HPFS (OS/2, NT)', - 7 => 'Macintosh', - 8 => 'Z-System', - 9 => 'CP/M', - 10 => 'TOPS-20', - 11 => 'NTFS (NT)', - 12 => 'SMS QDOS', - 13 => 'Acorn RISCOS', - 14 => 'VFAT file system (Win95, NT)', - 15 => 'MVS', - 16 => 'BeOS', - 17 => 'Tandem/NSK', - 18 => 'THEOS', - GZIP_OS_DEFAULT => 'Unknown', - ) ; +__END__ -1; diff --git a/ext/Compress/IO/Zlib/lib/IO/Compress/Zlib/Constants.pm b/ext/Compress/IO/Zlib/lib/IO/Compress/Zlib/Constants.pm index a06b6fb5e1..98c9955283 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Compress/Zlib/Constants.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Compress/Zlib/Constants.pm @@ -9,7 +9,7 @@ require Exporter; our ($VERSION, @ISA, @EXPORT); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; @ISA = qw(Exporter); diff --git a/ext/Compress/IO/Zlib/lib/IO/Compress/Zlib/Extra.pm b/ext/Compress/IO/Zlib/lib/IO/Compress/Zlib/Extra.pm new file mode 100644 index 0000000000..68ef02e31d --- /dev/null +++ b/ext/Compress/IO/Zlib/lib/IO/Compress/Zlib/Extra.pm @@ -0,0 +1,203 @@ +package IO::Compress::Zlib::Extra; + +require 5.004 ; + +use strict ; +use warnings; +use bytes; + +our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS); + +$VERSION = '2.000_12'; + +use IO::Compress::Gzip::Constants; + +sub ExtraFieldError +{ + return $_[0]; + return "Error with ExtraField Parameter: $_[0]" ; +} + +sub validateExtraFieldPair +{ + my $pair = shift ; + my $strict = shift; + my $gzipMode = shift ; + + return ExtraFieldError("Not an array ref") + unless ref $pair && ref $pair eq 'ARRAY'; + + return ExtraFieldError("SubField must have two parts") + unless @$pair == 2 ; + + return ExtraFieldError("SubField ID is a reference") + if ref $pair->[0] ; + + return ExtraFieldError("SubField Data is a reference") + if ref $pair->[1] ; + + # ID is exactly two chars + return ExtraFieldError("SubField ID not two chars long") + unless length $pair->[0] == GZIP_FEXTRA_SUBFIELD_ID_SIZE ; + + # Check that the 2nd byte of the ID isn't 0 + return ExtraFieldError("SubField ID 2nd byte is 0x00") + if $strict && $gzipMode && substr($pair->[0], 1, 1) eq "\x00" ; + + return ExtraFieldError("SubField Data too long") + if length $pair->[1] > GZIP_FEXTRA_SUBFIELD_MAX_SIZE ; + + + return undef ; +} + +sub parseRawExtra +{ + my $data = shift ; + my $extraRef = shift; + my $strict = shift; + my $gzipMode = shift ; + + #my $lax = shift ; + + #return undef + # if $lax ; + + my $XLEN = length $data ; + + return ExtraFieldError("Too Large") + if $XLEN > GZIP_FEXTRA_MAX_SIZE; + + my $offset = 0 ; + while ($offset < $XLEN) { + + return ExtraFieldError("Truncated in FEXTRA Body Section") + if $offset + GZIP_FEXTRA_SUBFIELD_HEADER_SIZE > $XLEN ; + + my $id = substr($data, $offset, GZIP_FEXTRA_SUBFIELD_ID_SIZE); + $offset += GZIP_FEXTRA_SUBFIELD_ID_SIZE; + + my $subLen = unpack("v", substr($data, $offset, + GZIP_FEXTRA_SUBFIELD_LEN_SIZE)); + $offset += GZIP_FEXTRA_SUBFIELD_LEN_SIZE ; + + return ExtraFieldError("Truncated in FEXTRA Body Section") + if $offset + $subLen > $XLEN ; + + my $bad = validateExtraFieldPair( [$id, + substr($data, $offset, $subLen)], + $strict, $gzipMode ); + return $bad if $bad ; + push @$extraRef, [$id => substr($data, $offset, $subLen)] + if defined $extraRef;; + + $offset += $subLen ; + } + + + return undef ; +} + + +sub mkSubField +{ + my $id = shift ; + my $data = shift ; + + return $id . pack("v", length $data) . $data ; +} + +sub parseExtraField +{ + my $dataRef = $_[0]; + my $strict = $_[1]; + my $gzipMode = $_[2]; + #my $lax = @_ == 2 ? $_[1] : 1; + + + # ExtraField can be any of + # + # -ExtraField => $data + # + # -ExtraField => [$id1, $data1, + # $id2, $data2] + # ... + # ] + # + # -ExtraField => [ [$id1 => $data1], + # [$id2 => $data2], + # ... + # ] + # + # -ExtraField => { $id1 => $data1, + # $id2 => $data2, + # ... + # } + + if ( ! ref $dataRef ) { + + return undef + if ! $strict; + + return parseRawExtra($dataRef, undef, 1, $gzipMode); + } + + #my $data = $$dataRef; + my $data = $dataRef; + my $out = '' ; + + if (ref $data eq 'ARRAY') { + if (ref $data->[0]) { + + foreach my $pair (@$data) { + return ExtraFieldError("Not list of lists") + unless ref $pair eq 'ARRAY' ; + + my $bad = validateExtraFieldPair($pair, $strict, $gzipMode) ; + return $bad if $bad ; + + $out .= mkSubField(@$pair); + #$out .= $pair->[0] . pack("v", length $pair->[1]) . + # $pair->[1] ; + } + } + else { + return ExtraFieldError("Not even number of elements") + unless @$data % 2 == 0; + + for (my $ix = 0; $ix <= length(@$data) -1 ; $ix += 2) { + my $bad = validateExtraFieldPair([$data->[$ix], + $data->[$ix+1]], + $strict, $gzipMode) ; + return $bad if $bad ; + + $out .= mkSubField($data->[$ix], $data->[$ix+1]); + #$out .= $data->[$ix] . pack("v", length $data->[$ix+1]) . + # $data->[$ix+1] ; + } + } + } + elsif (ref $data eq 'HASH') { + while (my ($id, $info) = each %$data) { + my $bad = validateExtraFieldPair([$id, $info], $strict, $gzipMode); + return $bad if $bad ; + + $out .= mkSubField($id, $info); + #$out .= $id . pack("v", length $info) . $info ; + } + } + else { + return ExtraFieldError("Not a scalar, array ref or hash ref") ; + } + + return ExtraFieldError("Too Large") + if length $out > GZIP_FEXTRA_MAX_SIZE; + + $_[0] = $out ; + + return undef; +} + +1; + +__END__ diff --git a/ext/Compress/IO/Zlib/lib/IO/Uncompress/Adapter/Identity.pm b/ext/Compress/IO/Zlib/lib/IO/Uncompress/Adapter/Identity.pm index 288bf58e05..b91f432675 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Uncompress/Adapter/Identity.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Uncompress/Adapter/Identity.pm @@ -8,7 +8,7 @@ use IO::Compress::Base::Common qw(:Status); our ($VERSION); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; use Compress::Raw::Zlib (); diff --git a/ext/Compress/IO/Zlib/lib/IO/Uncompress/Adapter/Inflate.pm b/ext/Compress/IO/Zlib/lib/IO/Uncompress/Adapter/Inflate.pm index 20f4e70f23..fa8242d2c1 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Uncompress/Adapter/Inflate.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Uncompress/Adapter/Inflate.pm @@ -8,7 +8,7 @@ use IO::Compress::Base::Common qw(:Status); use Compress::Raw::Zlib qw(Z_OK Z_DATA_ERROR Z_STREAM_END Z_FINISH MAX_WBITS); our ($VERSION); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; diff --git a/ext/Compress/IO/Zlib/lib/IO/Uncompress/AnyInflate.pm b/ext/Compress/IO/Zlib/lib/IO/Uncompress/AnyInflate.pm index 99dcd3361a..b2e8a98d8a 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Uncompress/AnyInflate.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Uncompress/AnyInflate.pm @@ -21,7 +21,7 @@ require Exporter ; our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $AnyInflateError); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; $AnyInflateError = ''; @ISA = qw( Exporter IO::Uncompress::Base ); @@ -344,9 +344,13 @@ If the C<$output> parameter is any other type, C<undef> will be returned. =head2 Notes -When C<$input> maps to multiple files/buffers and C<$output> is a single -file/buffer the uncompressed input files/buffers will all be stored -in C<$output> as a single uncompressed stream. + +When C<$input> maps to multiple compressed files/buffers and C<$output> is +a single file/buffer, after uncompression C<$output> will contain a +concatenation of all the uncompressed data from each of the input +files/buffers. + + diff --git a/ext/Compress/IO/Zlib/lib/IO/Uncompress/Gunzip.pm b/ext/Compress/IO/Zlib/lib/IO/Uncompress/Gunzip.pm index fbb3af80e7..d665103181 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Uncompress/Gunzip.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Uncompress/Gunzip.pm @@ -14,6 +14,7 @@ use IO::Uncompress::RawInflate ; use Compress::Raw::Zlib qw( crc32 ) ; use IO::Compress::Base::Common qw(:Status createSelfTiedObject); use IO::Compress::Gzip::Constants; +use IO::Compress::Zlib::Extra; require Exporter ; @@ -27,7 +28,7 @@ Exporter::export_ok_tags('all'); $GunzipError = ''; -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; sub new { @@ -179,28 +180,10 @@ sub _readGzipHeader($) $keep .= $buffer . $EXTRA ; if ($XLEN && *$self->{'ParseExtra'}) { - my $offset = 0 ; - while ($offset < $XLEN) { - - return $self->TruncatedHeader("FEXTRA Body") - if $offset + GZIP_FEXTRA_SUBFIELD_HEADER_SIZE > $XLEN ; - - my $id = substr($EXTRA, $offset, GZIP_FEXTRA_SUBFIELD_ID_SIZE); - $offset += GZIP_FEXTRA_SUBFIELD_ID_SIZE ; - - return $self->HeaderError("SubField ID 2nd byte is 0x00") - if *$self->{Strict} && substr($id, 1, 1) eq "\x00" ; - - my ($subLen) = unpack("v", substr($EXTRA, $offset, - GZIP_FEXTRA_SUBFIELD_LEN_SIZE)) ; - $offset += GZIP_FEXTRA_SUBFIELD_LEN_SIZE ; - - return $self->TruncatedHeader("FEXTRA Body") - if $offset + $subLen > $XLEN ; - - push @EXTRA, [$id => substr($EXTRA, $offset, $subLen)]; - $offset += $subLen ; - } + my $bad = IO::Compress::Zlib::Extra::parseRawExtra($EXTRA, + \@EXTRA, 1, 1); + return $self->HeaderError($bad) + if defined $bad; } } @@ -504,9 +487,13 @@ If the C<$output> parameter is any other type, C<undef> will be returned. =head2 Notes -When C<$input> maps to multiple files/buffers and C<$output> is a single -file/buffer the uncompressed input files/buffers will all be stored -in C<$output> as a single uncompressed stream. + +When C<$input> maps to multiple compressed files/buffers and C<$output> is +a single file/buffer, after uncompression C<$output> will contain a +concatenation of all the uncompressed data from each of the input +files/buffers. + + diff --git a/ext/Compress/IO/Zlib/lib/IO/Uncompress/Inflate.pm b/ext/Compress/IO/Zlib/lib/IO/Uncompress/Inflate.pm index d3efef615f..bf9eadbe79 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Uncompress/Inflate.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Uncompress/Inflate.pm @@ -13,7 +13,7 @@ use IO::Uncompress::RawInflate ; require Exporter ; our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $InflateError); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; $InflateError = ''; @ISA = qw( Exporter IO::Uncompress::RawInflate ); @@ -386,9 +386,13 @@ If the C<$output> parameter is any other type, C<undef> will be returned. =head2 Notes -When C<$input> maps to multiple files/buffers and C<$output> is a single -file/buffer the uncompressed input files/buffers will all be stored -in C<$output> as a single uncompressed stream. + +When C<$input> maps to multiple compressed files/buffers and C<$output> is +a single file/buffer, after uncompression C<$output> will contain a +concatenation of all the uncompressed data from each of the input +files/buffers. + + diff --git a/ext/Compress/IO/Zlib/lib/IO/Uncompress/RawInflate.pm b/ext/Compress/IO/Zlib/lib/IO/Uncompress/RawInflate.pm index 5977c9bf7a..1ed435b864 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Uncompress/RawInflate.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Uncompress/RawInflate.pm @@ -17,7 +17,7 @@ use IO::Uncompress::Adapter::Inflate ; require Exporter ; our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, %DEFLATE_CONSTANTS, $RawInflateError); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; $RawInflateError = ''; @ISA = qw( Exporter IO::Uncompress::Base ); @@ -539,9 +539,13 @@ If the C<$output> parameter is any other type, C<undef> will be returned. =head2 Notes -When C<$input> maps to multiple files/buffers and C<$output> is a single -file/buffer the uncompressed input files/buffers will all be stored -in C<$output> as a single uncompressed stream. + +When C<$input> maps to multiple compressed files/buffers and C<$output> is +a single file/buffer, after uncompression C<$output> will contain a +concatenation of all the uncompressed data from each of the input +files/buffers. + + diff --git a/ext/Compress/IO/Zlib/lib/IO/Uncompress/Unzip.pm b/ext/Compress/IO/Zlib/lib/IO/Uncompress/Unzip.pm index 4c9d882545..177906ab4c 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Uncompress/Unzip.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Uncompress/Unzip.pm @@ -11,12 +11,15 @@ use bytes; use IO::Uncompress::RawInflate ; use IO::Compress::Base::Common qw(:Status createSelfTiedObject); use IO::Uncompress::Adapter::Identity; +use IO::Compress::Zlib::Extra; +use IO::Compress::Zip::Constants; use Compress::Raw::Zlib qw(crc32) ; + BEGIN { - eval { require IO::Uncompress::Adapter::Bunzip2 ; - import IO::Uncompress::Adapter::Bunzip2 } ; + eval { require IO::Uncompress::Adapter::Bunzip2 ; + import IO::Uncompress::Adapter::Bunzip2 } ; } @@ -24,7 +27,7 @@ require Exporter ; our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $UnzipError); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; $UnzipError = ''; @ISA = qw(Exporter IO::Uncompress::RawInflate); @@ -33,7 +36,6 @@ $UnzipError = ''; push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ; Exporter::export_ok_tags('all'); - sub new { my $class = shift ; @@ -170,7 +172,7 @@ sub chkTrailer if (*$self->{ZipData}{Streaming}) { ($sig, $CRC32, $cSize, $uSize) = unpack("V V V V", $trailer) ; return $self->TrailerError("Data Descriptor signature, got $sig") - if $sig != 0x08074b50; + if $sig != ZIP_DATA_HDR_SIG; } else { ($CRC32, $cSize, $uSize) = @@ -217,7 +219,7 @@ sub chkTrailer my $sig = unpack("V", $magic) ; - if ($sig == 0x02014b50) + if ($sig == ZIP_CENTRAL_HDR_SIG) { if ($self->skipCentralDirectory($magic) != STATUS_OK ) { if (*$self->{Strict}) { @@ -229,7 +231,7 @@ sub chkTrailer } } } - elsif ($sig == 0x06054b50) + elsif ($sig == ZIP_END_CENTRAL_HDR_SIG) { if ($self->skipEndCentralDirectory($magic) != STATUS_OK) { if (*$self->{Strict}) { @@ -244,7 +246,7 @@ sub chkTrailer return STATUS_OK ; last; } - elsif ($sig == 0x04034b50) + elsif ($sig == ZIP_LOCAL_HDR_SIG) { $self->pushBack($magic) ; return STATUS_OK ; @@ -358,7 +360,7 @@ sub _isZipMagic my $buffer = shift ; return 0 if length $buffer < 4 ; my $sig = unpack("V", $buffer) ; - return $sig == 0x04034b50 ; + return $sig == ZIP_LOCAL_HDR_SIG ; } @@ -409,7 +411,8 @@ sub _readZipHeader($) my $filename; my $extraField; - my $streamingMode = ($gpFlag & 0x08) ? 1 : 0 ; + my @EXTRA = (); + my $streamingMode = ($gpFlag & ZIP_GP_FLAG_STREAMING_MASK) ? 1 : 0 ; return $self->HeaderError("Streamed Stored content not supported") if $streamingMode && $compressedMethod == 0 ; @@ -429,23 +432,29 @@ sub _readZipHeader($) if ($filename_length) { $self->smartReadExact(\$filename, $filename_length) - or return $self->HeaderError("xxx"); + or return $self->TruncatedHeader("Filename"); $keep .= $filename ; } if ($extra_length) { $self->smartReadExact(\$extraField, $extra_length) - or return $self->HeaderError("xxx"); + or return $self->TruncatedHeader("Extra Field"); + + my $bad = IO::Compress::Zlib::Extra::parseRawExtra($extraField, + \@EXTRA, 1, 0); + return $self->HeaderError($bad) + if defined $bad; + $keep .= $extraField ; } *$self->{ZipData}{Method} = $compressedMethod; - if ($compressedMethod == 8) + if ($compressedMethod == ZIP_CM_DEFLATE) { *$self->{Type} = 'zip-deflate'; } - elsif ($compressedMethod == 12) + elsif ($compressedMethod == ZIP_CM_BZIP2) { #if (! defined $IO::Uncompress::Adapter::Bunzip2::VERSION) @@ -458,7 +467,7 @@ sub _readZipHeader($) *$self->{ZipData}{CRC32} = crc32(undef); } - elsif ($compressedMethod == 0) + elsif ($compressedMethod == ZIP_CM_STORE) { # TODO -- add support for reading uncompressed @@ -491,11 +500,13 @@ sub _readZipHeader($) 'Stream' => $streamingMode, 'MethodID' => $compressedMethod, - 'MethodName' => $compressedMethod == 8 + 'MethodName' => $compressedMethod == ZIP_CM_DEFLATE ? "Deflated" - : $compressedMethod == 0 - ? "Stored" - : "Unknown" , + : $compressedMethod == ZIP_CM_BZIP2 + ? "Bzip2" + : $compressedMethod == ZIP_CM_STORE + ? "Stored" + : "Unknown" , # 'TextFlag' => $flag & GZIP_FLG_FTEXT ? 1 : 0, # 'HeaderCRCFlag' => $flag & GZIP_FLG_FHCRC ? 1 : 0, @@ -509,8 +520,8 @@ sub _readZipHeader($) # 'HeaderCRC' => $HeaderCRC, # 'Flags' => $flag, # 'ExtraFlags' => $xfl, -# 'ExtraFieldRaw' => $EXTRA, -# 'ExtraField' => [ @EXTRA ], + 'ExtraFieldRaw' => $extraField, + 'ExtraField' => [ @EXTRA ], } @@ -770,9 +781,13 @@ If the C<$output> parameter is any other type, C<undef> will be returned. =head2 Notes -When C<$input> maps to multiple files/buffers and C<$output> is a single -file/buffer the uncompressed input files/buffers will all be stored -in C<$output> as a single uncompressed stream. + +When C<$input> maps to multiple compressed files/buffers and C<$output> is +a single file/buffer, after uncompression C<$output> will contain a +concatenation of all the uncompressed data from each of the input +files/buffers. + + diff --git a/ext/Compress/IO/Zlib/t/004gziphdr.t b/ext/Compress/IO/Zlib/t/004gziphdr.t index 5956ac5c44..c09fc32852 100644 --- a/ext/Compress/IO/Zlib/t/004gziphdr.t +++ b/ext/Compress/IO/Zlib/t/004gziphdr.t @@ -380,20 +380,20 @@ for my $value ( "0D", "0A", "0A0D", "0D0A", "0A0A", "0D0D") my @tests = ( ["Sub-field truncated", - "Error with ExtraField Parameter: FEXTRA Body", + "Error with ExtraField Parameter: Truncated in FEXTRA Body Section", "Header Error: Truncated in FEXTRA Body Section", ['a', undef, undef] ], ["Length of field incorrect", - "Error with ExtraField Parameter: FEXTRA Body", + "Error with ExtraField Parameter: Truncated in FEXTRA Body Section", "Header Error: Truncated in FEXTRA Body Section", ["ab", 255, "abc"] ], ["Length of 2nd field incorrect", - "Error with ExtraField Parameter: FEXTRA Body", + "Error with ExtraField Parameter: Truncated in FEXTRA Body Section", "Header Error: Truncated in FEXTRA Body Section", ["ab", 3, "abc"], ["de", 7, "x"] ], ["Length of 2nd field incorrect", "Error with ExtraField Parameter: SubField ID 2nd byte is 0x00", - "Header Error: Truncated in FEXTRA Body Section", + "Header Error: SubField ID 2nd byte is 0x00", ["a\x00", 3, "abc"], ["de", 7, "x"] ], ); @@ -428,16 +428,19 @@ for my $value ( "0D", "0A", "0A0D", "0D0A", "0A0A", "0D0D") foreach my $check (0, 1) { - ok $x = new IO::Compress::Gzip \$buffer, -ExtraField => $input, Strict => 0 - or diag "GzipError is $GzipError" ; ; + ok $x = new IO::Compress::Gzip \$buffer, + ExtraField => $input, + Strict => 0 + or diag "GzipError is $GzipError" ; my $string = "abcd" ; $x->write($string) ; $x->close ; is anyUncompress(\$buffer), $string ; - $x = new IO::Uncompress::Gunzip \$buffer, Strict => 0, + $x = new IO::Uncompress::Gunzip \$buffer, + Strict => 0, Transparent => 0, - ParseExtra => $check; + ParseExtra => $check; if ($check) { ok ! $x ; like $GunzipError, "/^$gunzip_error/"; diff --git a/ext/Compress/IO/Zlib/t/101truncate-zip.t b/ext/Compress/IO/Zlib/t/101truncate-zip.t index d2548c577e..719da361ed 100644 --- a/ext/Compress/IO/Zlib/t/101truncate-zip.t +++ b/ext/Compress/IO/Zlib/t/101truncate-zip.t @@ -18,7 +18,7 @@ BEGIN { $extra = 1 if eval { require Test::NoWarnings ; import Test::NoWarnings; 1 }; - plan tests => 1986 + $extra; + plan tests => 2316 + $extra; }; diff --git a/ext/Compress/Raw/Zlib/Changes b/ext/Compress/Raw/Zlib/Changes new file mode 100644 index 0000000000..d48a762c36 --- /dev/null +++ b/ext/Compress/Raw/Zlib/Changes @@ -0,0 +1,68 @@ +CHANGES +------- + + 2.000_10 13 March 2006 + + * Fixed a potential NULL pointer dereference problem in + Compress::Raw::Zlib::resetLastBlockByte. + Issue highlighted by David Dyck and reproduced by Marcus Holland-Moritz. + + 2.000_09 3 March 2006 + + * Released onto CPAN + + * Documentation updates. + + 2.000_08 2 March 2006 + + * Moved the IO::* modules out into their own distributions. + + * Breakout zlib specific code into separate modules. + + * Limited support for reading/writing zip files added. + + 2.000_06 5 October 2005 + + * Added eof parameter to Compress::Zlib::inflate method. + + * Fixed issue with 64-bit + + 2.000_05 4 October 2005 + + * Renamed IO::* to IO::Compress::* & IO::Uncompress::* + + 2.000_04 23 September 2005 + + * Fixed some more non-portable test that were failing on VMS. + + * fixed problem where error messages in the oneshot interface were + getting lost. + + 2.000_03 12 September 2005 + + * Fixed some non-portable test that were failing on VMS. + + * Fixed export of zlib constants from the IO::* classes + + 2.000_02 6 September 2005 + + * Split Append mode into Append and Merge + + * Fixed typos in the documentation. + + * Added pod/FAQ.pod + + * Added libscan to Makefile.PL + + * Added InputLength for IO::Gunzip et al + + 2.000_01 22 August 2005 + + * Fixed VERSION in Compress::Gzip::Constants + + * Removed Compress::Gzip::Info from the distribution. + + 2.000_00 21 August 2005 + + * First Beta relase of Compress::zlib rewrite. + diff --git a/ext/Compress/Raw/Zlib/README b/ext/Compress/Raw/Zlib/README index 59b0133191..0fc887b7df 100644 --- a/ext/Compress/Raw/Zlib/README +++ b/ext/Compress/Raw/Zlib/README @@ -1,9 +1,9 @@ Compress::Raw::Zlib - Version 2.000_11 + Version 2.000_12 - 10 April 2006 + 17 May 2006 Copyright (c) 2005-2006 Paul Marquess. All rights reserved. diff --git a/ext/Compress/Raw/Zlib/lib/Compress/Raw/Zlib.pm b/ext/Compress/Raw/Zlib/lib/Compress/Raw/Zlib.pm index d216bd2400..84b3a7c03f 100644 --- a/ext/Compress/Raw/Zlib/lib/Compress/Raw/Zlib.pm +++ b/ext/Compress/Raw/Zlib/lib/Compress/Raw/Zlib.pm @@ -13,7 +13,7 @@ use warnings ; use bytes ; our ($VERSION, $XS_VERSION, @ISA, @EXPORT, $AUTOLOAD); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; $XS_VERSION = $VERSION; $VERSION = eval $VERSION; diff --git a/ext/Compress/Zlib/Changes b/ext/Compress/Zlib/Changes index e63ff55884..557c8ddbb8 100644 --- a/ext/Compress/Zlib/Changes +++ b/ext/Compress/Zlib/Changes @@ -1,6 +1,15 @@ CHANGES ------- + 2.000_12 16 April 2006 + + * Fixed gzread to zap the output buffer to an empty string when zero + bytes are requested. This matches the behaviour of C::Z 1.x + + 2.000_11 10 April 2006 + + * No changes. + 2.000_10 13 March 2006 * Changed gzread so that its behaviour matches C::Z::gzread 1.x if it diff --git a/ext/Compress/Zlib/README b/ext/Compress/Zlib/README index d94463f8df..a05884b92f 100644 --- a/ext/Compress/Zlib/README +++ b/ext/Compress/Zlib/README @@ -1,9 +1,9 @@ Compress::Zlib - Version 2.000_11 + Version 2.000_12 - 10 April 2006 + 17 May 2006 Copyright (c) 1995-2006 Paul Marquess. All rights reserved. diff --git a/ext/Compress/Zlib/lib/Compress/Zlib.pm b/ext/Compress/Zlib/lib/Compress/Zlib.pm index a82021a697..8f97b16657 100644 --- a/ext/Compress/Zlib/lib/Compress/Zlib.pm +++ b/ext/Compress/Zlib/lib/Compress/Zlib.pm @@ -18,7 +18,7 @@ use warnings ; use bytes ; our ($VERSION, $XS_VERSION, @ISA, @EXPORT, $AUTOLOAD); -$VERSION = '2.000_11'; +$VERSION = '2.000_12'; $XS_VERSION = $VERSION; $VERSION = eval $VERSION; |