From: Paul Marquess Date: Tue, 20 Jun 2006 13:40:47 +0000 (+0100) Subject: IO::Compress::* 2.000_13 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=e7d4598618188806a059004bf5be463e5ed0033b;p=p5sagit%2Fp5-mst-13.2.git IO::Compress::* 2.000_13 From: "Paul Marquess" Message-ID: <00b101c69466$c18f0af0$2405140a@myopwv.com> p4raw-id: //depot/perl@28407 --- diff --git a/ext/Compress/IO/Base/Changes b/ext/Compress/IO/Base/Changes index 7bff5f5..8ab7daf 100644 --- a/ext/Compress/IO/Base/Changes +++ b/ext/Compress/IO/Base/Changes @@ -1,6 +1,28 @@ CHANGES ------- + 2.000_13 20 June 2006 + + * Store compress & uncompressed sizes as 64-bit. + + * For one-shot uncompression, like this + + unzip "some.zip" => \@a, MultiStream => 1; + + Push each uncompressed stream from "some.zip" onto @a. + + * Added IO::Compress::Base::FilterEnvelope + + * Added IO::Uncompress::Base::nextStream + + * The '-' filehandle now maps to either *STDIN or *STDOUT. + This keeps mod_perl happier. Was using these before + + new IO::File("<-") + new IO::File(">-") + + 2.000_12 3 May 2006 + 2.000_11 10 April 2006 * Transparent + InputLength made more robust where input data is not diff --git a/ext/Compress/IO/Base/README b/ext/Compress/IO/Base/README index f6fea3d..4a041a3 100644 --- a/ext/Compress/IO/Base/README +++ b/ext/Compress/IO/Base/README @@ -1,9 +1,9 @@ IO::Compress::Base - Version 2.000_12 + Version 2.000_13 - 17 May 2006 + 20 June 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 952fd6c..03fbd93 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_12'; +$VERSION = '2.000_13'; #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. @@ -115,6 +115,31 @@ sub writeAt return 1; } +sub output +{ + my $self = shift ; + my $data = shift ; + my $last = shift ; + + return 1 + if length $data == 0 && ! $last ; + + if ( *$self->{FilterEnvelope} ) { + *_ = \$data; + &{ *$self->{FilterEnvelope} }(); + } + + if ( defined *$self->{FH} ) { + defined *$self->{FH}->write( $data, length $data ) + or return $self->saveErrorString(0, $!, $!); + } + else { + ${ *$self->{Buffer} } .= $data ; + } + + return 1; +} + sub getOneShotParams { return ( 'MultiStream' => [1, 1, Parse_boolean, 1], @@ -137,6 +162,8 @@ sub checkParams 'Append' => [1, 1, Parse_boolean, 0], 'BinModeIn' => [1, 1, Parse_boolean, 0], + 'FilterEnvelope' => [1, 1, Parse_any, undef], + $self->getExtraParams(), *$self->{OneShot} ? $self->getOneShotParams() : (), @@ -185,6 +212,8 @@ sub _create # Merge implies Append my $merge = $got->value('Merge') ; my $appendOutput = $got->value('Append') || $merge ; + *$obj->{Append} = $appendOutput; + *$obj->{FilterEnvelope} = $got->value('FilterEnvelope') ; if ($merge) { @@ -228,15 +257,12 @@ sub _create *$obj->{Compress} = $obj->mkComp($class, $got) or return undef; - *$obj->{BytesWritten} = 0 ; - *$obj->{UnCompSize_32bit} = 0 ; - - *$obj->{Header} = $obj->mkHeader($got) ; + *$obj->{UnCompSize} = new U64 ; + *$obj->{CompSize} = new U64 ; if ( $outType eq 'buffer') { ${ *$obj->{Buffer} } = '' unless $appendOutput ; - ${ *$obj->{Buffer} } .= *$obj->{Header}; } else { if ($outType eq 'handle') { @@ -260,13 +286,11 @@ sub _create *$obj->{StdIO} = ($outValue eq '-'); setBinModeOutput(*$obj->{FH}) ; } - - - if (length *$obj->{Header}) { - defined *$obj->{FH}->write(*$obj->{Header}, length(*$obj->{Header})) - or return $obj->saveErrorString(undef, $!, $!) ; - } } + + *$obj->{Header} = $obj->mkHeader($got) ; + $obj->output( *$obj->{Header} ) + or return undef; } else { @@ -478,7 +502,7 @@ sub _wr2 my $status ; my $buff ; my $count = 0 ; - while (($status = read($fh, $buff, 4096)) > 0) { + while (($status = read($fh, $buff, 16 * 1024)) > 0) { $count += length $buff; defined $self->syswrite($buff, @_) or return undef ; @@ -539,6 +563,7 @@ sub DESTROY my $self = shift ; $self->close() ; + # TODO - memory leak with 5.8.0 - this isn't called until # global destruction # @@ -591,14 +616,7 @@ sub syswrite return 0 if ! defined $$buffer || length $$buffer == 0 ; my $buffer_length = defined $$buffer ? length($$buffer) : 0 ; - *$self->{BytesWritten} += $buffer_length ; - my $rest = 0xFFFFFFFF - *$self->{UnCompSize_32bit} ; - if ($buffer_length > $rest) { - *$self->{UnCompSize_32bit} = $buffer_length - $rest - 1; - } - else { - *$self->{UnCompSize_32bit} += $buffer_length ; - } + *$self->{UnCompSize}->add($buffer_length) ; $self->filterUncompressed($buffer); @@ -606,20 +624,17 @@ sub syswrite # $$buffer = *$self->{Encoding}->encode($$buffer); # } - #my $length = length $$buffer; - - my $status = *$self->{Compress}->compr($buffer, *$self->{Buffer}) ; + my $outBuffer=''; + my $status = *$self->{Compress}->compr($buffer, $outBuffer) ; return $self->saveErrorString(undef, *$self->{Compress}{Error}, *$self->{Compress}{ErrorNo}) if $status == STATUS_ERROR; + *$self->{CompSize}->add(length $outBuffer) ; - if ( defined *$self->{FH} and length ${ *$self->{Buffer} }) { - defined *$self->{FH}->write( ${ *$self->{Buffer} }, length ${ *$self->{Buffer} } ) - or return $self->saveErrorString(undef, $!, $!); - ${ *$self->{Buffer} } = '' ; - } + $self->output($outBuffer) + or return undef; return $buffer_length; } @@ -660,18 +675,24 @@ sub flush { my $self = shift ; - my $status = *$self->{Compress}->flush(*$self->{Buffer}, @_) ; + my $outBuffer=''; + my $status = *$self->{Compress}->flush($outBuffer, @_) ; return $self->saveErrorString(0, *$self->{Compress}{Error}, *$self->{Compress}{ErrorNo}) if $status == STATUS_ERROR; if ( defined *$self->{FH} ) { *$self->{FH}->clearerr(); - defined *$self->{FH}->write(${ *$self->{Buffer} }, length ${ *$self->{Buffer} }) - or return $self->saveErrorString(0, $!, $!); + } + + *$self->{CompSize}->add(length $outBuffer) ; + + $self->output($outBuffer) + or return 0; + + if ( defined *$self->{FH} ) { defined *$self->{FH}->flush() or return $self->saveErrorString(0, $!, $!); - ${ *$self->{Buffer} } = '' ; } return 1; @@ -691,24 +712,16 @@ sub newStream or $self->croakError("newStream: $self->{Error}"); *$self->{Header} = $self->mkHeader($got) ; - ${ *$self->{Buffer} } .= *$self->{Header} ; - - if (defined *$self->{FH}) - { - defined *$self->{FH}->write(${ *$self->{Buffer} }, - length ${ *$self->{Buffer} }) - or return $self->saveErrorString(0, $!, $!); - ${ *$self->{Buffer} } = '' ; - } + $self->output(*$self->{Header} ) + or return 0; - #my $status = *$self->{Compress}->reset() ; my $status = $self->reset() ; return $self->saveErrorString(0, *$self->{Compress}{Error}, *$self->{Compress}{ErrorNo}) if $status == STATUS_ERROR; - *$self->{BytesWritten} = 0 ; - *$self->{UnCompSize_32bit} = 0 ; + *$self->{UnCompSize}->reset(); + *$self->{CompSize}->reset(); return 1 ; } @@ -723,40 +736,26 @@ sub _writeTrailer { my $self = shift ; - my $status = *$self->{Compress}->close(*$self->{Buffer}) ; + my $trailer = ''; + + my $status = *$self->{Compress}->close($trailer) ; return $self->saveErrorString(0, *$self->{Compress}{Error}, *$self->{Compress}{ErrorNo}) if $status == STATUS_ERROR; - my $trailer = $self->mkTrailer(); + *$self->{CompSize}->add(length $trailer) ; + + $trailer .= $self->mkTrailer(); defined $trailer or return 0; - ${ *$self->{Buffer} } .= $trailer; - - return 1 if ! defined *$self->{FH} ; - - defined *$self->{FH}->write(${ *$self->{Buffer} }, length ${ *$self->{Buffer} }) - or return $self->saveErrorString(0, $!, $!); - - ${ *$self->{Buffer} } = '' ; - - return 1; + return $self->output($trailer); } sub _writeFinalTrailer { my $self = shift ; - ${ *$self->{Buffer} } .= $self->mkFinalTrailer(); - - return 1 if ! defined *$self->{FH} ; - - defined *$self->{FH}->write(${ *$self->{Buffer} }, length ${ *$self->{Buffer} }) - or return $self->saveErrorString(0, $!, $!); - - ${ *$self->{Buffer} } = '' ; - - return 1; + return $self->output($self->mkFinalTrailer()); } sub close @@ -775,7 +774,11 @@ sub close $self->_writeFinalTrailer() or return 0 ; + $self->output( "", 1 ) + or return 0; + if (defined *$self->{FH}) { + #if (! *$self->{Handle} || *$self->{AutoClose}) { if ((! *$self->{Handle} || *$self->{AutoClose}) && ! *$self->{StdIO}) { $! = 0 ; @@ -830,7 +833,7 @@ sub tell { my $self = shift ; - return *$self->{BytesWritten} ; + return *$self->{UnCompSize}->get32bit() ; } sub eof 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 264e142..2c5da9e 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_12'; +$VERSION = '2.000_13'; @EXPORT = qw( isaFilehandle isaFilename whatIsInput whatIsOutput isaFileGlobString cleanFileGlobString oneTarget @@ -276,6 +276,14 @@ sub Validator::new { $obj->croakError("$reportClass: output filename is undef or null string") if ! defined $_[1] || $_[1] eq '' ; + + if (-e $_[1]) + { + if (-d _ ) + { + return $obj->saveErrorString("output file '$_[1]' is a directory"); + } + } } return $obj ; @@ -314,7 +322,12 @@ sub Validator::validateInputFilenames return $self->saveErrorString("input file '$filename' does not exist"); } - if (! -r $filename ) + if (-d _ ) + { + return $self->saveErrorString("input file '$filename' is a directory"); + } + + if (! -r _ ) { return $self->saveErrorString("cannot open file '$filename': $!"); } @@ -697,6 +710,128 @@ sub IO::Compress::Base::Parameters::clone return bless $obj, 'IO::Compress::Base::Parameters' ; } +package U64; + +use constant MAX32 => 0xFFFFFFFF ; +use constant LOW => 0 ; +use constant HIGH => 1; + +sub new +{ + my $class = shift ; + + my $high = 0 ; + my $low = 0 ; + + if (@_ == 2) { + $high = shift ; + $low = shift ; + } + elsif (@_ == 1) { + $low = shift ; + } + + bless [$low, $high], $class; +} + +sub newUnpack_V64 +{ + my $string = shift; + + my ($low, $hi) = unpack "V V", $string ; + bless [ $low, $hi ], "U64"; +} + +sub newUnpack_V32 +{ + my $string = shift; + + my $low = unpack "V", $string ; + bless [ $low, 0 ], "U64"; +} + +sub reset +{ + my $self = shift; + $self->[HIGH] = $self->[LOW] = 0; +} + +sub clone +{ + my $self = shift; + bless [ @$self ], ref $self ; +} + +sub getHigh +{ + my $self = shift; + return $self->[HIGH]; +} + +sub getLow +{ + my $self = shift; + return $self->[LOW]; +} + +sub get32bit +{ + my $self = shift; + return $self->[LOW]; +} + +sub add +{ + my $self = shift; + my $value = shift; + + if (ref $value eq 'U64') { + $self->[HIGH] += $value->[HIGH] ; + $value = $value->[LOW]; + } + + my $available = MAX32 - $self->[LOW] ; + + if ($value > $available) { + ++ $self->[HIGH] ; + $self->[LOW] = $value - $available - 1; + } + else { + $self->[LOW] += $value ; + } +} + +sub equal +{ + my $self = shift; + my $other = shift; + + return $self->[LOW] == $other->[LOW] && + $self->[HIGH] == $other->[HIGH] ; +} + +sub getPacked_V64 +{ + my $self = shift; + + return pack "V V", @$self ; +} + +sub getPacked_V32 +{ + my $self = shift; + + return pack "V", $self->[LOW] ; +} + +sub pack_V64 +{ + my $low = shift; + + return pack "V V", $low, 0; +} + + package IO::Compress::Base::Common; 1; diff --git a/ext/Compress/IO/Base/lib/IO/Uncompress/AnyUncompress.pm b/ext/Compress/IO/Base/lib/IO/Uncompress/AnyUncompress.pm index 54ec621..c7c71d7 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_12'; +$VERSION = '2.000_13'; $AnyUncompressError = ''; @ISA = qw( Exporter IO::Uncompress::Base ); @@ -186,7 +186,8 @@ IO::Uncompress::AnyUncompress - Uncompress gzip, zip, bzip2 or lzop file/buffer $char = $z->ungetc() $char = $z->opened() - $z->trailingData() + $data = $z->trailingData() + $status = $z->nextStream() $data = $z->getHeaderInfo() $z->tell() $z->seek($position, $whence) @@ -405,7 +406,7 @@ L section below. =over 5 -=item AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option applies to any input or output data streams to C that are filehandles. @@ -417,8 +418,7 @@ completed. This parameter defaults to 0. - -=item BinModeOut =E 0|1 +=item C<< BinModeOut => 0|1 >> When writing to a file or filehandle, set C before writing to the file. @@ -429,15 +429,16 @@ Defaults to 0. -=item -Append =E 0|1 +=item C<< Append => 0|1 >> TODO -=item -MultiStream =E 0|1 +=item C<< MultiStream => 0|1 >> -Creates a new stream after each file. +If the input file/buffer contains multiple compressed data streams, this +option will uncompress the whole lot as a single data stream. -Defaults to 1. +Defaults to 0. @@ -559,7 +560,7 @@ OPTS is a combination of the following options: =over 5 -=item -AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option is only valid when the C<$input> parameter is a filehandle. If specified, and the value is true, it will result in the file being closed once @@ -568,7 +569,7 @@ destroyed. This parameter defaults to 0. -=item -MultiStream =E 0|1 +=item C<< MultiStream => 0|1 >> @@ -581,8 +582,7 @@ start of another stream. This parameter defaults to 0. - -=item -Prime =E $string +=item C<< Prime => $string >> This option will uncompress the contents of C<$string> before processing the input file/buffer. @@ -593,21 +593,21 @@ data begins without having to read the first few bytes. If this is the case, the uncompression can be I with these bytes using this option. -=item -Transparent =E 0|1 +=item C<< Transparent => 0|1 >> If this option is set and the input file or buffer is not compressed data, the module will allow reading of it anyway. This option defaults to 1. -=item -BlockSize =E $num +=item C<< BlockSize => $num >> When reading the compressed input data, IO::Uncompress::AnyUncompress will read it in blocks of C<$num> bytes. This option defaults to 4096. -=item -InputLength =E $size +=item C<< InputLength => $size >> When present this option will limit the number of compressed bytes read from the input file/buffer to C<$size>. This option can be used in the @@ -623,7 +623,7 @@ compressed data stream. This option defaults to off. -=item -Append =E 0|1 +=item C<< Append => 0|1 >> This option controls what the C method does with uncompressed data. @@ -635,7 +635,7 @@ will be overwritten by the uncompressed data. Defaults to 0. -=item -Strict =E 0|1 +=item C<< Strict => 0|1 >> @@ -879,6 +879,27 @@ underlying file will also be closed. +=head2 nextStream + +Usage is + + my $status = $z->nextStream(); + +Skips to the next compressed data stream in the input file/buffer. If a new +compressed data stream is found, the eof marker will be cleared, C<$.> will +be reset to 0. + +Returns 1 if a new stream was found, 0 if none was found, and -1 if an +error was encountered. + +=head2 trailingData + +Usage is + + my $data = $z->trailingData(); + +Returns any data that + =head1 Importing No symbolic constants are required by this IO::Uncompress::AnyUncompress at present. diff --git a/ext/Compress/IO/Base/lib/IO/Uncompress/Base.pm b/ext/Compress/IO/Base/lib/IO/Uncompress/Base.pm index 157926d..8b64879 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_12'; +$VERSION = '2.000_13'; use constant G_EOF => 0 ; use constant G_ERR => -1 ; @@ -84,7 +84,10 @@ sub smartRead $$buf = '' unless defined $$buf ; #$$out = '' unless defined $$out ; substr($$out, $offset) = substr($$buf, *$self->{BufferOffset}, $get_size); - *$self->{BufferOffset} += length($$out) - $offset ; + if (*$self->{ConsumeInput}) + { substr($$buf, 0, $get_size) = '' } + else + { *$self->{BufferOffset} += length($$out) - $offset } } *$self->{InputLengthRemaining} -= length $$out; @@ -165,7 +168,7 @@ sub smartEof my ($self) = $_[0]; local $.; - return 0 if length *$self->{Prime}; + return 0 if length *$self->{Prime} || *$self->{PushMode}; if (defined *$self->{FH}) { *$self->{FH}->eof() } @@ -290,6 +293,7 @@ sub checkParams 'Scan' => [1, 1, Parse_boolean, 0], 'InputLength' => [1, 1, Parse_unsigned, undef], 'BinModeOut' => [1, 1, Parse_boolean, 0], + #'ConsumeInput' => [1, 1, Parse_boolean, 0], $self->getExtraParams(), @@ -370,10 +374,10 @@ sub _create *$obj->{BufferOffset} = 0 ; *$obj->{AutoClose} = $got->value('AutoClose'); *$obj->{Strict} = $got->value('Strict'); - #*$obj->{Strict} = ! $got->value('Lax'); *$obj->{BlockSize} = $got->value('BlockSize'); *$obj->{Append} = $got->value('Append'); *$obj->{AppendOutput} = $append_mode || $got->value('Append'); + *$obj->{ConsumeInput} = $got->value('ConsumeInput'); *$obj->{Transparent} = $got->value('Transparent'); *$obj->{MultiStream} = $got->value('MultiStream'); @@ -381,20 +385,26 @@ sub _create *$obj->{Scan} = $got->value('Scan'); *$obj->{ParseExtra} = $got->value('ParseExtra') || $got->value('Strict') ; - #|| ! $got->value('Lax') ; *$obj->{Type} = ''; *$obj->{Prime} = $got->value('Prime') || '' ; *$obj->{Pending} = ''; *$obj->{Plain} = 0; *$obj->{PlainBytesRead} = 0; *$obj->{InflatedBytesRead} = 0; - *$obj->{UnCompSize_32bit} = 0; + *$obj->{UnCompSize} = new U64; + *$obj->{CompSize} = new U64; *$obj->{TotalInflatedBytesRead} = 0; *$obj->{NewStream} = 0 ; *$obj->{EventEof} = 0 ; *$obj->{ClassName} = $class ; *$obj->{Params} = $got ; + if (*$obj->{ConsumeInput}) { + *$obj->{InNew} = 0; + *$obj->{Closed} = 0; + return $obj + } + my $status = $obj->mkUncomp($class, $got); return undef @@ -468,21 +478,24 @@ sub _inf my $got = $obj->checkParams($name, undef, @_) or return undef ; - $x->{Got} = $got ; - - if ($x->{Hash}) - { - while (my($k, $v) = each %$input) - { - $v = \$input->{$k} - unless defined $v ; + *$obj->{MultiStream} = $got->value('MultiStream'); + $got->value('MultiStream', 0); - $obj->_singleTarget($x, 1, $k, $v, @_) - or return undef ; - } + $x->{Got} = $got ; - return keys %$input ; - } +# if ($x->{Hash}) +# { +# while (my($k, $v) = each %$input) +# { +# $v = \$input->{$k} +# unless defined $v ; +# +# $obj->_singleTarget($x, $k, $v, @_) +# or return undef ; +# } +# +# return keys %$input ; +# } if ($x->{GlobMap}) { @@ -490,42 +503,34 @@ sub _inf foreach my $pair (@{ $x->{Pairs} }) { my ($from, $to) = @$pair ; - $obj->_singleTarget($x, 1, $from, $to, @_) + $obj->_singleTarget($x, $from, $to, @_) or return undef ; } return scalar @{ $x->{Pairs} } ; } - #if ($x->{outType} eq 'array' || $x->{outType} eq 'hash') if (! $x->{oneOutput} ) { my $inFile = ($x->{inType} eq 'filenames' || $x->{inType} eq 'filename'); $x->{inType} = $inFile ? 'filename' : 'buffer'; - my $ot = $x->{outType} ; - $x->{outType} = 'buffer'; foreach my $in ($x->{oneInput} ? $input : @$input) { my $out ; $x->{oneInput} = 1 ; - $obj->_singleTarget($x, $inFile, $in, \$out, @_) + $obj->_singleTarget($x, $in, $output, @_) or return undef ; - - if ($ot eq 'array') - { push @$output, \$out } - else - { $output->{$in} = \$out } } return 1 ; } # finally the 1 to 1 and n to 1 - return $obj->_singleTarget($x, 1, $input, $output, @_); + return $obj->_singleTarget($x, $input, $output, @_); croak "should not be here" ; } @@ -544,11 +549,11 @@ sub _singleTarget { my $self = shift ; my $x = shift ; - my $inputIsFilename = shift; my $input = shift; my $output = shift; - $x->{buff} = '' ; + my $buff = ''; + $x->{buff} = \$buff ; my $fh ; if ($x->{outType} eq 'filename') { @@ -580,16 +585,14 @@ sub _singleTarget if ($x->{oneInput}) { - defined $self->_rd2($x, $input, $inputIsFilename) + defined $self->_rd2($x, $input, $output) or return undef; } else { - my $inputIsFilename = ($x->{inType} ne 'array'); - for my $element ( ($x->{inType} eq 'hash') ? keys %$input : @$input) { - defined $self->_rd2($x, $element, $inputIsFilename) + defined $self->_rd2($x, $element, $output) or return undef ; } } @@ -599,7 +602,6 @@ sub _singleTarget ($x->{outType} eq 'handle' && $x->{Got}->value('AutoClose'))) { $x->{fh}->close() or return retErr($x, $!); - #or return $gunzip->saveErrorString(undef, $!, $!); delete $x->{fh}; } @@ -611,7 +613,7 @@ sub _rd2 my $self = shift ; my $x = shift ; my $input = shift; - my $inputIsFilename = shift; + my $output = shift; my $z = createSelfTiedObject($x->{Class}, *$self->{Error}); @@ -621,12 +623,35 @@ sub _rd2 my $status ; my $fh = $x->{fh}; - while (($status = $z->read($x->{buff})) > 0) { - if ($fh) { - print $fh $x->{buff} - or return $z->saveErrorString(undef, "Error writing to output file: $!", $!); - $x->{buff} = '' ; + while (1) { + + while (($status = $z->read($x->{buff})) > 0) { + if ($fh) { + print $fh ${ $x->{buff} } + or return $z->saveErrorString(undef, "Error writing to output file: $!", $!); + ${ $x->{buff} } = '' ; + } + } + + if (! $x->{oneOutput} ) { + my $ot = $x->{outType} ; + + if ($ot eq 'array') + { push @$output, $x->{buff} } + elsif ($ot eq 'hash') + { $output->{$input} = $x->{buff} } + + my $buff = ''; + $x->{buff} = \$buff; } + + last + unless *$self->{MultiStream}; + + $status = $z->nextStream(); + + last + unless $status == 1 ; } return $z->closeError(undef) @@ -684,7 +709,6 @@ sub readBlock } return STATUS_OK; - } sub postBlockChk @@ -728,17 +752,8 @@ sub _raw_read if (*$self->{NewStream}) { - *$self->{NewStream} = 0 ; - *$self->{EndStream} = 0 ; - $self->reset(); - - return G_ERR - unless my $magic = $self->ckMagic(); - *$self->{Info} = $self->readHeader($magic); - - return G_ERR unless defined *$self->{Info} ; - - push @{ *$self->{InfoList} }, *$self->{Info} ; + $self->gotoNextStream() > 0 + or return G_ERR; # For the headers that actually uncompressed data, put the # uncompressed data into the output buffer. @@ -748,21 +763,20 @@ sub _raw_read return $len; } - my $temp_buf ; + my $temp_buf = ''; my $outSize = 0; my $status = $self->readBlock(\$temp_buf, *$self->{BlockSize}, $outSize) ; return G_ERR if $status == STATUS_ERROR ; + my $buf_len = 0; if ($status == STATUS_OK) { + my $beforeC_len = length $temp_buf; my $before_len = defined $$buffer ? length $$buffer : 0 ; $status = *$self->{Uncomp}->uncompr(\$temp_buf, $buffer, defined *$self->{CompressedInputLengthDone} || $self->smartEof(), $outSize); -# (defined *$self->{CompressedInputLength} && -# *$self->{CompressedInputLengthRemaining} < 0) || -# $self->smartEof(), $outSize); return $self->saveErrorString(G_ERR, *$self->{Uncomp}{Error}, *$self->{Uncomp}{ErrorNo}) if $self->saveStatus($status) == STATUS_ERROR; @@ -772,19 +786,14 @@ sub _raw_read $self->filterUncompressed($buffer); - #$buf_len = *$self->{Uncomp}->count(); $buf_len = length($$buffer) - $before_len; + *$self->{CompSize}->add($beforeC_len - length $temp_buf) ; + *$self->{InflatedBytesRead} += $buf_len ; *$self->{TotalInflatedBytesRead} += $buf_len ; - my $rest = 0xFFFFFFFF - *$self->{UnCompSize_32bit} ; - if ($buf_len > $rest) { - *$self->{UnCompSize_32bit} = $buf_len - $rest - 1; - } - else { - *$self->{UnCompSize_32bit} += $buf_len ; - } + *$self->{UnCompSize}->add($buf_len) ; } if ($status == STATUS_ENDSTREAM) { @@ -812,11 +821,13 @@ sub _raw_read $self->pushBack($trailer) ; } - if (*$self->{MultiStream} && ! $self->smartEof()) { - #&& (length $temp_buf || ! $self->smartEof())){ + if (! $self->smartEof()) { *$self->{NewStream} = 1 ; - *$self->{EndStream} = 0 ; - return $buf_len ; + + if (*$self->{MultiStream}) { + *$self->{EndStream} = 0 ; + return $buf_len ; + } } } @@ -844,6 +855,56 @@ sub filterUncompressed # *$self->{EndStream} ; #} +sub nextStream +{ + my $self = shift ; + + my $status = $self->gotoNextStream(); + $status == 1 + or return $status ; + + *$self->{TotalInflatedBytesRead} = 0 ; + *$self->{LineNo} = $. = 0; + + return 1; +} + +sub gotoNextStream +{ + my $self = shift ; + + if (! *$self->{NewStream}) { + my $status = 1; + my $buffer ; + + # TODO - make this more efficient if know the offset for the end of + # the stream and seekable + $status = $self->read($buffer) + while $status > 0 ; + + return $status + if $status < 0; + } + + *$self->{NewStream} = 0 ; + *$self->{EndStream} = 0 ; + $self->reset(); + *$self->{UnCompSize}->reset(); + *$self->{CompSize}->reset(); + + return 0 + unless my $magic = $self->ckMagic(); + *$self->{Info} = $self->readHeader($magic); + + return -1 + unless defined *$self->{Info} ; + + + push @{ *$self->{InfoList} }, *$self->{Info} ; + + return 1; +} + sub streamCount { my $self = shift ; @@ -1219,80 +1280,6 @@ sub _notAvailable #*sysread = \&read; #*syswrite = \&_notAvailable; -#package IO::_infScan ; -# -#*_raw_read = \&IO::Uncompress::Base::_raw_read ; -#*smartRead = \&IO::Uncompress::Base::smartRead ; -#*smartWrite = \&IO::Uncompress::Base::smartWrite ; -#*smartSeek = \&IO::Uncompress::Base::smartSeek ; - -#sub mkIdentityUncomp -#{ -# my $self = shift ; -# my $class = shift ; -# my $got = shift ; -# -# *$self->{Uncomp} = UncompressPlugin::Identity::mkUncompObject($self, $class, $got) -# or return undef; -# -# return 1; -# -#} -# -# -#package UncompressPlugin::Identity; -# -#use strict ; -#use warnings; -# -#our ($VERSION, @ISA, @EXPORT); -# -#$VERSION = '2.000_05'; -# -#use constant STATUS_OK => 0; -#use constant STATUS_ENDSTREAM => 1; -#use constant STATUS_ERROR => 2; -# -#sub mkUncompObject -#{ -# my $class = shift ; -# -# bless { 'CompSize' => 0, -# 'UnCompSize' => 0, -# 'CRC32' => 0, -# 'ADLER32' => 0, -# }, __PACKAGE__ ; -#} -# -#sub uncompr -#{ -# my $self = shift ; -# my $from = shift ; -# my $to = shift ; -# my $eof = shift ; -# -# -# $self->{CompSize} += length $$from ; -# $self->{UnCompSize} = $self->{CompSize} ; -# -# $$to = $$from ; -# -# return STATUS_ENDSTREAM if $eof; -# return STATUS_OK ; -#} -# -#sub count -#{ -# my $self = shift ; -# return $self->{UnCompSize} ; -#} -# -#sub sync -#{ -# return STATUS_OK ; -#} -# -# package IO::Uncompress::Base ; diff --git a/ext/Compress/IO/Base/t/01misc.t b/ext/Compress/IO/Base/t/01misc.t index 6613fa3..ea40978 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 => 33 + $extra ; + plan tests => 69 + $extra ; use_ok('IO::Compress::Base::Common'); @@ -129,3 +129,82 @@ My::testParseParameters(); is whatIsOutput(sub { 1 }), '' , "Don't match code"; } + +# U64 + +{ + title "U64" ; + + my $x = new U64(); + is $x->getHigh, 0, " getHigh is 0"; + is $x->getLow, 0, " getLow is 0"; + + $x = new U64(1,2); + $x = new U64(1,2); + is $x->getHigh, 1, " getHigh is 1"; + is $x->getLow, 2, " getLow is 2"; + + $x = new U64(0xFFFFFFFF,2); + is $x->getHigh, 0xFFFFFFFF, " getHigh is 0xFFFFFFFF"; + is $x->getLow, 2, " getLow is 2"; + + $x = new U64(7, 0xFFFFFFFF); + is $x->getHigh, 7, " getHigh is 7"; + is $x->getLow, 0xFFFFFFFF, " getLow is 0xFFFFFFFF"; + + $x = new U64(666); + is $x->getHigh, 0, " getHigh is 0"; + is $x->getLow, 666, " getLow is 666"; + + title "U64 - add" ; + + $x = new U64(0, 1); + is $x->getHigh, 0, " getHigh is 0"; + is $x->getLow, 1, " getLow is 1"; + + $x->add(1); + is $x->getHigh, 0, " getHigh is 0"; + is $x->getLow, 2, " getLow is 2"; + + $x = new U64(0, 0xFFFFFFFE); + is $x->getHigh, 0, " getHigh is 0"; + is $x->getLow, 0xFFFFFFFE, " getLow is 0xFFFFFFFE"; + + $x->add(1); + is $x->getHigh, 0, " getHigh is 0"; + is $x->getLow, 0xFFFFFFFF, " getLow is 0xFFFFFFFF"; + + $x->add(1); + is $x->getHigh, 1, " getHigh is 1"; + is $x->getLow, 0, " getLow is 0"; + + $x->add(1); + is $x->getHigh, 1, " getHigh is 1"; + is $x->getLow, 1, " getLow is 1"; + + $x = new U64(1, 0xFFFFFFFE); + my $y = new U64(2, 3); + + $x->add($y); + is $x->getHigh, 4, " getHigh is 4"; + is $x->getLow, 1, " getLow is 1"; + + title "U64 - equal" ; + + $x = new U64(0, 1); + is $x->getHigh, 0, " getHigh is 0"; + is $x->getLow, 1, " getLow is 1"; + + $y = new U64(0, 1); + is $x->getHigh, 0, " getHigh is 0"; + is $x->getLow, 1, " getLow is 1"; + + my $z = new U64(0, 2); + is $x->getHigh, 0, " getHigh is 0"; + is $x->getLow, 1, " getLow is 1"; + + ok $x->equal($y), " equal"; + ok !$x->equal($z), " ! equal"; + + title "U64 - pack_V" ; +} diff --git a/ext/Compress/IO/Zlib/Changes b/ext/Compress/IO/Zlib/Changes index fd928ca..d052abe 100644 --- a/ext/Compress/IO/Zlib/Changes +++ b/ext/Compress/IO/Zlib/Changes @@ -1,6 +1,10 @@ CHANGES ------- + 2.000_13 20 June 2006 + + * Preliminary support for reading zip files with zip64 members. + 2.000_12 3 May 2006 * Moved the code for creating and parsing the gzip extra field into diff --git a/ext/Compress/IO/Zlib/README b/ext/Compress/IO/Zlib/README index fdeadaa..3812a7e 100644 --- a/ext/Compress/IO/Zlib/README +++ b/ext/Compress/IO/Zlib/README @@ -1,9 +1,9 @@ IO::Compress::Zlib - Version 2.000_12 + Version 2.000_13 - 17 May 2006 + 20 June 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 07a84fa..644920e 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_12'; +$VERSION = '2.000_13'; 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 e253d43..0c8a60c 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_12'; +$VERSION = '2.000_13'; sub mkCompObject { @@ -30,7 +30,10 @@ sub compr $self->{CompSize} += length ${ $_[0] } ; $self->{UnCompSize} = $self->{CompSize} ; - ${ $_[1] } .= ${ $_[0] }; + if ( ref $_[1] ) + { ${ $_[1] } .= ${ $_[0] } } + else + { $_[1] .= ${ $_[0] } } } return STATUS_OK ; diff --git a/ext/Compress/IO/Zlib/lib/IO/Compress/Deflate.pm b/ext/Compress/IO/Zlib/lib/IO/Compress/Deflate.pm index 9ef3ebc..c9d0aac 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_12'; +$VERSION = '2.000_13'; $DeflateError = ''; @ISA = qw(Exporter IO::Compress::RawDeflate); @@ -397,7 +397,7 @@ L section below. =over 5 -=item AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option applies to any input or output data streams to C that are filehandles. @@ -409,8 +409,7 @@ completed. This parameter defaults to 0. - -=item BinModeIn =E 0|1 +=item C<< BinModeIn => 0|1 >> When reading from a file or filehandle, set C before reading. @@ -420,7 +419,7 @@ Defaults to 0. -=item -Append =E 0|1 +=item C<< Append => 0|1 >> TODO @@ -537,7 +536,7 @@ C is any combination of the following options: =over 5 -=item AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option is only valid when the C<$output> parameter is a filehandle. If specified, and the value is true, it will result in the C<$output> being @@ -546,7 +545,7 @@ object is destroyed. This parameter defaults to 0. -=item Append =E 0|1 +=item C<< Append => 0|1 >> Opens C<$output> in append mode. @@ -580,7 +579,7 @@ This parameter defaults to 0. -=item Merge =E 0|1 +=item C<< Merge => 0|1 >> This option is used to compress input data and append it to an existing compressed data stream in C<$output>. The end result is a single compressed @@ -651,7 +650,7 @@ The default is Z_DEFAULT_STRATEGY. -=item -Strict =E 0|1 +=item C<< Strict => 0|1 >> @@ -876,18 +875,10 @@ Usage is Closes the current compressed data stream and starts a new one. -OPTS consists of the following sub-set of the the options that are -available when creating the C<$z> object, - -=over 5 - - - -=item * Level - +OPTS consists of any of the the options that are available when creating +the C<$z> object. - -=back +See the L section for more details. =head2 deflateParams @@ -972,6 +963,11 @@ TODO + + + + + =head1 SEE ALSO L, L, L, L, L, L, L, L, L, L, L, L diff --git a/ext/Compress/IO/Zlib/lib/IO/Compress/Gzip.pm b/ext/Compress/IO/Zlib/lib/IO/Compress/Gzip.pm index ce3a903..9e706d2 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Compress/Gzip.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Compress/Gzip.pm @@ -27,7 +27,7 @@ require Exporter ; our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $GzipError); -$VERSION = '2.000_12'; +$VERSION = '2.000_13'; $GzipError = '' ; @ISA = qw(Exporter IO::Compress::RawDeflate); @@ -163,7 +163,7 @@ sub mkTrailer { my $self = shift ; return pack("V V", *$self->{Compress}->crc32(), - *$self->{UnCompSize_32bit}); + *$self->{UnCompSize}->get32bit()); } sub getInverseClass @@ -516,7 +516,7 @@ L section below. =over 5 -=item AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option applies to any input or output data streams to C that are filehandles. @@ -528,8 +528,7 @@ completed. This parameter defaults to 0. - -=item BinModeIn =E 0|1 +=item C<< BinModeIn => 0|1 >> When reading from a file or filehandle, set C before reading. @@ -539,7 +538,7 @@ Defaults to 0. -=item -Append =E 0|1 +=item C<< Append => 0|1 >> TODO @@ -656,7 +655,7 @@ C is any combination of the following options: =over 5 -=item AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option is only valid when the C<$output> parameter is a filehandle. If specified, and the value is true, it will result in the C<$output> being @@ -665,7 +664,7 @@ object is destroyed. This parameter defaults to 0. -=item Append =E 0|1 +=item C<< Append => 0|1 >> Opens C<$output> in append mode. @@ -699,7 +698,7 @@ This parameter defaults to 0. -=item Merge =E 0|1 +=item C<< Merge => 0|1 >> This option is used to compress input data and append it to an existing compressed data stream in C<$output>. The end result is a single compressed @@ -770,7 +769,7 @@ The default is Z_DEFAULT_STRATEGY. -=item -Minimal =E 0|1 +=item C<< Minimal => 0|1 >> If specified, this option will force the creation of the smallest possible compliant gzip header (which is exactly 10 bytes long) as defined in @@ -784,7 +783,7 @@ be ignored if this parameter is set to 1. This parameter defaults to 0. -=item -Comment =E $comment +=item C<< Comment => $comment >> Stores the contents of C<$comment> in the COMMENT field in the gzip header. @@ -797,7 +796,7 @@ If the C<-Strict> option is disabled, the comment field can contain any character except NULL. If any null characters are present, the field will be truncated at the first NULL. -=item -Name =E $string +=item C<< Name => $string >> Stores the contents of C<$string> in the gzip NAME header field. If C is not specified, no gzip NAME field will be created. @@ -809,14 +808,14 @@ If C<-Strict> is disabled, then C<$string> can contain any character except NULL. If any null characters are present, the field will be truncated at the first NULL. -=item -Time =E $number +=item C<< Time => $number >> Sets the MTIME field in the gzip header to $number. This field defaults to the time the C object was created if this option is not specified. -=item -TextFlag =E 0|1 +=item C<< TextFlag => 0|1 >> This parameter controls the setting of the FLG.FTEXT bit in the gzip header. It is used to signal that the data stored in the gzip file/buffer @@ -824,7 +823,7 @@ is probably text. The default is 0. -=item -HeaderCRC =E 0|1 +=item C<< HeaderCRC => 0|1 >> When true this parameter will set the FLG.FHCRC bit to 1 in the gzip header and set the CRC16 header field to the CRC of the complete gzip header @@ -837,7 +836,7 @@ you want to maximize the portability of your gzip files. This parameter defaults to 0. -=item -OS_Code =E $value +=item C<< OS_Code => $value >> Stores C<$value> in the gzip OS header field. A number between 0 and 255 is valid. @@ -846,7 +845,7 @@ If not specified, this parameter defaults to the OS code of the Operating System this module was built on. The value 3 is used as a catch-all for all Unix variants and unknown Operating Systems. -=item -ExtraField =E $data +=item C<< ExtraField => $data >> This parameter allows additional metadata to be stored in the ExtraField in the gzip header. An RFC 1952 compliant ExtraField consists of zero or more @@ -886,20 +885,20 @@ consist of any arbitrary byte stream. The maximum size of the Extra Field 65535 bytes. -=item -ExtraFlags =E $value +=item C<< ExtraFlags => $value >> Sets the XFL byte in the gzip header to C<$value>. If this option is not present, the value stored in XFL field will be determined by the setting of the C option. -If C Z_BEST_SPEED> has been specified then XFL is set to 2. -If C Z_BEST_COMPRESSION> has been specified then XFL is set to 4. +If C<< Level => Z_BEST_SPEED >> has been specified then XFL is set to 2. +If C<< Level => Z_BEST_COMPRESSION >> has been specified then XFL is set to 4. Otherwise XFL is set to 0. -=item -Strict =E 0|1 +=item C<< Strict => 0|1 >> @@ -1191,18 +1190,10 @@ Usage is Closes the current compressed data stream and starts a new one. -OPTS consists of the following sub-set of the the options that are -available when creating the C<$z> object, - -=over 5 - - - -=item * Level - +OPTS consists of any of the the options that are available when creating +the C<$z> object. - -=back +See the L section for more details. =head2 deflateParams @@ -1287,6 +1278,11 @@ TODO + + + + + =head1 SEE ALSO L, L, L, L, L, L, L, L, L, L, L, L 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 9c671b5..0b1a7c1 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_12'; +$VERSION = '2.000_13'; @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 0f917e2..3ad280b 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_12'; +$VERSION = '2.000_13'; $RawDeflateError = ''; @ISA = qw(Exporter IO::Compress::Base); @@ -202,8 +202,10 @@ sub createMerge my $def = *$self->{Compress} = $inf->createDeflate(); *$self->{Header} = *$inf->{Info}{Header}; - *$self->{UnCompSize_32bit} = - *$self->{BytesWritten} = *$inf->{UnCompSize_32bit} ; + *$self->{UnCompSize} = *$inf->{UnCompSize}->clone(); + *$self->{CompSize} = *$inf->{CompSize}->clone(); + # TODO -- fix this + #*$self->{CompSize} = new U64(0, *$self->{UnCompSize_32bit}); if ( $outType eq 'buffer') @@ -481,7 +483,7 @@ L section below. =over 5 -=item AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option applies to any input or output data streams to C that are filehandles. @@ -493,8 +495,7 @@ completed. This parameter defaults to 0. - -=item BinModeIn =E 0|1 +=item C<< BinModeIn => 0|1 >> When reading from a file or filehandle, set C before reading. @@ -504,7 +505,7 @@ Defaults to 0. -=item -Append =E 0|1 +=item C<< Append => 0|1 >> TODO @@ -621,7 +622,7 @@ C is any combination of the following options: =over 5 -=item AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option is only valid when the C<$output> parameter is a filehandle. If specified, and the value is true, it will result in the C<$output> being @@ -630,7 +631,7 @@ object is destroyed. This parameter defaults to 0. -=item Append =E 0|1 +=item C<< Append => 0|1 >> Opens C<$output> in append mode. @@ -664,7 +665,7 @@ This parameter defaults to 0. -=item Merge =E 0|1 +=item C<< Merge => 0|1 >> This option is used to compress input data and append it to an existing compressed data stream in C<$output>. The end result is a single compressed @@ -735,7 +736,7 @@ The default is Z_DEFAULT_STRATEGY. -=item -Strict =E 0|1 +=item C<< Strict => 0|1 >> @@ -960,18 +961,10 @@ Usage is Closes the current compressed data stream and starts a new one. -OPTS consists of the following sub-set of the the options that are -available when creating the C<$z> object, - -=over 5 - - - -=item * Level - +OPTS consists of any of the the options that are available when creating +the C<$z> object. - -=back +See the L section for more details. =head2 deflateParams @@ -1056,6 +1049,11 @@ TODO + + + + + =head1 SEE ALSO L, L, L, L, L, L, L, L, L, L, L, L diff --git a/ext/Compress/IO/Zlib/lib/IO/Compress/Zip.pm b/ext/Compress/IO/Zlib/lib/IO/Compress/Zip.pm index ea189b0..adbdf23 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Compress/Zip.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Compress/Zip.pm @@ -8,6 +8,7 @@ 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::Zlib::Extra; use IO::Compress::Zip::Constants; @@ -26,7 +27,7 @@ require Exporter ; our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $ZipError); -$VERSION = '2.000_12'; +$VERSION = '2.000_13'; $ZipError = ''; @ISA = qw(Exporter IO::Compress::RawDeflate); @@ -88,7 +89,8 @@ sub mkComp if ! defined $obj; if (! defined *$self->{ZipData}{StartOffset}) { - *$self->{ZipData}{StartOffset} = *$self->{ZipData}{Offset} = 0; + *$self->{ZipData}{StartOffset} = 0; + *$self->{ZipData}{Offset} = new U64 ; } return $obj; @@ -122,7 +124,7 @@ sub mkHeader my $self = shift; my $param = shift ; - *$self->{ZipData}{StartOffset} = *$self->{ZipData}{Offset} ; + *$self->{ZipData}{StartOffset} = *$self->{ZipData}{Offset}->get32bit() ; my $filename = ''; $filename = $param->value('Name') || ''; @@ -136,6 +138,21 @@ sub mkHeader my $extra = ''; my $ctlExtra = ''; + my $empty = 0; + + if (*$self->{ZipData}{Zip64}) { + $empty = 0xFFFF; + + my $x = ''; + $x .= pack "V V", 0, 0 ; # uncompressedLength + $x .= pack "V V", 0, 0 ; # compressedLength + $x .= *$self->{ZipData}{Offset}->getPacked_V64() ; # offset to local hdr + #$x .= pack "V ", 0 ; # disk no + + $x = IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_ZIP64, $x); + $extra .= $x; + $ctlExtra .= $x; + } if (! $param->value('Minimal')) { if (defined $param->value('exTime')) @@ -160,6 +177,7 @@ sub mkHeader if defined $param->value('ExtraFieldCentral'); } + my $extAttr = 0; $extAttr = $param->value('Mode') << 16 if defined $param->value('Mode') ; @@ -170,11 +188,14 @@ sub mkHeader my $method = *$self->{ZipData}{Method} ; - # deflate is 20 - # bzip2 is 46 - my $madeBy = ($param->value('OS_Code') << 8) + - $ZIP_CM_MIN_VERSIONS{$method}; - my $extract = $ZIP_CM_MIN_VERSIONS{$method}; + my $version = $ZIP_CM_MIN_VERSIONS{$method}; + $version = ZIP64_MIN_VERSION + if ZIP64_MIN_VERSION > $version && *$self->{ZipData}{Zip64}; + my $madeBy = ($param->value('OS_Code') << 8) + $version; + my $extract = $version; + + *$self->{ZipData}{Version} = $version; + *$self->{ZipData}{MadeBy} = $madeBy; my $ifa = 0; $ifa |= ZIP_IFA_TEXT_MASK @@ -186,8 +207,8 @@ sub mkHeader $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', $empty ; # compressed length - 0 when streaming + $hdr .= pack 'V', $empty ; # uncompressed length - 0 when streaming $hdr .= pack 'v', length $filename ; # filename length $hdr .= pack 'v', length $extra ; # extra length @@ -204,21 +225,27 @@ sub mkHeader $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', $empty ; # compressed length + $ctl .= pack 'V', $empty ; # uncompressed length $ctl .= pack 'v', length $filename ; # filename 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', $ifa ; # internal file attributes $ctl .= pack 'V', $extAttr ; # external file attributes - $ctl .= pack 'V', *$self->{ZipData}{Offset} ; # offset to local header + if (! *$self->{ZipData}{Zip64}) { + $ctl .= pack 'V', *$self->{ZipData}{Offset}->get32bit() ; # offset to local header + } + else { + $ctl .= pack 'V', $empty ; # offset to local header + } $ctl .= $filename ; + *$self->{ZipData}{StartOffset64} = 4 + length $ctl; $ctl .= $ctlExtra ; $ctl .= $comment ; - *$self->{ZipData}{Offset} += length $hdr ; + *$self->{ZipData}{Offset}->add(length $hdr) ; *$self->{ZipData}{CentralHeader} = $ctl; @@ -231,19 +258,26 @@ sub mkTrailer my $crc32 ; if (*$self->{ZipData}{Method} == ZIP_CM_DEFLATE) { - $crc32 = *$self->{Compress}->crc32(); + $crc32 = pack "V", *$self->{Compress}->crc32(); } else { - $crc32 = *$self->{ZipData}{CRC32}; + $crc32 = pack "V", *$self->{ZipData}{CRC32}; } - my $compressedBytes = *$self->{Compress}->compressedBytes(); - my $uncompressedBytes = *$self->{Compress}->uncompressedBytes(); + my $ctl = *$self->{ZipData}{CentralHeader} ; + + my $sizes ; + if (! *$self->{ZipData}{Zip64}) { + $sizes .= *$self->{CompSize}->getPacked_V32() ; # Compressed size + $sizes .= *$self->{UnCompSize}->getPacked_V32() ; # Uncompressed size + } + else { + $sizes .= *$self->{CompSize}->getPacked_V64() ; # Compressed size + $sizes .= *$self->{UnCompSize}->getPacked_V64() ; # Uncompressed size + } + + my $data = $crc32 . $sizes ; - my $data ; - $data .= pack "V", $crc32 ; # CRC32 - $data .= pack "V", $compressedBytes ; # Compressed Size - $data .= pack "V", $uncompressedBytes; # Uncompressed Size my $hdr = ''; @@ -256,10 +290,17 @@ sub mkTrailer or return undef; } - my $ctl = *$self->{ZipData}{CentralHeader} ; - substr($ctl, 16, 12) = $data ; + if (! *$self->{ZipData}{Zip64}) + { substr($ctl, 16, length $data) = $data } + else { + substr($ctl, 16, length $crc32) = $crc32 ; + my $s = *$self->{UnCompSize}->getPacked_V64() ; # Uncompressed size + $s .= *$self->{CompSize}->getPacked_V64() ; # Compressed size + substr($ctl, *$self->{ZipData}{StartOffset64}, length $s) = $s ; + } - *$self->{ZipData}{Offset} += length($hdr) + $compressedBytes; + *$self->{ZipData}{Offset}->add(length($hdr)); + *$self->{ZipData}{Offset}->add( *$self->{CompSize} ); push @{ *$self->{ZipData}{CentralDir} }, $ctl ; return $hdr; @@ -272,21 +313,56 @@ sub mkFinalTrailer my $comment = ''; $comment = *$self->{ZipData}{ZipComment} ; + my $cd_offset = *$self->{ZipData}{Offset}->get32bit() ; # offset to start central dir + my $entries = @{ *$self->{ZipData}{CentralDir} }; my $cd = join '', @{ *$self->{ZipData}{CentralDir} }; + my $cd_len = length $cd ; + + my $z64e = ''; + + if ( *$self->{ZipData}{Zip64} ) { + + my $v = *$self->{ZipData}{Version} ; + my $mb = *$self->{ZipData}{MadeBy} ; + $z64e .= pack 'v', $v ; # Version made by + $z64e .= pack 'v', $mb ; # Version to extract + $z64e .= pack 'V', 0 ; # number of disk + $z64e .= pack 'V', 0 ; # number of disk with central dir + $z64e .= U64::pack_V64 $entries ; # entries in central dir on this disk + $z64e .= U64::pack_V64 $entries ; # entries in central dir + $z64e .= U64::pack_V64 $cd_len ; # size of central dir + $z64e .= *$self->{ZipData}{Offset}->getPacked_V64() ; # offset to start central dir + + $z64e = pack("V", ZIP64_END_CENTRAL_REC_HDR_SIG) # signature + . U64::pack_V64(length $z64e) + . $z64e ; + + *$self->{ZipData}{Offset}->add(length $cd) ; + + $z64e .= pack "V", ZIP64_END_CENTRAL_LOC_HDR_SIG; # signature + $z64e .= pack 'V', 0 ; # number of disk with central dir + $z64e .= *$self->{ZipData}{Offset}->getPacked_V64() ; # offset to end zip64 central dir + $z64e .= pack 'V', 1 ; # Total number of disks + + # TODO - fix these when info-zip 3 is fixed. + #$cd_len = + #$cd_offset = + $entries = 0xFFFF ; + } my $ecd = ''; $ecd .= pack "V", ZIP_END_CENTRAL_HDR_SIG ; # signature $ecd .= pack 'v', 0 ; # number of disk - $ecd .= pack 'v', 0 ; # number if disk with central dir + $ecd .= pack 'v', 0 ; # number of disk with central dir $ecd .= pack 'v', $entries ; # entries in central dir on this disk $ecd .= pack 'v', $entries ; # entries in central dir - $ecd .= pack 'V', length $cd ; # size of central dir - $ecd .= pack 'V', *$self->{ZipData}{Offset} ; # offset to start central dir + $ecd .= pack 'V', $cd_len ; # size of central dir + $ecd .= pack 'V', $cd_offset ; # offset to start central dir $ecd .= pack 'v', length $comment ; # zipfile comment length $ecd .= $comment; - return $cd . $ecd ; + return $cd . $z64e . $ecd ; } sub ckParams @@ -313,8 +389,12 @@ sub ckParams $got->value("CTime", $timeRef->[2]); } + *$self->{ZipData}{Zip64} = $got->value('Zip64'); *$self->{ZipData}{Stream} = $got->value('Stream'); + return $self->saveErrorString(undef, "Zip64 only supported if Stream enabled") + if *$self->{ZipData}{Zip64} && ! *$self->{ZipData}{Stream} ; + my $method = $got->value('Method'); return $self->saveErrorString(undef, "Unknown Method '$method'") if ! defined $ZIP_CM_MIN_VERSIONS{$method}; @@ -375,6 +455,7 @@ sub getExtraParams # # Zip header fields 'Minimal' => [0, 1, Parse_boolean, 0], + 'Zip64' => [0, 1, Parse_boolean, 0], 'Comment' => [0, 1, Parse_any, ''], 'ZipComment'=> [0, 1, Parse_any, ''], 'Name' => [0, 1, Parse_any, ''], @@ -729,7 +810,7 @@ L section below. =over 5 -=item AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option applies to any input or output data streams to C that are filehandles. @@ -741,8 +822,7 @@ completed. This parameter defaults to 0. - -=item BinModeIn =E 0|1 +=item C<< BinModeIn => 0|1 >> When reading from a file or filehandle, set C before reading. @@ -752,7 +832,7 @@ Defaults to 0. -=item -Append =E 0|1 +=item C<< Append => 0|1 >> TODO @@ -869,7 +949,7 @@ C is any combination of the following options: =over 5 -=item AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option is only valid when the C<$output> parameter is a filehandle. If specified, and the value is true, it will result in the C<$output> being @@ -878,7 +958,7 @@ object is destroyed. This parameter defaults to 0. -=item Append =E 0|1 +=item C<< Append => 0|1 >> Opens C<$output> in append mode. @@ -910,19 +990,19 @@ This parameter defaults to 0. -=item -Name =E $string +=item C<< Name => $string >> Stores the contents of C<$string> in the zip filename header field. If C is not specified, no zip filename field will be created. -=item -Time =E $number +=item C<< Time => $number >> Sets the last modified time field in the zip header to $number. This field defaults to the time the C object was created if this option is not specified. -=item -exTime =E [$atime, $mtime, $ctime] +=item C<< exTime => [$atime, $mtime, $ctime] >> This option expects an array reference with exactly three elements: C<$atime>, C and C<$ctime>. These correspond to the last access @@ -936,21 +1016,21 @@ If the C option is set to true, this option will be ignored. By default no extended time field is created. -=item -Comment =E $comment +=item C<< Comment => $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 $comment +=item C<< ZipComment => $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 $method +=item C<< Method => $method >> Controls which compression method is used. At present three compression methods are supported, namely Store (no compression at all), Deflate and @@ -971,7 +1051,7 @@ content when C is not available. The default method is ZIP_CM_DEFLATE. -=item Stream =E 0|1 +=item C<< Stream => 0|1 >> This option controls whether the zip file/buffer output is created in streaming mode. @@ -981,7 +1061,7 @@ is 0), the output file must be seekable. The default is 1. -=item -TextFlag =E 0|1 +=item C<< TextFlag => 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 @@ -989,8 +1069,8 @@ text. The default is 0. -=item ExtraFieldLocal =E $data -=item ExtraFieldCentral =E $data +=item C<< ExtraFieldLocal => $data >> +=item C<< ExtraFieldCentral => $data >> These options allows additional metadata to be stored in the local and central headers in the zip file/buffer. @@ -1031,14 +1111,14 @@ If the C option is set to true, this option will be ignored. The maximum size of an extra field 65535 bytes. -=item Minimal =E 1|0 +=item C<< Minimal => 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 number +=item C<< BlockSize100K => number >> Specify the number of 100K blocks bzip2 uses during compression. @@ -1049,7 +1129,7 @@ otherwise. The default is 1. -=item WorkFactor =E number +=item C<< WorkFactor => number >> Specifies how much effort bzip2 should take before resorting to a slower fallback compression algorithm. @@ -1101,7 +1181,7 @@ The default is Z_DEFAULT_STRATEGY. -=item -Strict =E 0|1 +=item C<< Strict => 0|1 >> @@ -1326,18 +1406,10 @@ Usage is Closes the current compressed data stream and starts a new one. -OPTS consists of the following sub-set of the the options that are -available when creating the C<$z> object, - -=over 5 - - - -=item * Level +OPTS consists of any of the the options that are available when creating +the C<$z> object. - - -=back +See the L section for more details. =head2 deflateParams @@ -1432,6 +1504,11 @@ TODO + + + + + =head1 SEE ALSO L, L, L, L, L, L, L, L, L, L, L, L, L 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 952a3b3..f962b72 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Compress/Zip/Constants.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Compress/Zip/Constants.pm @@ -7,7 +7,7 @@ require Exporter; our ($VERSION, @ISA, @EXPORT, %ZIP_CM_MIN_VERSIONS); -$VERSION = '2.000_12'; +$VERSION = '2.000_13'; @ISA = qw(Exporter); @@ -21,15 +21,21 @@ $VERSION = '2.000_12'; ZIP_DATA_HDR_SIG ZIP_CENTRAL_HDR_SIG ZIP_END_CENTRAL_HDR_SIG + ZIP64_END_CENTRAL_REC_HDR_SIG + ZIP64_END_CENTRAL_LOC_HDR_SIG + ZIP64_ARCHIVE_EXTRA_SIG + ZIP64_DIGITAL_SIGNATURE_SIG ZIP_GP_FLAG_STREAMING_MASK + ZIP_EXTRA_ID_ZIP64 ZIP_EXTRA_ID_EXT_TIMESTAMP ZIP_EXTRA_ID_INFO_ZIP_UNIX ZIP_IFA_TEXT_MASK %ZIP_CM_MIN_VERSIONS + ZIP64_MIN_VERSION ); @@ -50,11 +56,18 @@ 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 ZIP64_END_CENTRAL_REC_HDR_SIG => 0x06064b50; +use constant ZIP64_END_CENTRAL_LOC_HDR_SIG => 0x07064b50; +use constant ZIP64_ARCHIVE_EXTRA_SIG => 0x08064b50; +use constant ZIP64_DIGITAL_SIGNATURE_SIG => 0x05054b50; # Extra Field ID's +use constant ZIP_EXTRA_ID_ZIP64 => pack "v", 1; use constant ZIP_EXTRA_ID_EXT_TIMESTAMP => "UT"; use constant ZIP_EXTRA_ID_INFO_ZIP_UNIX => "Ux"; +use constant ZIP64_MIN_VERSION => 45; + %ZIP_CM_MIN_VERSIONS = ( ZIP_CM_STORE() => 20, ZIP_CM_DEFLATE() => 20, 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 98c9955..7aa402b 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_12'; +$VERSION = '2.000_13'; @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 index 68ef02e..8a9b9c4 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Compress/Zlib/Extra.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Compress/Zlib/Extra.pm @@ -8,7 +8,7 @@ use bytes; our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS); -$VERSION = '2.000_12'; +$VERSION = '2.000_13'; use IO::Compress::Gzip::Constants; @@ -157,8 +157,6 @@ sub parseExtraField return $bad if $bad ; $out .= mkSubField(@$pair); - #$out .= $pair->[0] . pack("v", length $pair->[1]) . - # $pair->[1] ; } } else { @@ -172,8 +170,6 @@ sub parseExtraField return $bad if $bad ; $out .= mkSubField($data->[$ix], $data->[$ix+1]); - #$out .= $data->[$ix] . pack("v", length $data->[$ix+1]) . - # $data->[$ix+1] ; } } } @@ -183,7 +179,6 @@ sub parseExtraField return $bad if $bad ; $out .= mkSubField($id, $info); - #$out .= $id . pack("v", length $info) . $info ; } } else { 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 b91f4326..628bfef 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_12'; +$VERSION = '2.000_13'; use Compress::Raw::Zlib (); @@ -55,8 +55,8 @@ sub reset $self->{CompSize} = 0; $self->{UnCompSize} = 0; - $self->{CRC32} = Compress::Zlib::crc32(''); - $self->{ADLER32} = Compress::Zlib::adler32(''); + $self->{CRC32} = Compress::Raw::Zlib::crc32(''); + $self->{ADLER32} = Compress::Raw::Zlib::adler32(''); return STATUS_OK ; } 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 fa8242d..99036a0 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_12'; +$VERSION = '2.000_13'; diff --git a/ext/Compress/IO/Zlib/lib/IO/Uncompress/AnyInflate.pm b/ext/Compress/IO/Zlib/lib/IO/Uncompress/AnyInflate.pm index b2e8a98..8c6be98 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_12'; +$VERSION = '2.000_13'; $AnyInflateError = ''; @ISA = qw( Exporter IO::Uncompress::Base ); @@ -146,7 +146,8 @@ IO::Uncompress::AnyInflate - Uncompress zlib-based (zip, gzip) file/buffer $status = $z->inflateSync() - $z->trailingData() + $data = $z->trailingData() + $status = $z->nextStream() $data = $z->getHeaderInfo() $z->tell() $z->seek($position, $whence) @@ -362,7 +363,7 @@ L section below. =over 5 -=item AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option applies to any input or output data streams to C that are filehandles. @@ -374,8 +375,7 @@ completed. This parameter defaults to 0. - -=item BinModeOut =E 0|1 +=item C<< BinModeOut => 0|1 >> When writing to a file or filehandle, set C before writing to the file. @@ -386,15 +386,16 @@ Defaults to 0. -=item -Append =E 0|1 +=item C<< Append => 0|1 >> TODO -=item -MultiStream =E 0|1 +=item C<< MultiStream => 0|1 >> -Creates a new stream after each file. +If the input file/buffer contains multiple compressed data streams, this +option will uncompress the whole lot as a single data stream. -Defaults to 1. +Defaults to 0. @@ -516,7 +517,7 @@ OPTS is a combination of the following options: =over 5 -=item -AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option is only valid when the C<$input> parameter is a filehandle. If specified, and the value is true, it will result in the file being closed once @@ -525,7 +526,7 @@ destroyed. This parameter defaults to 0. -=item -MultiStream =E 0|1 +=item C<< MultiStream => 0|1 >> @@ -538,8 +539,7 @@ start of another stream. This parameter defaults to 0. - -=item -Prime =E $string +=item C<< Prime => $string >> This option will uncompress the contents of C<$string> before processing the input file/buffer. @@ -550,21 +550,21 @@ data begins without having to read the first few bytes. If this is the case, the uncompression can be I with these bytes using this option. -=item -Transparent =E 0|1 +=item C<< Transparent => 0|1 >> If this option is set and the input file or buffer is not compressed data, the module will allow reading of it anyway. This option defaults to 1. -=item -BlockSize =E $num +=item C<< BlockSize => $num >> When reading the compressed input data, IO::Uncompress::AnyInflate will read it in blocks of C<$num> bytes. This option defaults to 4096. -=item -InputLength =E $size +=item C<< InputLength => $size >> When present this option will limit the number of compressed bytes read from the input file/buffer to C<$size>. This option can be used in the @@ -580,7 +580,7 @@ compressed data stream. This option defaults to off. -=item -Append =E 0|1 +=item C<< Append => 0|1 >> This option controls what the C method does with uncompressed data. @@ -592,7 +592,7 @@ will be overwritten by the uncompressed data. Defaults to 0. -=item -Strict =E 0|1 +=item C<< Strict => 0|1 >> @@ -671,7 +671,7 @@ uncompressed data actually read from the file. -=item -ParseExtra =E 0|1 +=item C<< ParseExtra => 0|1 >> If the gzip FEXTRA header field is present and this option is set, it will force the module to check that it conforms to the sub-field structure as @@ -914,6 +914,27 @@ underlying file will also be closed. +=head2 nextStream + +Usage is + + my $status = $z->nextStream(); + +Skips to the next compressed data stream in the input file/buffer. If a new +compressed data stream is found, the eof marker will be cleared, C<$.> will +be reset to 0. + +Returns 1 if a new stream was found, 0 if none was found, and -1 if an +error was encountered. + +=head2 trailingData + +Usage is + + my $data = $z->trailingData(); + +Returns any data that + =head1 Importing No symbolic constants are required by this IO::Uncompress::AnyInflate at present. diff --git a/ext/Compress/IO/Zlib/lib/IO/Uncompress/Gunzip.pm b/ext/Compress/IO/Zlib/lib/IO/Uncompress/Gunzip.pm index d665103..5eab533 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Uncompress/Gunzip.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Uncompress/Gunzip.pm @@ -28,7 +28,7 @@ Exporter::export_ok_tags('all'); $GunzipError = ''; -$VERSION = '2.000_12'; +$VERSION = '2.000_13'; sub new { @@ -105,7 +105,7 @@ sub chkTrailer return $self->TrailerError("CRC mismatch") if $CRC32 != *$self->{Uncomp}->crc32() ; - my $exp_isize = *$self->{Uncomp}->uncompressedBytes(); + my $exp_isize = *$self->{UnCompSize}->get32bit(); return $self->TrailerError("ISIZE mismatch. Got $ISIZE" . ", expected $exp_isize") if $ISIZE != $exp_isize ; @@ -304,7 +304,8 @@ IO::Uncompress::Gunzip - Read RFC 1952 files/buffers $status = $z->inflateSync() - $z->trailingData() + $data = $z->trailingData() + $status = $z->nextStream() $data = $z->getHeaderInfo() $z->tell() $z->seek($position, $whence) @@ -505,7 +506,7 @@ L section below. =over 5 -=item AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option applies to any input or output data streams to C that are filehandles. @@ -517,8 +518,7 @@ completed. This parameter defaults to 0. - -=item BinModeOut =E 0|1 +=item C<< BinModeOut => 0|1 >> When writing to a file or filehandle, set C before writing to the file. @@ -529,15 +529,16 @@ Defaults to 0. -=item -Append =E 0|1 +=item C<< Append => 0|1 >> TODO -=item -MultiStream =E 0|1 +=item C<< MultiStream => 0|1 >> -Creates a new stream after each file. +If the input file/buffer contains multiple compressed data streams, this +option will uncompress the whole lot as a single data stream. -Defaults to 1. +Defaults to 0. @@ -659,7 +660,7 @@ OPTS is a combination of the following options: =over 5 -=item -AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option is only valid when the C<$input> parameter is a filehandle. If specified, and the value is true, it will result in the file being closed once @@ -668,7 +669,7 @@ destroyed. This parameter defaults to 0. -=item -MultiStream =E 0|1 +=item C<< MultiStream => 0|1 >> @@ -681,8 +682,7 @@ start of another stream. This parameter defaults to 0. - -=item -Prime =E $string +=item C<< Prime => $string >> This option will uncompress the contents of C<$string> before processing the input file/buffer. @@ -693,21 +693,21 @@ data begins without having to read the first few bytes. If this is the case, the uncompression can be I with these bytes using this option. -=item -Transparent =E 0|1 +=item C<< Transparent => 0|1 >> If this option is set and the input file or buffer is not compressed data, the module will allow reading of it anyway. This option defaults to 1. -=item -BlockSize =E $num +=item C<< BlockSize => $num >> When reading the compressed input data, IO::Uncompress::Gunzip will read it in blocks of C<$num> bytes. This option defaults to 4096. -=item -InputLength =E $size +=item C<< InputLength => $size >> When present this option will limit the number of compressed bytes read from the input file/buffer to C<$size>. This option can be used in the @@ -723,7 +723,7 @@ compressed data stream. This option defaults to off. -=item -Append =E 0|1 +=item C<< Append => 0|1 >> This option controls what the C method does with uncompressed data. @@ -735,7 +735,7 @@ will be overwritten by the uncompressed data. Defaults to 0. -=item -Strict =E 0|1 +=item C<< Strict => 0|1 >> @@ -796,7 +796,7 @@ uncompressed data actually read from the file. -=item -ParseExtra =E 0|1 +=item C<< ParseExtra => 0|1 >> If the gzip FEXTRA header field is present and this option is set, it will force the module to check that it conforms to the sub-field structure as @@ -1057,6 +1057,27 @@ underlying file will also be closed. +=head2 nextStream + +Usage is + + my $status = $z->nextStream(); + +Skips to the next compressed data stream in the input file/buffer. If a new +compressed data stream is found, the eof marker will be cleared, C<$.> will +be reset to 0. + +Returns 1 if a new stream was found, 0 if none was found, and -1 if an +error was encountered. + +=head2 trailingData + +Usage is + + my $data = $z->trailingData(); + +Returns any data that + =head1 Importing No symbolic constants are required by this IO::Uncompress::Gunzip at present. diff --git a/ext/Compress/IO/Zlib/lib/IO/Uncompress/Inflate.pm b/ext/Compress/IO/Zlib/lib/IO/Uncompress/Inflate.pm index bf9eadb..1435321 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_12'; +$VERSION = '2.000_13'; $InflateError = ''; @ISA = qw( Exporter IO::Uncompress::RawInflate ); @@ -203,7 +203,8 @@ IO::Uncompress::Inflate - Read RFC 1950 files/buffers $status = $z->inflateSync() - $z->trailingData() + $data = $z->trailingData() + $status = $z->nextStream() $data = $z->getHeaderInfo() $z->tell() $z->seek($position, $whence) @@ -404,7 +405,7 @@ L section below. =over 5 -=item AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option applies to any input or output data streams to C that are filehandles. @@ -416,8 +417,7 @@ completed. This parameter defaults to 0. - -=item BinModeOut =E 0|1 +=item C<< BinModeOut => 0|1 >> When writing to a file or filehandle, set C before writing to the file. @@ -428,15 +428,16 @@ Defaults to 0. -=item -Append =E 0|1 +=item C<< Append => 0|1 >> TODO -=item -MultiStream =E 0|1 +=item C<< MultiStream => 0|1 >> -Creates a new stream after each file. +If the input file/buffer contains multiple compressed data streams, this +option will uncompress the whole lot as a single data stream. -Defaults to 1. +Defaults to 0. @@ -558,7 +559,7 @@ OPTS is a combination of the following options: =over 5 -=item -AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option is only valid when the C<$input> parameter is a filehandle. If specified, and the value is true, it will result in the file being closed once @@ -567,7 +568,7 @@ destroyed. This parameter defaults to 0. -=item -MultiStream =E 0|1 +=item C<< MultiStream => 0|1 >> @@ -580,8 +581,7 @@ start of another stream. This parameter defaults to 0. - -=item -Prime =E $string +=item C<< Prime => $string >> This option will uncompress the contents of C<$string> before processing the input file/buffer. @@ -592,21 +592,21 @@ data begins without having to read the first few bytes. If this is the case, the uncompression can be I with these bytes using this option. -=item -Transparent =E 0|1 +=item C<< Transparent => 0|1 >> If this option is set and the input file or buffer is not compressed data, the module will allow reading of it anyway. This option defaults to 1. -=item -BlockSize =E $num +=item C<< BlockSize => $num >> When reading the compressed input data, IO::Uncompress::Inflate will read it in blocks of C<$num> bytes. This option defaults to 4096. -=item -InputLength =E $size +=item C<< InputLength => $size >> When present this option will limit the number of compressed bytes read from the input file/buffer to C<$size>. This option can be used in the @@ -622,7 +622,7 @@ compressed data stream. This option defaults to off. -=item -Append =E 0|1 +=item C<< Append => 0|1 >> This option controls what the C method does with uncompressed data. @@ -634,7 +634,7 @@ will be overwritten by the uncompressed data. Defaults to 0. -=item -Strict =E 0|1 +=item C<< Strict => 0|1 >> @@ -900,6 +900,27 @@ underlying file will also be closed. +=head2 nextStream + +Usage is + + my $status = $z->nextStream(); + +Skips to the next compressed data stream in the input file/buffer. If a new +compressed data stream is found, the eof marker will be cleared, C<$.> will +be reset to 0. + +Returns 1 if a new stream was found, 0 if none was found, and -1 if an +error was encountered. + +=head2 trailingData + +Usage is + + my $data = $z->trailingData(); + +Returns any data that + =head1 Importing No symbolic constants are required by this IO::Uncompress::Inflate at present. diff --git a/ext/Compress/IO/Zlib/lib/IO/Uncompress/RawInflate.pm b/ext/Compress/IO/Zlib/lib/IO/Uncompress/RawInflate.pm index 1ed435b..9fedb9c 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_12'; +$VERSION = '2.000_13'; $RawInflateError = ''; @ISA = qw( Exporter IO::Uncompress::Base ); @@ -146,7 +146,8 @@ sub _isRawx return $self->saveErrorString(undef, *$self->{Uncomp}{Error}, STATUS_ERROR) if $status == STATUS_ERROR; - my $buf_len = *$self->{Uncomp}->uncompressedBytes(); + #my $buf_len = *$self->{Uncomp}->uncompressedBytes(); + my $buf_len = length $buffer; if ($status == STATUS_ENDSTREAM) { if (*$self->{MultiStream} @@ -356,7 +357,8 @@ IO::Uncompress::RawInflate - Read RFC 1951 files/buffers $status = $z->inflateSync() - $z->trailingData() + $data = $z->trailingData() + $status = $z->nextStream() $data = $z->getHeaderInfo() $z->tell() $z->seek($position, $whence) @@ -557,7 +559,7 @@ L section below. =over 5 -=item AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option applies to any input or output data streams to C that are filehandles. @@ -569,8 +571,7 @@ completed. This parameter defaults to 0. - -=item BinModeOut =E 0|1 +=item C<< BinModeOut => 0|1 >> When writing to a file or filehandle, set C before writing to the file. @@ -581,15 +582,16 @@ Defaults to 0. -=item -Append =E 0|1 +=item C<< Append => 0|1 >> TODO -=item -MultiStream =E 0|1 +=item C<< MultiStream => 0|1 >> -Creates a new stream after each file. +If the input file/buffer contains multiple compressed data streams, this +option will uncompress the whole lot as a single data stream. -Defaults to 1. +Defaults to 0. @@ -711,7 +713,7 @@ OPTS is a combination of the following options: =over 5 -=item -AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option is only valid when the C<$input> parameter is a filehandle. If specified, and the value is true, it will result in the file being closed once @@ -720,7 +722,7 @@ destroyed. This parameter defaults to 0. -=item -MultiStream =E 0|1 +=item C<< MultiStream => 0|1 >> @@ -728,7 +730,7 @@ This option is a no-op. -=item -Prime =E $string +=item C<< Prime => $string >> This option will uncompress the contents of C<$string> before processing the input file/buffer. @@ -739,21 +741,21 @@ data begins without having to read the first few bytes. If this is the case, the uncompression can be I with these bytes using this option. -=item -Transparent =E 0|1 +=item C<< Transparent => 0|1 >> If this option is set and the input file or buffer is not compressed data, the module will allow reading of it anyway. This option defaults to 1. -=item -BlockSize =E $num +=item C<< BlockSize => $num >> When reading the compressed input data, IO::Uncompress::RawInflate will read it in blocks of C<$num> bytes. This option defaults to 4096. -=item -InputLength =E $size +=item C<< InputLength => $size >> When present this option will limit the number of compressed bytes read from the input file/buffer to C<$size>. This option can be used in the @@ -769,7 +771,7 @@ compressed data stream. This option defaults to off. -=item -Append =E 0|1 +=item C<< Append => 0|1 >> This option controls what the C method does with uncompressed data. @@ -781,7 +783,7 @@ will be overwritten by the uncompressed data. Defaults to 0. -=item -Strict =E 0|1 +=item C<< Strict => 0|1 >> @@ -1021,6 +1023,27 @@ underlying file will also be closed. +=head2 nextStream + +Usage is + + my $status = $z->nextStream(); + +Skips to the next compressed data stream in the input file/buffer. If a new +compressed data stream is found, the eof marker will be cleared, C<$.> will +be reset to 0. + +Returns 1 if a new stream was found, 0 if none was found, and -1 if an +error was encountered. + +=head2 trailingData + +Usage is + + my $data = $z->trailingData(); + +Returns any data that + =head1 Importing No symbolic constants are required by this IO::Uncompress::RawInflate at present. diff --git a/ext/Compress/IO/Zlib/lib/IO/Uncompress/Unzip.pm b/ext/Compress/IO/Zlib/lib/IO/Uncompress/Unzip.pm index 177906a..ae123c9 100644 --- a/ext/Compress/IO/Zlib/lib/IO/Uncompress/Unzip.pm +++ b/ext/Compress/IO/Zlib/lib/IO/Uncompress/Unzip.pm @@ -25,9 +25,9 @@ BEGIN require Exporter ; -our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $UnzipError); +our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $UnzipError, %headerLookup); -$VERSION = '2.000_12'; +$VERSION = '2.000_13'; $UnzipError = ''; @ISA = qw(Exporter IO::Uncompress::RawInflate); @@ -36,6 +36,15 @@ $UnzipError = ''; push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ; Exporter::export_ok_tags('all'); +%headerLookup = ( + ZIP_CENTRAL_HDR_SIG, \&skipCentralDirectory, + ZIP_END_CENTRAL_HDR_SIG, \&skipEndCentralDirectory, + ZIP64_END_CENTRAL_REC_HDR_SIG, \&skipCentralDirectory64Rec, + ZIP64_END_CENTRAL_LOC_HDR_SIG, \&skipCentralDirectory64Loc, + ZIP64_ARCHIVE_EXTRA_SIG, \&skipArchiveExtra, + ZIP64_DIGITAL_SIGNATURE_SIG, \&skipDigitalSignature, + ); + sub new { my $class = shift ; @@ -145,7 +154,7 @@ sub readHeader or return $self->saveErrorString(undef, "Truncated file"); } else { - my $c = $hdr->{CompressedLength}; + my $c = $hdr->{CompressedLength}->get32bit(); $self->smartReadExact(\$buffer, $c) or return $self->saveErrorString(undef, "Truncated file"); $buffer = ''; @@ -169,8 +178,20 @@ sub chkTrailer my $trailer = shift; my ($sig, $CRC32, $cSize, $uSize) ; + my ($cSizeHi, $uSizeHi) = (0, 0); if (*$self->{ZipData}{Streaming}) { - ($sig, $CRC32, $cSize, $uSize) = unpack("V V V V", $trailer) ; + $sig = unpack ("V", substr($trailer, 0, 4)); + $CRC32 = unpack ("V", substr($trailer, 4, 4)); + + if (*$self->{ZipData}{Zip64} ) { + $cSize = U64::newUnpack_V64 substr($trailer, 8, 8); + $uSize = U64::newUnpack_V64 substr($trailer, 16, 8); + } + else { + $cSize = U64::newUnpack_V32 substr($trailer, 8, 4); + $uSize = U64::newUnpack_V32 substr($trailer, 12, 4); + } + return $self->TrailerError("Data Descriptor signature, got $sig") if $sig != ZIP_DATA_HDR_SIG; } @@ -185,15 +206,11 @@ sub chkTrailer return $self->TrailerError("CRC mismatch") if $CRC32 != *$self->{ZipData}{CRC32} ; - my $exp_isize = *$self->{Uncomp}->compressedBytes(); - return $self->TrailerError("CSIZE mismatch. Got $cSize" - . ", expected $exp_isize") - if $cSize != $exp_isize ; + return $self->TrailerError("CSIZE mismatch.") + if ! $cSize->equal(*$self->{CompSize}); - $exp_isize = *$self->{Uncomp}->uncompressedBytes(); - return $self->TrailerError("USIZE mismatch. Got $uSize" - . ", expected $exp_isize") - if $uSize != $exp_isize ; + return $self->TrailerError("USIZE mismatch.") + if ! $uSize->equal(*$self->{UnCompSize}); } my $reachedEnd = STATUS_ERROR ; @@ -219,9 +236,9 @@ sub chkTrailer my $sig = unpack("V", $magic) ; - if ($sig == ZIP_CENTRAL_HDR_SIG) + if ($headerLookup{$sig}) { - if ($self->skipCentralDirectory($magic) != STATUS_OK ) { + if ($headerLookup{$sig}($self, $magic) != STATUS_OK ) { if (*$self->{Strict}) { return STATUS_ERROR ; } @@ -230,21 +247,12 @@ sub chkTrailer return STATUS_OK ; } } - } - elsif ($sig == ZIP_END_CENTRAL_HDR_SIG) - { - if ($self->skipEndCentralDirectory($magic) != STATUS_OK) { - if (*$self->{Strict}) { - return STATUS_ERROR ; - } - else { - $self->clearError(); - return STATUS_OK ; - } + + if ($sig == ZIP_END_CENTRAL_HDR_SIG) + { + return STATUS_OK ; + last; } - # $reachedEnd = STATUS_OK ; - return STATUS_OK ; - last; } elsif ($sig == ZIP_LOCAL_HDR_SIG) { @@ -281,8 +289,8 @@ sub skipCentralDirectory #my $compressedMethod = unpack ("v", substr($buffer, 10-4, 2)); #my $lastModTime = unpack ("V", substr($buffer, 12-4, 4)); #my $crc32 = unpack ("V", substr($buffer, 16-4, 4)); - #my $compressedLength = unpack ("V", substr($buffer, 20-4, 4)); - #my $uncompressedLength = unpack ("V", substr($buffer, 24-4, 4)); + my $compressedLength = unpack ("V", substr($buffer, 20-4, 4)); + my $uncompressedLength = unpack ("V", substr($buffer, 24-4, 4)); my $filename_length = unpack ("v", substr($buffer, 28-4, 2)); my $extra_length = unpack ("v", substr($buffer, 30-4, 2)); my $comment_length = unpack ("v", substr($buffer, 32-4, 2)); @@ -319,6 +327,85 @@ sub skipCentralDirectory return STATUS_OK ; } +sub skipArchiveExtra +{ + my $self = shift; + my $magic = shift ; + + my $buffer; + $self->smartReadExact(\$buffer, 4) + or return $self->TrailerError("Minimum header size is " . + 4 . " bytes") ; + + my $keep = $magic . $buffer ; + + my $size = unpack ("V", $buffer); + + $self->smartReadExact(\$buffer, $size) + or return $self->TrailerError("Minimum header size is " . + $size . " bytes") ; + + $keep .= $buffer ; + *$self->{HeaderPending} = $keep ; + + return STATUS_OK ; +} + + +sub skipCentralDirectory64Rec +{ + my $self = shift; + my $magic = shift ; + + my $buffer; + $self->smartReadExact(\$buffer, 8) + or return $self->TrailerError("Minimum header size is " . + 8 . " bytes") ; + + my $keep = $magic . $buffer ; + + my ($sizeLo, $sizeHi) = unpack ("V V", $buffer); + + # TODO - take SizeHi into account + $self->smartReadExact(\$buffer, $sizeLo) + or return $self->TrailerError("Minimum header size is " . + $sizeLo . " bytes") ; + + $keep .= $buffer ; + *$self->{HeaderPending} = $keep ; + + #my $versionMadeBy = unpack ("v", substr($buffer, 0, 2)); + #my $extractVersion = unpack ("v", substr($buffer, 2, 2)); + #my $diskNumber = unpack ("V", substr($buffer, 4, 4)); + #my $cntrlDirDiskNo = unpack ("V", substr($buffer, 8, 4)); + #my $entriesInThisCD = unpack ("V V", substr($buffer, 12, 8)); + #my $entriesInCD = unpack ("V V", substr($buffer, 20, 8)); + #my $sizeOfCD = unpack ("V V", substr($buffer, 28, 8)); + #my $offsetToCD = unpack ("V V", substr($buffer, 36, 8)); + + return STATUS_OK ; +} + +sub skipCentralDirectory64Loc +{ + my $self = shift; + my $magic = shift ; + + my $buffer; + $self->smartReadExact(\$buffer, 20 - 4) + or return $self->TrailerError("Minimum header size is " . + 20 . " bytes") ; + + my $keep = $magic . $buffer ; + *$self->{HeaderPending} = $keep ; + + #my $startCdDisk = unpack ("V", substr($buffer, 4-4, 4)); + #my $offsetToCD = unpack ("V V", substr($buffer, 8-4, 8)); + #my $diskCount = unpack ("V", substr($buffer, 16-4, 4)); + + return STATUS_OK ; +} + sub skipEndCentralDirectory { my $self = shift; @@ -353,8 +440,6 @@ sub skipEndCentralDirectory } - - sub _isZipMagic { my $buffer = shift ; @@ -404,8 +489,8 @@ sub _readZipHeader($) my $compressedMethod = unpack ("v", substr($buffer, 8-4, 2)); my $lastModTime = unpack ("V", substr($buffer, 10-4, 4)); my $crc32 = unpack ("V", substr($buffer, 14-4, 4)); - my $compressedLength = unpack ("V", substr($buffer, 18-4, 4)); - my $uncompressedLength = unpack ("V", substr($buffer, 22-4, 4)); + my $compressedLength = new U64 unpack ("V", substr($buffer, 18-4, 4)); + my $uncompressedLength = new U64 unpack ("V", substr($buffer, 22-4, 4)); my $filename_length = unpack ("v", substr($buffer, 26-4, 2)); my $extra_length = unpack ("v", substr($buffer, 28-4, 2)); @@ -419,15 +504,6 @@ sub _readZipHeader($) *$self->{ZipData}{Streaming} = $streamingMode; - if (! $streamingMode) { - *$self->{ZipData}{Streaming} = 0; - *$self->{ZipData}{Crc32} = $crc32; - *$self->{ZipData}{CompressedLen} = $compressedLength; - *$self->{ZipData}{UnCompressedLen} = $uncompressedLength; - *$self->{CompressedInputLengthRemaining} = - *$self->{CompressedInputLength} = $compressedLength; - } - if ($filename_length) { @@ -436,6 +512,8 @@ sub _readZipHeader($) $keep .= $filename ; } + my $zip64 = 0 ; + if ($extra_length) { $self->smartReadExact(\$extraField, $extra_length) @@ -447,6 +525,35 @@ sub _readZipHeader($) if defined $bad; $keep .= $extraField ; + + my %Extra ; + for (@EXTRA) + { + $Extra{$_->[0]} = \$_->[1]; + } + + if (defined $Extra{ZIP_EXTRA_ID_ZIP64()}) + { + $zip64 = 1 ; + + my $buff = ${ $Extra{ZIP_EXTRA_ID_ZIP64()} }; + + $uncompressedLength = U64::newUnpack_V64 substr($buff, 0, 8); + $compressedLength = U64::newUnpack_V64 substr($buff, 8, 8); + #my $cheaderOffset = U64::newUnpack_V64 substr($buff, 16, 8); + #my $diskNumber = unpack ("V", substr($buff, 24, 4)); + } + } + + *$self->{ZipData}{Zip64} = $zip64; + + if (! $streamingMode) { + *$self->{ZipData}{Streaming} = 0; + *$self->{ZipData}{Crc32} = $crc32; + *$self->{ZipData}{CompressedLen} = $compressedLength; + *$self->{ZipData}{UnCompressedLen} = $uncompressedLength; + *$self->{CompressedInputLengthRemaining} = + *$self->{CompressedInputLength} = $compressedLength->get32bit(); } *$self->{ZipData}{Method} = $compressedMethod; @@ -490,7 +597,8 @@ sub _readZipHeader($) 'FingerprintLength' => 4, #'HeaderLength' => $compressedMethod == 8 ? length $keep : 0, 'HeaderLength' => length $keep, - 'TrailerLength' => $streamingMode ? 16 : 0, + 'Zip64' => $zip64, + 'TrailerLength' => ! $streamingMode ? 0 : $zip64 ? 24 : 16, 'Header' => $keep, 'CompressedLength' => $compressedLength , 'UncompressedLength' => $uncompressedLength , @@ -598,7 +706,8 @@ IO::Uncompress::Unzip - Read zip files/buffers $status = $z->inflateSync() - $z->trailingData() + $data = $z->trailingData() + $status = $z->nextStream() $data = $z->getHeaderInfo() $z->tell() $z->seek($position, $whence) @@ -799,7 +908,7 @@ L section below. =over 5 -=item AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option applies to any input or output data streams to C that are filehandles. @@ -811,8 +920,7 @@ completed. This parameter defaults to 0. - -=item BinModeOut =E 0|1 +=item C<< BinModeOut => 0|1 >> When writing to a file or filehandle, set C before writing to the file. @@ -823,15 +931,16 @@ Defaults to 0. -=item -Append =E 0|1 +=item C<< Append => 0|1 >> TODO -=item -MultiStream =E 0|1 +=item C<< MultiStream => 0|1 >> -Creates a new stream after each file. +If the input file/buffer contains multiple compressed data streams, this +option will uncompress the whole lot as a single data stream. -Defaults to 1. +Defaults to 0. @@ -953,7 +1062,7 @@ OPTS is a combination of the following options: =over 5 -=item -AutoClose =E 0|1 +=item C<< AutoClose => 0|1 >> This option is only valid when the C<$input> parameter is a filehandle. If specified, and the value is true, it will result in the file being closed once @@ -962,21 +1071,19 @@ destroyed. This parameter defaults to 0. -=item -MultiStream =E 0|1 +=item C<< MultiStream => 0|1 >> -Allows multiple concatenated compressed streams to be treated as a single -compressed stream. Decompression will stop once either the end of the -file/buffer is reached, an error is encountered (premature eof, corrupt -compressed data) or the end of a stream is not immediately followed by the -start of another stream. +Treats the complete zip file/buffer as a single compressed data +stream. When reading in multi-stream mode each member of the zip +file/buffer will be uncompressed in turn until the end of the file/buffer +is encountered. This parameter defaults to 0. - -=item -Prime =E $string +=item C<< Prime => $string >> This option will uncompress the contents of C<$string> before processing the input file/buffer. @@ -987,21 +1094,21 @@ data begins without having to read the first few bytes. If this is the case, the uncompression can be I with these bytes using this option. -=item -Transparent =E 0|1 +=item C<< Transparent => 0|1 >> If this option is set and the input file or buffer is not compressed data, the module will allow reading of it anyway. This option defaults to 1. -=item -BlockSize =E $num +=item C<< BlockSize => $num >> When reading the compressed input data, IO::Uncompress::Unzip will read it in blocks of C<$num> bytes. This option defaults to 4096. -=item -InputLength =E $size +=item C<< InputLength => $size >> When present this option will limit the number of compressed bytes read from the input file/buffer to C<$size>. This option can be used in the @@ -1017,7 +1124,7 @@ compressed data stream. This option defaults to off. -=item -Append =E 0|1 +=item C<< Append => 0|1 >> This option controls what the C method does with uncompressed data. @@ -1029,7 +1136,7 @@ will be overwritten by the uncompressed data. Defaults to 0. -=item -Strict =E 0|1 +=item C<< Strict => 0|1 >> @@ -1281,6 +1388,27 @@ underlying file will also be closed. +=head2 nextStream + +Usage is + + my $status = $z->nextStream(); + +Skips to the next compressed data stream in the input file/buffer. If a new +compressed data stream is found, the eof marker will be cleared, C<$.> will +be reset to 0. + +Returns 1 if a new stream was found, 0 if none was found, and -1 if an +error was encountered. + +=head2 trailingData + +Usage is + + my $data = $z->trailingData(); + +Returns any data that + =head1 Importing No symbolic constants are required by this IO::Uncompress::Unzip at present. diff --git a/ext/Compress/IO/Zlib/t/105oneshot-zip-only.t b/ext/Compress/IO/Zlib/t/105oneshot-zip-only.t index 6ad67b7..807c9e9 100644 --- a/ext/Compress/IO/Zlib/t/105oneshot-zip-only.t +++ b/ext/Compress/IO/Zlib/t/105oneshot-zip-only.t @@ -23,7 +23,7 @@ BEGIN { $extra = 1 if eval { require Test::NoWarnings ; import Test::NoWarnings; 1 }; - plan tests => 119 + $extra ; + plan tests => 146 + $extra ; #use_ok('IO::Compress::Zip', qw(zip $ZipError :zip_method)) ; use_ok('IO::Compress::Zip', qw(:all)) ; @@ -135,82 +135,100 @@ sub zipGetHeader for my $stream (0, 1) { - for my $method (ZIP_CM_STORE, ZIP_CM_DEFLATE) + for my $zip64 (0, 1) { - title "Stream $stream, Method $method"; + next if $zip64 && ! $stream; - my $lex = new LexFile my $file1; + for my $method (ZIP_CM_STORE, ZIP_CM_DEFLATE) + { - my $content = "hello "; - #writeFile($file1, $content); + title "Stream $stream, Zip64 $zip64, Method $method"; - ok zip(\$content => $file1 , Method => $method, Stream => $stream), " zip ok" - or diag $ZipError ; + my $lex = new LexFile my $file1; - my $got ; - if ($stream && $method == ZIP_CM_STORE ) { - #eval ' unzip($file1 => \$got) '; - ok ! unzip($file1 => \$got), " unzip fails"; - like $UnzipError, "/Streamed Stored content not supported/", - " Streamed Stored content not supported"; - next ; - } + my $content = "hello "; + #writeFile($file1, $content); - ok unzip($file1 => \$got), " unzip ok" - or diag $UnzipError ; + my $status = zip(\$content => $file1 , + Method => $method, + Stream => $stream, + Zip64 => $zip64); - is $got, $content, " content ok"; + ok $status, " zip ok" + or diag $ZipError ; - my $u = new IO::Uncompress::Unzip $file1 - or diag $ZipError ; + my $got ; + if ($stream && $method == ZIP_CM_STORE ) { + #eval ' unzip($file1 => \$got) '; + ok ! unzip($file1 => \$got), " unzip fails"; + like $UnzipError, "/Streamed Stored content not supported/", + " Streamed Stored content not supported"; + next ; + } - my $hdr = $u->getHeaderInfo(); - ok $hdr, " got header"; + ok unzip($file1 => \$got), " unzip ok" + or diag $UnzipError ; + + is $got, $content, " content ok"; + + my $u = new IO::Uncompress::Unzip $file1 + or diag $ZipError ; - is $hdr->{Stream}, $stream, " stream is $stream" ; - is $hdr->{MethodID}, $method, " MethodID is $method" ; + my $hdr = $u->getHeaderInfo(); + ok $hdr, " got header"; + + is $hdr->{Stream}, $stream, " stream is $stream" ; + is $hdr->{MethodID}, $method, " MethodID is $method" ; + is $hdr->{Zip64}, $zip64, " Zip64 is $zip64" ; + } } } for my $stream (0, 1) { - for my $method (ZIP_CM_STORE, ZIP_CM_DEFLATE) + for my $zip64 (0, 1) { - title "Stream $stream, Method $method"; - - my $file1; - my $file2; - my $zipfile; - my $lex = new LexFile $file1, $file2, $zipfile; - - my $content1 = "hello "; - writeFile($file1, $content1); - - my $content2 = "goodbye "; - writeFile($file2, $content2); - - my %content = ( $file1 => $content1, - $file2 => $content2, - ); - - ok zip([$file1, $file2] => $zipfile , Method => $method, Stream => $stream), " zip ok" - or diag $ZipError ; - - for my $file ($file1, $file2) + next if $zip64 && ! $stream; + for my $method (ZIP_CM_STORE, ZIP_CM_DEFLATE) { - my $got ; - if ($stream && $method == ZIP_CM_STORE ) { - #eval ' unzip($zipfile => \$got) '; - ok ! unzip($zipfile => \$got, Name => $file), " unzip fails"; - like $UnzipError, "/Streamed Stored content not supported/", - " Streamed Stored content not supported"; - next ; + title "Stream $stream, Zip64 $zip64, Method $method"; + + my $file1; + my $file2; + my $zipfile; + my $lex = new LexFile $file1, $file2, $zipfile; + + my $content1 = "hello "; + writeFile($file1, $content1); + + my $content2 = "goodbye "; + writeFile($file2, $content2); + + my %content = ( $file1 => $content1, + $file2 => $content2, + ); + + ok zip([$file1, $file2] => $zipfile , Method => $method, + Zip64 => $zip64, + Stream => $stream), " zip ok" + or diag $ZipError ; + + for my $file ($file1, $file2) + { + my $got ; + if ($stream && $method == ZIP_CM_STORE ) { + #eval ' unzip($zipfile => \$got) '; + ok ! unzip($zipfile => \$got, Name => $file), " unzip fails"; + like $UnzipError, "/Streamed Stored content not supported/", + " Streamed Stored content not supported"; + next ; + } + + ok unzip($zipfile => \$got, Name => $file), " unzip $file ok" + or diag $UnzipError ; + + is $got, $content{$file}, " content ok"; } - - ok unzip($zipfile => \$got, Name => $file), " unzip $file ok" - or diag $UnzipError ; - - is $got, $content{$file}, " content ok"; } } } diff --git a/ext/Compress/Raw/Zlib/README b/ext/Compress/Raw/Zlib/README index 0fc887b..3515c58 100644 --- a/ext/Compress/Raw/Zlib/README +++ b/ext/Compress/Raw/Zlib/README @@ -1,9 +1,9 @@ Compress::Raw::Zlib - Version 2.000_12 + Version 2.000_13 - 17 May 2006 + 20 June 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 84b3a7c..f2677ab 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_12'; +$VERSION = '2.000_13'; $XS_VERSION = $VERSION; $VERSION = eval $VERSION; @@ -594,7 +594,7 @@ If not successful, the returned deflation object, C<$d>, will be I and C<$status> will hold the a I error code. The function optionally takes a number of named options specified as -C<-Name =E value> pairs. This allows individual options to be +C<< Name => value >> pairs. This allows individual options to be tailored without having to specify them all in the parameter list. For backward compatibility, it is also possible to pass the parameters @@ -610,26 +610,26 @@ Defines the compression level. Valid values are 0 through 9, C, C, C, and C. -The default is C<-Level =E Z_DEFAULT_COMPRESSION>. +The default is Z_DEFAULT_COMPRESSION. =item B<-Method> Defines the compression method. The only valid value at present (and -the default) is C<-Method =E Z_DEFLATED>. +the default) is Z_DEFLATED. =item B<-WindowBits> For a definition of the meaning and valid values for C refer to the I documentation for I. -Defaults to C<-WindowBits =E MAX_WBITS>. +Defaults to MAX_WBITS. =item B<-MemLevel> For a definition of the meaning and valid values for C refer to the I documentation for I. -Defaults to C<-MemLevel =E MAX_MEM_LEVEL>. +Defaults to MAX_MEM_LEVEL. =item B<-Strategy> @@ -637,7 +637,7 @@ Defines the strategy used to tune the compression. The valid values are C, C, C, C and C. -The default is C<-Strategy =EZ_DEFAULT_STRATEGY>. +The default is Z_DEFAULT_STRATEGY. =item B<-Dictionary> @@ -881,11 +881,11 @@ If not successful, C<$i> will be I and C<$status> will hold the I error code. The function optionally takes a number of named options specified as -C<-Name =E value> pairs. This allows individual options to be +C<< -Name => value >> pairs. This allows individual options to be tailored without having to specify them all in the parameter list. For backward compatibility, it is also possible to pass the parameters -as a reference to a hash containing the name=Evalue pairs. +as a reference to a hash containing the C<< name=>value >> pairs. Here is a list of the valid options: @@ -901,7 +901,7 @@ To uncompress an RFC 1951 data stream, set C to C<-MAX_WBITS>. For a full definition of the meaning and valid values for C refer to the I documentation for I. -Defaults to C<-WindowBits =EMAX_WBITS>. +Defaults to MAX_WBITS. =item B<-Bufsize> diff --git a/ext/Compress/Zlib/Changes b/ext/Compress/Zlib/Changes index 557c8dd..9122642 100644 --- a/ext/Compress/Zlib/Changes +++ b/ext/Compress/Zlib/Changes @@ -1,6 +1,10 @@ CHANGES ------- + 2.000_13 20 June 2006 + + * No changes. + 2.000_12 16 April 2006 * Fixed gzread to zap the output buffer to an empty string when zero diff --git a/ext/Compress/Zlib/README b/ext/Compress/Zlib/README index a05884b..f2c6285 100644 --- a/ext/Compress/Zlib/README +++ b/ext/Compress/Zlib/README @@ -1,9 +1,9 @@ Compress::Zlib - Version 2.000_12 + Version 2.000_13 - 17 May 2006 + 20 June 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 8f97b16..8e6f8cd 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_12'; +$VERSION = '2.000_13'; $XS_VERSION = $VERSION; $VERSION = eval $VERSION; @@ -703,7 +703,7 @@ Added C. =back A more complete and flexible interface for reading/writing gzip -files/buffers is included with the module C. See +files/buffers is included with the module C. See L and L for more details. @@ -1044,7 +1044,7 @@ If not successful, the returned deflation stream (C<$d>) will be I and C<$status> will hold the exact I error code. The function optionally takes a number of named options specified as -C<-Name=Evalue> pairs. This allows individual options to be +C<< -Name=>value >> pairs. This allows individual options to be tailored without having to specify them all in the parameter list. For backward compatibility, it is also possible to pass the parameters @@ -1063,12 +1063,12 @@ Defines the compression level. Valid values are 0 through 9, C, C, C, and C. -The default is C<-Level =EZ_DEFAULT_COMPRESSION>. +The default is Z_DEFAULT_COMPRESSION. =item B<-Method> Defines the compression method. The only valid value at present (and -the default) is C<-Method =EZ_DEFLATED>. +the default) is Z_DEFLATED. =item B<-WindowBits> @@ -1079,21 +1079,21 @@ To create an RFC 1951 data stream, set C to C<-MAX_WBITS>. For a full definition of the meaning and valid values for C refer to the I documentation for I. -Defaults to C<-WindowBits =EMAX_WBITS>. +Defaults to MAX_WBITS. =item B<-MemLevel> For a definition of the meaning and valid values for C refer to the I documentation for I. -Defaults to C<-MemLevel =EMAX_MEM_LEVEL>. +Defaults to MAX_MEM_LEVEL. =item B<-Strategy> Defines the strategy used to tune the compression. The valid values are C, C and C. -The default is C<-Strategy =EZ_DEFAULT_STRATEGY>. +The default is Z_DEFAULT_STRATEGY. =item B<-Dictionary> @@ -1254,7 +1254,7 @@ If not successful, C<$i> will be I and C<$status> will hold the I error code. The function optionally takes a number of named options specified as -C<-Name=Evalue> pairs. This allows individual options to be +C<< -Name=>value >> pairs. This allows individual options to be tailored without having to specify them all in the parameter list. For backward compatibility, it is also possible to pass the parameters @@ -1276,7 +1276,7 @@ To uncompress an RFC 1951 data stream, set C to C<-MAX_WBITS>. For a full definition of the meaning and valid values for C refer to the I documentation for I. -Defaults to C<-WindowBits =EMAX_WBITS>. +Defaults to MAX_WBITS. =item B<-Bufsize> @@ -1399,15 +1399,6 @@ CRC-related functions are available. These functions allow checksums to be merged. -=head1 ACCESSING ZIP FILES - -Although it is possible (with some effort on your part) to use this -module to access .zip files, there is a module on CPAN that will do all -the hard work for you. Check out the C module on CPAN at - - http://www.cpan.org/modules/by-module/Archive/Archive-Zip-*.tar.gz - - =head1 CONSTANTS All the I constants are automatically imported when you make use diff --git a/t/lib/compress/multi.pl b/t/lib/compress/multi.pl index 5409606..259447c 100644 --- a/t/lib/compress/multi.pl +++ b/t/lib/compress/multi.pl @@ -13,7 +13,7 @@ BEGIN { $extra = 1 if eval { require Test::NoWarnings ; import Test::NoWarnings; 1 }; - plan tests => 190 + $extra ; + plan tests => 694 + $extra ; use_ok('IO::Uncompress::AnyUncompress', qw($AnyUncompressError)) ; @@ -40,6 +40,7 @@ EOM push @buffers, < 1, + AutoClose => 1, + Append => 1, + MultiStream => 0, + Transparent => 0) + or diag $$UnError; + isa_ok $gz, $UncompressClass, ' $gz' ; + + for my $stream (1 .. $i) + { + my $buff = $buffs[$stream-1]; + my @lines = split("\n", $buff); + my $lines = @lines; + + my $un = ''; + while (<$gz>) { + $un .= $_; + } + is $., $lines, " \$. is $lines"; + + ok ! $gz->error(), " ! error()" + or diag "Error is " . $gz->error() ; + ok $gz->eof(), " eof()"; + is $gz->streamCount(), $stream, " streamCount is $stream" + or diag "Stream count is " . $gz->streamCount(); + ok $un eq $buff, " expected output" ; + #is $gz->tell(), length $buff, " tell is ok"; + is $gz->nextStream(), 1, " nextStream ok"; + is $gz->tell(), 0, " tell is 0"; + is $., 0, ' $. is 0'; + } + + { + my $un = ''; + 1 while $gz->read($un) > 0 ; + #print "[[$un]]\n" while $gz->read($un) > 0 ; + ok ! $gz->error(), " ! error()" + or diag "Error is " . $gz->error() ; + ok $gz->eof(), " eof()"; + is $gz->streamCount(), $i+1, " streamCount is ok" + or diag "Stream count is " . $gz->streamCount(); + ok $un eq "", " expected output" ; + is $gz->tell(), 0, " tell is 0"; + is $., 0, " \$. is 0"; + } + + is $gz->nextStream(), 0, " nextStream ok"; + ok $gz->eof(), " eof()"; + ok $gz->close(), " close() ok" + or diag "errno $!\n" ; + + is $gz->streamCount(), $i +1, " streamCount ok" + or diag "Stream count is " . $gz->streamCount(); + + } } } } @@ -137,7 +202,6 @@ EOM # corrupt one of the streams - all previous should be ok # trailing stuff -# need a way to skip to the start of the next stream. # check that "tell" works ok 1; diff --git a/t/lib/compress/oneshot.pl b/t/lib/compress/oneshot.pl index 8cc9e22..3ef6bb2 100644 --- a/t/lib/compress/oneshot.pl +++ b/t/lib/compress/oneshot.pl @@ -16,7 +16,7 @@ BEGIN { $extra = 1 if eval { require Test::NoWarnings ; import Test::NoWarnings; 1 }; - plan tests => 944 + $extra ; + plan tests => 956 + $extra ; use_ok('IO::Uncompress::AnyUncompress', qw(anyuncompress $AnyUncompressError)) ; @@ -74,6 +74,22 @@ sub run ' Input and Output filename are the same'; } + { + my $dir = "tmpdir"; + my $lex = new LexDir $dir ; + mkdir $dir, 0777 ; + + $a = $Func->($dir, \$x) ; + is $a, undef, " $TopType returned undef"; + like $$Error, "/input file '$dir' is a directory/", + ' Input filename is a directory'; + + $a = $Func->(\$x, $dir) ; + is $a, undef, " $TopType returned undef"; + like $$Error, "/output file '$dir' is a directory/", + ' Output filename is a directory'; + } + eval { $a = $Func->(\$in, \$in) ;} ; like $@, mkErr("^$TopType: input and output buffer are identical"), ' Input and Output buffer are the same';