summaryrefslogtreecommitdiff
path: root/ext/Compress/Zlib/lib
diff options
context:
space:
mode:
authorPaul Marquess <paul.marquess@btinternet.com>2006-01-09 20:25:00 +0000
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>2006-01-10 10:05:26 +0000
commit1a6a845317ff5e6bc844195898061e5a9910928d (patch)
tree1ce6bb51b3450987f1e08250b928e28495686e0f /ext/Compress/Zlib/lib
parent2d2af554da24863760d055834f4984fbca7ec85b (diff)
downloadperl-1a6a845317ff5e6bc844195898061e5a9910928d.tar.gz
Compress::Zlib becomes zlib agnostic
From: "Paul Marquess" <Paul.Marquess@ntlworld.com> Message-ID: <002101c6155a$c5886c90$1340100a@myopwv.com> p4raw-id: //depot/perl@26761
Diffstat (limited to 'ext/Compress/Zlib/lib')
-rw-r--r--ext/Compress/Zlib/lib/Compress/Gzip/Constants.pm2
-rw-r--r--ext/Compress/Zlib/lib/Compress/Zip/Constants.pm135
-rw-r--r--ext/Compress/Zlib/lib/Compress/Zlib/Common.pm215
-rw-r--r--ext/Compress/Zlib/lib/Compress/Zlib/FileConstants.pm2
-rw-r--r--ext/Compress/Zlib/lib/Compress/Zlib/ParseParameters.pm55
-rw-r--r--ext/Compress/Zlib/lib/CompressPlugin/Deflate.pm164
-rw-r--r--ext/Compress/Zlib/lib/CompressPlugin/Identity.pm121
-rw-r--r--ext/Compress/Zlib/lib/File/GlobMapper.pm16
-rw-r--r--ext/Compress/Zlib/lib/IO/Compress/Base.pm917
-rw-r--r--ext/Compress/Zlib/lib/IO/Compress/Deflate.pm319
-rw-r--r--ext/Compress/Zlib/lib/IO/Compress/Gzip.pm1586
-rw-r--r--ext/Compress/Zlib/lib/IO/Compress/RawDeflate.pm403
-rw-r--r--ext/Compress/Zlib/lib/IO/Compress/Zip.pm290
-rw-r--r--ext/Compress/Zlib/lib/IO/Uncompress/AnyInflate.pm319
-rw-r--r--ext/Compress/Zlib/lib/IO/Uncompress/AnyUncompress.pm156
-rw-r--r--ext/Compress/Zlib/lib/IO/Uncompress/Base.pm1250
-rw-r--r--ext/Compress/Zlib/lib/IO/Uncompress/Gunzip.pm1879
-rw-r--r--ext/Compress/Zlib/lib/IO/Uncompress/Inflate.pm368
-rw-r--r--ext/Compress/Zlib/lib/IO/Uncompress/RawInflate.pm519
-rw-r--r--ext/Compress/Zlib/lib/IO/Uncompress/Unzip.pm459
-rw-r--r--ext/Compress/Zlib/lib/UncompressPlugin/Identity.pm93
-rw-r--r--ext/Compress/Zlib/lib/UncompressPlugin/Inflate.pm160
22 files changed, 5604 insertions, 3824 deletions
diff --git a/ext/Compress/Zlib/lib/Compress/Gzip/Constants.pm b/ext/Compress/Zlib/lib/Compress/Gzip/Constants.pm
index 358dfaa8ff..531b3477f4 100644
--- a/ext/Compress/Zlib/lib/Compress/Gzip/Constants.pm
+++ b/ext/Compress/Zlib/lib/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_05';
+$VERSION = '2.000_07';
@ISA = qw(Exporter);
diff --git a/ext/Compress/Zlib/lib/Compress/Zip/Constants.pm b/ext/Compress/Zlib/lib/Compress/Zip/Constants.pm
new file mode 100644
index 0000000000..ef82024140
--- /dev/null
+++ b/ext/Compress/Zlib/lib/Compress/Zip/Constants.pm
@@ -0,0 +1,135 @@
+package Compress::Zip::Constants;
+
+use strict ;
+use warnings;
+
+require Exporter;
+
+our ($VERSION, @ISA, @EXPORT, %GZIP_OS_Names);
+
+$VERSION = '1.00';
+
+@ISA = qw(Exporter);
+
+@EXPORT= qw(
+
+ ZIP_ID_SIZE
+ GZIP_ID1
+ GZIP_ID2
+
+ GZIP_FLG_DEFAULT
+ GZIP_FLG_FTEXT
+ GZIP_FLG_FHCRC
+ GZIP_FLG_FEXTRA
+ GZIP_FLG_FNAME
+ GZIP_FLG_FCOMMENT
+ GZIP_FLG_RESERVED
+
+ GZIP_CM_DEFLATED
+
+ GZIP_MIN_HEADER_SIZE
+ GZIP_TRAILER_SIZE
+
+ GZIP_MTIME_DEFAULT
+ GZIP_FEXTRA_DEFAULT
+ GZIP_FEXTRA_HEADER_SIZE
+ GZIP_FEXTRA_MAX_SIZE
+ GZIP_FEXTRA_SUBFIELD_HEADER_SIZE
+ GZIP_FEXTRA_SUBFIELD_ID_SIZE
+ GZIP_FEXTRA_SUBFIELD_LEN_SIZE
+ GZIP_FEXTRA_SUBFIELD_MAX_SIZE
+
+ GZIP_FNAME_INVALID_CHAR_RE
+ GZIP_FCOMMENT_INVALID_CHAR_RE
+
+ GZIP_FHCRC_SIZE
+
+ GZIP_ISIZE_MAX
+ GZIP_ISIZE_MOD_VALUE
+
+
+ GZIP_NULL_BYTE
+
+ GZIP_OS_DEFAULT
+
+ %GZIP_OS_Names
+
+ GZIP_MINIMUM_HEADER
+
+ );
+
+
+# Constants for the Zip Local Header
+
+use constant ZIP_ID_SIZE => 4 ;
+use constant ZIP_LOCAL_ID => 0x02014B50;
+use constant ZIP_LOCAL_ID1 => 0x04;
+use constant ZIP_LOCAL_ID2 => 0x03;
+use constant ZIP_LOCAL_ID3 => 0x4B;
+use constant ZIP_LOCAL_ID4 => 0x50;
+
+use constant ZIP_MIN_HEADER_SIZE => 30 ;
+use constant ZIP_TRAILER_SIZE => 0 ;
+
+
+use constant GZIP_FLG_DEFAULT => 0x00 ;
+use constant GZIP_FLG_FTEXT => 0x01 ;
+use constant GZIP_FLG_FHCRC => 0x02 ; # called CONTINUATION in gzip
+use constant GZIP_FLG_FEXTRA => 0x04 ;
+use constant GZIP_FLG_FNAME => 0x08 ;
+use constant GZIP_FLG_FCOMMENT => 0x10 ;
+#use constant GZIP_FLG_ENCRYPTED => 0x20 ; # documented in gzip sources
+use constant GZIP_FLG_RESERVED => (0x20 | 0x40 | 0x80) ;
+
+use constant GZIP_MTIME_DEFAULT => 0x00 ;
+use constant GZIP_FEXTRA_DEFAULT => 0x00 ;
+use constant GZIP_FEXTRA_HEADER_SIZE => 2 ;
+use constant GZIP_FEXTRA_MAX_SIZE => 0xFFFF ;
+use constant GZIP_FEXTRA_SUBFIELD_HEADER_SIZE => 4 ;
+use constant GZIP_FEXTRA_SUBFIELD_ID_SIZE => 2 ;
+use constant GZIP_FEXTRA_SUBFIELD_LEN_SIZE => 2 ;
+use constant GZIP_FEXTRA_SUBFIELD_MAX_SIZE => 0xFFFF ;
+
+use constant GZIP_FNAME_INVALID_CHAR_RE => qr/[\x00-\x1F\x7F-\x9F]/;
+use constant GZIP_FCOMMENT_INVALID_CHAR_RE => qr/[\x00-\x09\x11-\x1F\x7F-\x9F]/;
+
+use constant GZIP_FHCRC_SIZE => 2 ; # aka CONTINUATION in gzip
+
+use constant GZIP_CM_DEFLATED => 8 ;
+
+use constant GZIP_NULL_BYTE => "\x00";
+use constant GZIP_ISIZE_MAX => 0xFFFFFFFF ;
+use constant GZIP_ISIZE_MOD_VALUE => GZIP_ISIZE_MAX + 1 ;
+
+# OS Names sourced from http://www.gzip.org/format.txt
+
+use constant GZIP_OS_DEFAULT=> 0xFF ;
+%ZIP_OS_Names = (
+ 0 => 'MS-DOS',
+ 1 => 'Amiga',
+ 2 => 'VMS',
+ 3 => 'Unix',
+ 4 => 'VM/CMS',
+ 5 => 'Atari TOS',
+ 6 => 'HPFS (OS/2, NT)',
+ 7 => 'Macintosh',
+ 8 => 'Z-System',
+ 9 => 'CP/M',
+ 10 => 'TOPS-20',
+ 11 => 'NTFS (NT)',
+ 12 => 'SMS QDOS',
+ 13 => 'Acorn RISCOS',
+ 14 => 'VFAT file system (Win95, NT)',
+ 15 => 'MVS',
+ 16 => 'BeOS',
+ 17 => 'Tandem/NSK',
+ 18 => 'THEOS',
+ GZIP_OS_DEFAULT => 'Unknown',
+ ) ;
+
+use constant GZIP_MINIMUM_HEADER => pack("C4 V C C",
+ GZIP_ID1, GZIP_ID2, GZIP_CM_DEFLATED, GZIP_FLG_DEFAULT,
+ GZIP_MTIME_DEFAULT, GZIP_FEXTRA_DEFAULT, GZIP_OS_DEFAULT) ;
+
+
+1;
diff --git a/ext/Compress/Zlib/lib/Compress/Zlib/Common.pm b/ext/Compress/Zlib/lib/Compress/Zlib/Common.pm
index 36d6f648e7..a01ab9be84 100644
--- a/ext/Compress/Zlib/lib/Compress/Zlib/Common.pm
+++ b/ext/Compress/Zlib/lib/Compress/Zlib/Common.pm
@@ -9,20 +9,36 @@ use Scalar::Util qw(blessed readonly);
use File::GlobMapper;
require Exporter;
-our ($VERSION, @ISA, @EXPORT);
+our ($VERSION, @ISA, @EXPORT, %EXPORT_TAGS);
@ISA = qw(Exporter);
-$VERSION = '2.000_05';
+$VERSION = '2.000_07';
-@EXPORT = qw( isaFilehandle isaFilename whatIsInput whatIsOutput ckInputParam
+@EXPORT = qw( isaFilehandle isaFilename whatIsInput whatIsOutput
isaFileGlobString cleanFileGlobString oneTarget
setBinModeInput setBinModeOutput
- ckOutputParam ckInOutParams
+ ckInOutParams
+ createSelfTiedObject
+
WANT_CODE
WANT_EXT
WANT_UNDEF
WANT_HASH
+
+ STATUS_OK
+ STATUS_ENDSTREAM
+ STATUS_ERROR
);
+%EXPORT_TAGS = ( Status => [qw( STATUS_OK
+ STATUS_ENDSTREAM
+ STATUS_ERROR
+ )]);
+
+
+use constant STATUS_OK => 0;
+use constant STATUS_ENDSTREAM => 1;
+use constant STATUS_ERROR => 2;
+
our ($needBinmode);
$needBinmode = ($^O eq 'MSWin32' ||
($] >= 5.006 && eval ' ${^UNICODE} || ${^UTF8LOCALE} '))
@@ -76,7 +92,8 @@ sub cleanFileGlobString
use constant WANT_CODE => 1 ;
use constant WANT_EXT => 2 ;
use constant WANT_UNDEF => 4 ;
-use constant WANT_HASH => 8 ;
+#use constant WANT_HASH => 8 ;
+use constant WANT_HASH => 0 ;
sub whatIsInput($;$)
{
@@ -137,59 +154,15 @@ sub oneTarget
return $_[0] =~ /^(code|handle|buffer|filename)$/;
}
-sub ckInputParam ($$$;$)
-{
- my $from = shift ;
- my $inType = whatIsInput($_[0], $_[2]);
- local $Carp::CarpLevel = 1;
-
- croak "$from: input parameter not a filename, filehandle, array ref or scalar ref"
- if ! $inType ;
-
- if ($inType eq 'filename' )
- {
- croak "$from: input filename is undef or null string"
- if ! defined $_[0] || $_[0] eq '' ;
-
- if ($_[0] ne '-' && ! -e $_[0] )
- {
- ${$_[1]} = "input file '$_[0]' does not exist";
- return undef;
- }
- }
-
- return 1;
-}
-
-sub ckOutputParam ($$$)
-{
- my $from = shift ;
- my $outType = whatIsOutput($_[0]);
- local $Carp::CarpLevel = 1;
-
- croak "$from: output parameter not a filename, filehandle or scalar ref"
- if ! $outType ;
-
- croak "$from: output filename is undef or null string"
- if $outType eq 'filename' && (! defined $_[0] || $_[0] eq '') ;
-
- croak("$from: output buffer is read-only")
- if $outType eq 'buffer' && readonly(${ $_[0] });
-
- return 1;
-}
-
sub Validator::new
{
my $class = shift ;
my $Class = shift ;
- my $type = shift ;
my $error_ref = shift ;
my $reportClass = shift ;
my %data = (Class => $Class,
- Type => $type,
Error => $error_ref,
reportClass => $reportClass,
) ;
@@ -206,35 +179,33 @@ sub Validator::new
if (! $inType)
{
- croak "$reportClass: illegal input parameter" ;
+ $obj->croakError("$reportClass: illegal input parameter") ;
#return undef ;
}
- if ($inType eq 'hash')
- {
- $obj->{Hash} = 1 ;
- $obj->{oneInput} = 1 ;
- return $obj->validateHash($_[0]);
- }
+# if ($inType eq 'hash')
+# {
+# $obj->{Hash} = 1 ;
+# $obj->{oneInput} = 1 ;
+# return $obj->validateHash($_[0]);
+# }
if (! $outType)
{
- croak "$reportClass: illegal output parameter" ;
+ $obj->croakError("$reportClass: illegal output parameter") ;
#return undef ;
}
if ($inType ne 'fileglob' && $outType eq 'fileglob')
{
- ${ $data{Error} } = "Need input fileglob for outout fileglob";
- return undef ;
+ $obj->croakError("Need input fileglob for outout fileglob");
}
- if ($inType ne 'fileglob' && $outType eq 'hash' && $inType ne 'filename' )
- {
- ${ $data{Error} } = "input must ne filename or fileglob when output is a hash";
- return undef ;
- }
+# if ($inType ne 'fileglob' && $outType eq 'hash' && $inType ne 'filename' )
+# {
+# $obj->croakError("input must ne filename or fileglob when output is a hash");
+# }
if ($inType eq 'fileglob' && $outType eq 'fileglob')
{
@@ -243,15 +214,14 @@ sub Validator::new
my $mapper = new File::GlobMapper($_[0], $_[1]);
if ( ! $mapper )
{
- ${ $data{Error} } = $File::GlobMapper::Error ;
- return undef ;
+ return $obj->saveErrorString($File::GlobMapper::Error) ;
}
$data{Pairs} = $mapper->getFileMap();
return $obj;
}
- croak("$reportClass: input and output $inType are identical")
+ $obj->croakError("$reportClass: input and output $inType are identical")
if $inType eq $outType && $_[0] eq $_[1] && $_[0] ne '-' ;
if ($inType eq 'fileglob') # && $outType ne 'fileglob'
@@ -261,8 +231,8 @@ sub Validator::new
if (@inputs == 0)
{
- # legal or die?
- die "legal or die???" ;
+ # TODO -- legal or die?
+ die "globmap matched zero file -- legal or die???" ;
}
elsif (@inputs == 1)
{
@@ -287,22 +257,39 @@ sub Validator::new
}
elsif ($inType eq 'array')
{
+ $data{inType} = 'filenames' ;
$obj->validateInputArray($_[0])
or return undef ;
}
- croak("$reportClass: output buffer is read-only")
- if $outType eq 'buffer' && Compress::Zlib::_readonly_ref($_[1]);
+ return $obj->saveErrorString("$reportClass: output buffer is read-only")
+ if $outType eq 'buffer' && readonly(${ $_[1] });
if ($outType eq 'filename' )
{
- croak "$reportClass: output filename is undef or null string"
+ $obj->croakError("$reportClass: output filename is undef or null string")
if ! defined $_[1] || $_[1] eq '' ;
}
return $obj ;
}
+sub Validator::saveErrorString
+{
+ my $self = shift ;
+ ${ $self->{Error} } = shift ;
+ return undef;
+
+}
+
+sub Validator::croakError
+{
+ my $self = shift ;
+ $self->saveErrorString($_[0]);
+ croak $_[0];
+}
+
+
sub Validator::validateInputFilenames
{
@@ -310,21 +297,19 @@ sub Validator::validateInputFilenames
foreach my $filename (@_)
{
- croak "$self->{reportClass}: input filename is undef or null string"
+ $self->croakError("$self->{reportClass}: input filename is undef or null string")
if ! defined $filename || $filename eq '' ;
next if $filename eq '-';
if (! -e $filename )
{
- ${ $self->{Error} } = "input file '$filename' does not exist";
- return undef;
+ return $self->saveErrorString("input file '$filename' does not exist");
}
if (! -r $filename )
{
- ${ $self->{Error} } = "cannot open file '$filename': $!";
- return undef;
+ return $self->saveErrorString("cannot open file '$filename': $!");
}
}
@@ -335,45 +320,73 @@ sub Validator::validateInputArray
{
my $self = shift ;
+ if ( @{ $_[0] } == 0 )
+ {
+ return $self->saveErrorString("empty array reference") ;
+ }
+
foreach my $element ( @{ $_[0] } )
{
my $inType = whatIsInput($element);
if (! $inType)
{
- ${ $self->{Error} } = "unknown input parameter" ;
- return undef ;
+ $self->croakError("unknown input parameter") ;
}
+ elsif($inType eq 'filename')
+ {
+ $self->validateInputFilenames($element)
+ or return undef ;
+ }
+ else
+ {
+ $self->croakError("not a filename") ;
+ }
}
return 1 ;
}
-sub Validator::validateHash
+#sub Validator::validateHash
+#{
+# my $self = shift ;
+# my $href = shift ;
+#
+# while (my($k, $v) = each %$href)
+# {
+# my $ktype = whatIsInput($k);
+# my $vtype = whatIsOutput($v, WANT_EXT|WANT_UNDEF) ;
+#
+# if ($ktype ne 'filename')
+# {
+# return $self->saveErrorString("hash key not filename") ;
+# }
+#
+# my %valid = map { $_ => 1 } qw(filename buffer array undef handle) ;
+# if (! $valid{$vtype})
+# {
+# return $self->saveErrorString("hash value not ok") ;
+# }
+# }
+#
+# return $self ;
+#}
+
+sub createSelfTiedObject
{
- my $self = shift ;
- my $href = shift ;
-
- while (my($k, $v) = each %$href)
- {
- my $ktype = whatIsInput($k);
- my $vtype = whatIsOutput($v, WANT_EXT|WANT_UNDEF) ;
-
- if ($ktype ne 'filename')
- {
- ${ $self->{Error} } = "hash key not filename" ;
- return undef ;
- }
+ my $class = shift || (caller)[0] ;
+ my $error_ref = shift ;
- my %valid = map { $_ => 1 } qw(filename buffer array undef handle) ;
- if (! $valid{$vtype})
- {
- ${ $self->{Error} } = "hash value not ok" ;
- return undef ;
- }
- }
+ my $obj = bless Symbol::gensym(), ref($class) || $class;
+ tie *$obj, $obj if $] >= 5.005;
+ *$obj->{Closed} = 1 ;
+ $$error_ref = '';
+ *$obj->{Error} = $error_ref ;
+ my $errno = 0 ;
+ *$obj->{ErrorNo} = \$errno ;
- return $self ;
+ return $obj;
}
+
1;
diff --git a/ext/Compress/Zlib/lib/Compress/Zlib/FileConstants.pm b/ext/Compress/Zlib/lib/Compress/Zlib/FileConstants.pm
index 69befce53d..540f892982 100644
--- a/ext/Compress/Zlib/lib/Compress/Zlib/FileConstants.pm
+++ b/ext/Compress/Zlib/lib/Compress/Zlib/FileConstants.pm
@@ -9,7 +9,7 @@ require Exporter;
our ($VERSION, @ISA, @EXPORT);
-$VERSION = '2.000_05';
+$VERSION = '2.000_07';
@ISA = qw(Exporter);
diff --git a/ext/Compress/Zlib/lib/Compress/Zlib/ParseParameters.pm b/ext/Compress/Zlib/lib/Compress/Zlib/ParseParameters.pm
index d89ec6764e..71fb45b412 100644
--- a/ext/Compress/Zlib/lib/Compress/Zlib/ParseParameters.pm
+++ b/ext/Compress/Zlib/lib/Compress/Zlib/ParseParameters.pm
@@ -7,7 +7,7 @@ use Carp;
require Exporter;
our ($VERSION, @ISA, @EXPORT);
-$VERSION = '2.000_05';
+$VERSION = '2.000_07';
@ISA = qw(Exporter);
use constant Parse_any => 0x01;
@@ -23,6 +23,8 @@ use constant OFF_PARSED => 0 ;
use constant OFF_TYPE => 1 ;
use constant OFF_DEFAULT => 2 ;
use constant OFF_FIXED => 3 ;
+use constant OFF_FIRST_ONLY => 4 ;
+use constant OFF_STICKY => 5 ;
push @EXPORT, qw( ParseParameters
Parse_any Parse_unsigned Parse_signed
@@ -46,6 +48,7 @@ sub ParseParameters
sub new
{
my $class = shift ;
+
my $obj = { Error => '',
Got => {},
} ;
@@ -76,6 +79,9 @@ sub parse
my $default = shift ;
+ my $got = $self->{Got} ;
+ my $firstTime = keys %{ $got } == 0 ;
+
my (@Bad) ;
my @entered = () ;
@@ -106,14 +112,23 @@ sub parse
}
- my %got = () ;
while (my ($key, $v) = each %$default)
{
- my ($type, $value) = @$v ;
+ croak "need 4 params [@$v]"
+ if @$v != 4 ;
+
+ my ($first_only, $sticky, $type, $value) = @$v ;
my $x ;
$self->_checkType($key, \$value, $type, 0, \$x)
or return undef ;
- $got{lc $key} = [0, $type, $value, $x] ;
+
+ $key = lc $key;
+
+ if ($firstTime || ! $sticky) {
+ $got->{$key} = [0, $type, $value, $x, $first_only, $sticky] ;
+ }
+
+ $got->{$key}[OFF_PARSED] = 0 ;
}
for my $i (0.. @entered / 2 - 1) {
@@ -124,16 +139,18 @@ sub parse
#print defined $$value ? "[$$value]\n" : "[undef]\n";
$key =~ s/^-// ;
+ my $canonkey = lc $key;
- if ($got{lc $key})
+ if ($got->{$canonkey} && ($firstTime ||
+ ! $got->{$canonkey}[OFF_FIRST_ONLY] ))
{
- my $type = $got{lc $key}[OFF_TYPE] ;
+ my $type = $got->{$canonkey}[OFF_TYPE] ;
my $s ;
$self->_checkType($key, $value, $type, 1, \$s)
or return undef ;
#$value = $$value unless $type & Parse_store_ref ;
$value = $$value ;
- $got{lc $key} = [1, $type, $value, $s] ;
+ $got->{$canonkey} = [1, $type, $value, $s] ;
}
else
{ push (@Bad, $key) }
@@ -144,8 +161,6 @@ sub parse
return $self->setError("unknown key value(s) @Bad") ;
}
- $self->{Got} = { %got } ;
-
return 1;
}
@@ -179,7 +194,7 @@ sub _checkType
}
elsif ($type & Parse_unsigned)
{
- return $self->setError("Parameter '$key' must be an unsigned int, got undef")
+ return $self->setError("Parameter '$key' must be an unsigned int, got 'undef'")
if $validate && ! defined $value ;
return $self->setError("Parameter '$key' must be an unsigned int, got '$value'")
if $validate && $value !~ /^\d+$/;
@@ -189,7 +204,7 @@ sub _checkType
}
elsif ($type & Parse_signed)
{
- return $self->setError("Parameter '$key' must be a signed int, got undef")
+ return $self->setError("Parameter '$key' must be a signed int, got 'undef'")
if $validate && ! defined $value ;
return $self->setError("Parameter '$key' must be a signed int, got '$value'")
if $validate && $value !~ /^-?\d+$/;
@@ -199,6 +214,8 @@ sub _checkType
}
elsif ($type & Parse_boolean)
{
+ return $self->setError("Parameter '$key' must be an int, got '$value'")
+ if $validate && defined $value && $value !~ /^\d*$/;
$$output = defined $value ? $value != 0 : 0 ;
return 1;
}
@@ -258,5 +275,21 @@ sub wantValue
}
+sub clone
+{
+ my $self = shift ;
+ my $obj = { };
+ my %got ;
+
+ while (my ($k, $v) = each %{ $self->{Got} }) {
+ $got{$k} = [ @$v ];
+ }
+
+ $obj->{Error} = $self->{Error};
+ $obj->{Got} = \%got ;
+
+ return bless $obj ;
+}
+
1;
diff --git a/ext/Compress/Zlib/lib/CompressPlugin/Deflate.pm b/ext/Compress/Zlib/lib/CompressPlugin/Deflate.pm
new file mode 100644
index 0000000000..28ca794933
--- /dev/null
+++ b/ext/Compress/Zlib/lib/CompressPlugin/Deflate.pm
@@ -0,0 +1,164 @@
+package CompressPlugin::Deflate ;
+
+use strict;
+use warnings;
+
+use Compress::Zlib::Common qw(:Status);
+
+use Compress::Zlib qw(Z_OK Z_FINISH MAX_WBITS) ;
+our ($VERSION);
+
+$VERSION = '2.000_05';
+
+sub mkCompObject
+{
+ my $crc32 = shift ;
+ my $adler32 = shift ;
+ my $level = shift ;
+ my $strategy = shift ;
+
+ my ($def, $status) = new Compress::Zlib::Deflate
+ -AppendOutput => 1,
+ -CRC32 => $crc32,
+ -ADLER32 => $adler32,
+ -Level => $level,
+ -Strategy => $strategy,
+ -WindowBits => - MAX_WBITS;
+
+ return (undef, "Cannot create Deflate object: $status", $status)
+ if $status != Z_OK;
+
+ return bless {'Def' => $def,
+ 'CompSize' => 0,
+ 'UnCompSize' => 0,
+ 'Error' => '',
+ } ;
+}
+
+sub compr
+{
+ my $self = shift ;
+
+ my $def = $self->{Def};
+
+ my $status = $def->deflate($_[0], $_[1]) ;
+ $self->{ErrorNo} = $status;
+
+ if ($status != Z_OK)
+ {
+ $self->{Error} = "Deflate Error: $status";
+ return STATUS_ERROR;
+ }
+
+ return STATUS_OK;
+}
+
+sub flush
+{
+ my $self = shift ;
+
+ my $def = $self->{Def};
+
+ my $opt = $_[1] || Z_FINISH;
+ my $status = $def->flush($_[0], $opt);
+ $self->{ErrorNo} = $status;
+
+ if ($status != Z_OK)
+ {
+ $self->{Error} = "Deflate Error: $status";
+ return STATUS_ERROR;
+ }
+
+ return STATUS_OK;
+
+}
+
+sub close
+{
+ my $self = shift ;
+
+ my $def = $self->{Def};
+
+ $def->flush($_[0], Z_FINISH);
+}
+
+sub reset
+{
+ my $self = shift ;
+
+ my $def = $self->{Def};
+
+ my $status = $def->deflateReset() ;
+ $self->{ErrorNo} = $status;
+ if ($status != Z_OK)
+ {
+ $self->{Error} = "Deflate Error: $status";
+ return STATUS_ERROR;
+ }
+
+ return STATUS_OK;
+}
+
+sub deflateParams
+{
+ my $self = shift ;
+
+ my $def = $self->{Def};
+
+ my $status = $def->deflateParams(@_);
+ $self->{ErrorNo} = $status;
+ if ($status != Z_OK)
+ {
+ $self->{Error} = "deflateParams Error: $status";
+ return STATUS_ERROR;
+ }
+
+ return STATUS_OK;
+}
+
+
+
+sub total_out
+{
+ my $self = shift ;
+ $self->{Def}->total_out();
+}
+
+sub total_in
+{
+ my $self = shift ;
+ $self->{Def}->total_in();
+}
+
+sub compressedBytes
+{
+ my $self = shift ;
+ $self->{Def}->compressedBytes();
+}
+
+sub uncompressedBytes
+{
+ my $self = shift ;
+ $self->{Def}->uncompressedBytes();
+}
+
+
+
+
+sub crc32
+{
+ my $self = shift ;
+ $self->{Def}->crc32();
+}
+
+sub adler32
+{
+ my $self = shift ;
+ $self->{Def}->adler32();
+}
+
+
+1;
+
+__END__
+
diff --git a/ext/Compress/Zlib/lib/CompressPlugin/Identity.pm b/ext/Compress/Zlib/lib/CompressPlugin/Identity.pm
new file mode 100644
index 0000000000..db90e97622
--- /dev/null
+++ b/ext/Compress/Zlib/lib/CompressPlugin/Identity.pm
@@ -0,0 +1,121 @@
+package CompressPlugin::Identity ;
+
+use strict;
+use warnings;
+
+use Compress::Zlib::Common qw(:Status);
+use Compress::Zlib () ;
+our ($VERSION);
+
+$VERSION = '2.000_05';
+
+sub mkCompObject
+{
+ my $crc32 = shift ;
+ my $adler32 = shift ;
+ my $level = shift ;
+ my $strategy = shift ;
+
+ return bless {
+ 'CompSize' => 0,
+ 'UnCompSize' => 0,
+ 'Error' => '',
+ 'ErrorNo' => 0,
+ 'wantCRC32' => $crc32,
+ 'CRC32' => Compress::Zlib::crc32(''),
+ 'wantADLER32'=> $adler32,
+ 'ADLER32' => Compress::Zlib::adler32(''),
+ } ;
+}
+
+sub compr
+{
+ my $self = shift ;
+
+ if (defined ${ $_[0] } && length ${ $_[0] }) {
+ $self->{CompSize} += length ${ $_[0] } ;
+ $self->{UnCompSize} = $self->{CompSize} ;
+
+ $self->{CRC32} = Compress::Zlib::crc32($_[0], $self->{CRC32})
+ if $self->{wantCRC32};
+
+ $self->{ADLER32} = Compress::Zlib::adler32($_[0], $self->{ADLER32})
+ if $self->{wantADLER32};
+
+ ${ $_[1] } .= ${ $_[0] };
+ }
+
+ return STATUS_OK ;
+}
+
+sub flush
+{
+ my $self = shift ;
+
+ return STATUS_OK;
+}
+
+sub close
+{
+ my $self = shift ;
+
+ return STATUS_OK;
+}
+
+sub reset
+{
+ my $self = shift ;
+
+ return STATUS_OK;
+}
+
+sub deflateParams
+{
+ my $self = shift ;
+
+ return STATUS_OK;
+}
+
+sub total_out
+{
+ my $self = shift ;
+ return $self->{UnCompSize} ;
+}
+
+sub total_in
+{
+ my $self = shift ;
+ return $self->{UnCompSize} ;
+}
+
+sub compressedBytes
+{
+ my $self = shift ;
+ return $self->{UnCompSize} ;
+}
+
+sub uncompressedBytes
+{
+ my $self = shift ;
+ return $self->{UnCompSize} ;
+}
+
+sub crc32
+{
+ my $self = shift ;
+ return $self->{CRC32};
+}
+
+sub adler32
+{
+ my $self = shift ;
+ return $self->{ADLER32};
+}
+
+
+
+1;
+
+
+__END__
+
diff --git a/ext/Compress/Zlib/lib/File/GlobMapper.pm b/ext/Compress/Zlib/lib/File/GlobMapper.pm
index b8542264cb..9e7c217cbd 100644
--- a/ext/Compress/Zlib/lib/File/GlobMapper.pm
+++ b/ext/Compress/Zlib/lib/File/GlobMapper.pm
@@ -12,14 +12,14 @@ BEGIN
{
require File::BSDGlob; import File::BSDGlob qw(:glob) ;
$CSH_GLOB = File::BSDGlob::GLOB_CSH() ;
- *globber = \&File::BSDGlob::glob;
+ *globber = \&File::BSDGlob::csh_glob;
}
else
{
require File::Glob; import File::Glob qw(:glob) ;
$CSH_GLOB = File::Glob::GLOB_CSH() ;
#*globber = \&File::Glob::bsd_glob;
- *globber = \&File::Glob::glob;
+ *globber = \&File::Glob::csh_glob;
}
}
@@ -424,7 +424,7 @@ useful include, file renaming, file copying and file compression.
To help explain what C<File::GlobMapper> does, consider what code you
would write if you wanted to rename all files in the current directory
that ended in C<.tar.gz> to C<.tgz>. So say these files are in the
-current directoty
+current directory
alpha.tar.gz
beta.tar.gz
@@ -474,11 +474,11 @@ Behind the scenes the C<globmap> function does a combination of a
file glob to match existing filenames followed by a substitute
to create the new filenames.
-Notice how both parameters to C<globmap> are strings that are delimired by <>.
+Notice how both parameters to C<globmap> are strings that are delimited by <>.
This is done to make them look more like file globs - it is just syntactic
sugar, but it can be handy when you want the strings to be visually
distinctive. The enclosing <> are optional, so you don't have to use them - in
-fact the first thing globmap will do is remove these delimeters if they are
+fact the first thing globmap will do is remove these delimiters if they are
present.
The first parameter to C<globmap>, C<*.tar.gz>, is an I<Input File Glob>.
@@ -528,7 +528,7 @@ derived from the I<from> filename.
C<File::GlobMapper> has been kept simple deliberately, so it isn't intended to
solve all filename mapping operations. Under the hood C<File::Glob> (or for
-older verions of Perl, C<File::BSDGlob>) is used to match the files, so you
+older versions of Perl, C<File::BSDGlob>) is used to match the files, so you
will never have the flexibility of full Perl regular expression.
=head2 Input File Glob
@@ -624,7 +624,7 @@ Output FileGlobs take the
=item "*"
-The "*" chanacter will be replaced with the complete input filename.
+The "*" character will be replaced with the complete input filename.
=item #1
@@ -668,7 +668,7 @@ Here is an example that renames all c files to cpp.
=head2 A few example globmaps
-Below are a few examles of globmaps
+Below are a few examples of globmaps
To copy all your .c file to a backup directory
diff --git a/ext/Compress/Zlib/lib/IO/Compress/Base.pm b/ext/Compress/Zlib/lib/IO/Compress/Base.pm
new file mode 100644
index 0000000000..e084612ec3
--- /dev/null
+++ b/ext/Compress/Zlib/lib/IO/Compress/Base.pm
@@ -0,0 +1,917 @@
+
+package IO::Compress::Base ;
+
+require 5.004 ;
+
+use strict ;
+use warnings;
+
+use Compress::Zlib::Common;
+use Compress::Zlib::ParseParameters;
+
+use IO::File ;
+use Scalar::Util qw(blessed readonly);
+
+#use File::Glob;
+#require Exporter ;
+use Carp ;
+use Symbol;
+use bytes;
+
+our (@ISA, $VERSION, $got_encode);
+@ISA = qw(Exporter IO::File);
+
+$VERSION = '2.000_05';
+
+#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.
+
+#$got_encode = 0;
+#eval
+#{
+# require Encode;
+# Encode->import('encode', 'find_encoding');
+#};
+#
+#$got_encode = 1 unless $@;
+
+sub saveStatus
+{
+ my $self = shift ;
+ ${ *$self->{ErrorNo} } = shift() + 0 ;
+ ${ *$self->{Error} } = '' ;
+
+ return ${ *$self->{ErrorNo} } ;
+}
+
+
+sub saveErrorString
+{
+ my $self = shift ;
+ my $retval = shift ;
+ ${ *$self->{Error} } = shift ;
+ ${ *$self->{ErrorNo} } = shift() + 0 if @_ ;
+
+ return $retval;
+}
+
+sub croakError
+{
+ my $self = shift ;
+ $self->saveErrorString(0, $_[0]);
+ croak $_[0];
+}
+
+sub closeError
+{
+ my $self = shift ;
+ my $retval = shift ;
+
+ my $errno = *$self->{ErrorNo};
+ my $error = ${ *$self->{Error} };
+
+ $self->close();
+
+ *$self->{ErrorNo} = $errno ;
+ ${ *$self->{Error} } = $error ;
+
+ return $retval;
+}
+
+
+
+sub error
+{
+ my $self = shift ;
+ return ${ *$self->{Error} } ;
+}
+
+sub errorNo
+{
+ my $self = shift ;
+ return ${ *$self->{ErrorNo} } ;
+}
+
+
+sub writeAt
+{
+ my $self = shift ;
+ my $offset = shift;
+ my $data = shift;
+
+ if (defined *$self->{FH}) {
+ my $here = tell(*$self->{FH});
+ return $self->saveErrorString(undef, "Cannot seek to end of output filehandle: $!", $!)
+ if $here < 0 ;
+ seek(*$self->{FH}, $offset, SEEK_SET)
+ or return $self->saveErrorString(undef, "Cannot seek to end of output filehandle: $!", $!) ;
+ defined *$self->{FH}->write($data, length $data)
+ or return $self->saveErrorString(undef, $!, $!) ;
+ seek(*$self->{FH}, $here, SEEK_SET)
+ or return $self->saveErrorString(undef, "Cannot seek to end of output filehandle: $!", $!) ;
+ }
+ else {
+ substr(${ *$self->{Buffer} }, $offset, length($data)) = $data ;
+ }
+
+ return 1;
+}
+
+sub getOneShotParams
+{
+ return ( 'MultiStream' => [1, 1, Parse_boolean, 1],
+ );
+}
+
+sub checkParams
+{
+ my $self = shift ;
+ my $class = shift ;
+
+ my $got = shift || Compress::Zlib::ParseParameters::new();
+
+ $got->parse(
+ {
+ # Generic Parameters
+ 'AutoClose' => [1, 1, Parse_boolean, 0],
+ #'Encoding' => [1, 1, Parse_any, undef],
+ 'Strict' => [0, 1, Parse_boolean, 1],
+ 'Append' => [1, 1, Parse_boolean, 0],
+ 'BinModeIn' => [1, 1, Parse_boolean, 0],
+
+ $self->getExtraParams(),
+ *$self->{OneShot} ? $self->getOneShotParams()
+ : (),
+ },
+ @_) or $self->croakError("${class}: $got->{Error}") ;
+
+ return $got ;
+}
+
+sub _create
+{
+ my $obj = shift;
+ my $got = shift;
+
+ *$obj->{Closed} = 1 ;
+
+ my $class = ref $obj;
+ $obj->croakError("$class: Missing Output parameter")
+ if ! @_ && ! $got ;
+
+ my $outValue = shift ;
+ my $oneShot = 1 ;
+
+ if (! $got)
+ {
+ $oneShot = 0 ;
+ $got = $obj->checkParams($class, undef, @_)
+ or return undef ;
+ }
+
+ my $lax = ! $got->value('Strict') ;
+
+ my $outType = whatIsOutput($outValue);
+
+ $obj->ckOutputParam($class, $outValue)
+ or return undef ;
+
+ if ($outType eq 'buffer') {
+ *$obj->{Buffer} = $outValue;
+ }
+ else {
+ my $buff = "" ;
+ *$obj->{Buffer} = \$buff ;
+ }
+
+ # Merge implies Append
+ my $merge = $got->value('Merge') ;
+ my $appendOutput = $got->value('Append') || $merge ;
+
+ if ($merge)
+ {
+ # Switch off Merge mode if output file/buffer is empty/doesn't exist
+ if (($outType eq 'buffer' && length $$outValue == 0 ) ||
+ ($outType ne 'buffer' && (! -e $outValue || (-w _ && -z _))) )
+ { $merge = 0 }
+ }
+
+ # If output is a file, check that it is writable
+ if ($outType eq 'filename' && -e $outValue && ! -w _)
+ { return $obj->saveErrorString(undef, "Output file '$outValue' is not writable" ) }
+
+ elsif ($outType eq 'handle' && ! -w $outValue)
+ { return $obj->saveErrorString(undef, "Output filehandle is not writable" ) }
+
+
+# TODO - encoding
+# if ($got->parsed('Encoding')) {
+# $obj->croakError("$class: Encode module needed to use -Encoding")
+# if ! $got_encode;
+#
+# my $want_encoding = $got->value('Encoding');
+# my $encoding = find_encoding($want_encoding);
+#
+# $obj->croakError("$class: Encoding '$want_encoding' is not available")
+# if ! $encoding;
+#
+# *$obj->{Encoding} = $encoding;
+# }
+
+ $obj->ckParams($got)
+ or $obj->croakError("${class}: " . $obj->error());
+
+
+ $obj->saveStatus(STATUS_OK) ;
+
+ my $status ;
+ if (! $merge)
+ {
+ *$obj->{Compress} = $obj->mkComp($class, $got)
+ or return undef;
+
+ *$obj->{BytesWritten} = 0 ;
+ *$obj->{UnCompSize_32bit} = 0 ;
+
+ *$obj->{Header} = $obj->mkHeader($got) ;
+
+ if ( $outType eq 'buffer') {
+ ${ *$obj->{Buffer} } = ''
+ unless $appendOutput ;
+ ${ *$obj->{Buffer} } .= *$obj->{Header};
+ }
+ else {
+ if ($outType eq 'handle') {
+ *$obj->{FH} = $outValue ;
+ setBinModeOutput(*$obj->{FH}) ;
+ $outValue->flush() ;
+ *$obj->{Handle} = 1 ;
+ if ($appendOutput)
+ {
+ seek(*$obj->{FH}, 0, SEEK_END)
+ or return $obj->saveErrorString(undef, "Cannot seek to end of output filehandle: $!", $!) ;
+
+ }
+ }
+ elsif ($outType eq 'filename') {
+ my $mode = '>' ;
+ $mode = '>>'
+ if $appendOutput;
+ *$obj->{FH} = new IO::File "$mode $outValue"
+ or return $obj->saveErrorString(undef, "cannot open file '$outValue': $!", $!) ;
+ *$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, $!, $!) ;
+ }
+ }
+ }
+ else
+ {
+ *$obj->{Compress} = $obj->createMerge($outValue, $outType)
+ or return undef;
+ }
+
+ *$obj->{Closed} = 0 ;
+ *$obj->{AutoClose} = $got->value('AutoClose') ;
+ *$obj->{Output} = $outValue;
+ *$obj->{ClassName} = $class;
+ *$obj->{Got} = $got;
+ *$obj->{OneShot} = 0 ;
+
+ return $obj ;
+}
+
+sub ckOutputParam
+{
+ my $self = shift ;
+ my $from = shift ;
+ my $outType = whatIsOutput($_[0]);
+
+ $self->croakError("$from: output parameter not a filename, filehandle or scalar ref")
+ if ! $outType ;
+
+ $self->croakError("$from: output filename is undef or null string")
+ if $outType eq 'filename' && (! defined $_[0] || $_[0] eq '') ;
+
+ $self->croakError("$from: output buffer is read-only")
+ if $outType eq 'buffer' && readonly(${ $_[0] });
+
+ return 1;
+}
+
+
+sub _def
+{
+ my $obj = shift ;
+
+ my $class= (caller)[0] ;
+ my $name = (caller(1))[3] ;
+
+ $obj->croakError("$name: expected at least 1 parameters\n")
+ unless @_ >= 1 ;
+
+ my $input = shift ;
+ my $haveOut = @_ ;
+ my $output = shift ;
+
+ my $x = new Validator($class, *$obj->{Error}, $name, $input, $output)
+ or return undef ;
+
+ push @_, $output if $haveOut && $x->{Hash};
+
+ *$obj->{OneShot} = 1 ;
+
+ 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->_singleTarget($x, 1, $k, $v, @_)
+# or return undef ;
+# }
+#
+# return keys %$input ;
+# }
+
+ if ($x->{GlobMap})
+ {
+ $x->{oneInput} = 1 ;
+ foreach my $pair (@{ $x->{Pairs} })
+ {
+ my ($from, $to) = @$pair ;
+ $obj->_singleTarget($x, 1, $from, $to, @_)
+ or return undef ;
+ }
+
+ return scalar @{ $x->{Pairs} } ;
+ }
+
+ if (! $x->{oneOutput} )
+ {
+ my $inFile = ($x->{inType} eq 'filenames'
+ || $x->{inType} eq 'filename');
+
+ $x->{inType} = $inFile ? 'filename' : 'buffer';
+
+ foreach my $in ($x->{oneInput} ? $input : @$input)
+ {
+ my $out ;
+ $x->{oneInput} = 1 ;
+
+ $obj->_singleTarget($x, $inFile, $in, \$out, @_)
+ or return undef ;
+
+ push @$output, \$out ;
+ #if ($x->{outType} 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, @_);
+
+ croak "should not be here" ;
+}
+
+sub _singleTarget
+{
+ my $obj = shift ;
+ my $x = shift ;
+ my $inputIsFilename = shift;
+ my $input = shift;
+
+ if ($x->{oneInput})
+ {
+ $obj->getFileInfo($x->{Got}, $input)
+ if isaFilename($input) and $inputIsFilename ;
+
+ my $z = $obj->_create($x->{Got}, @_)
+ or return undef ;
+
+
+ defined $z->_wr2($input, $inputIsFilename)
+ or return $z->closeError(undef) ;
+
+ return $z->close() ;
+ }
+ else
+ {
+ my $afterFirst = 0 ;
+ my $inputIsFilename = ($x->{inType} ne 'array');
+ my $keep = $x->{Got}->clone();
+
+ #for my $element ( ($x->{inType} eq 'hash') ? keys %$input : @$input)
+ for my $element ( @$input)
+ {
+ my $isFilename = isaFilename($element);
+
+ if ( $afterFirst ++ )
+ {
+ defined addInterStream($obj, $element, $isFilename)
+ or return $obj->closeError(undef) ;
+ }
+ else
+ {
+ $obj->getFileInfo($x->{Got}, $element)
+ if $isFilename;
+
+ $obj->_create($x->{Got}, @_)
+ or return undef ;
+ }
+
+ defined $obj->_wr2($element, $isFilename)
+ or return $obj->closeError(undef) ;
+
+ *$obj->{Got} = $keep->clone();
+ }
+ return $obj->close() ;
+ }
+
+}
+
+sub _wr2
+{
+ my $self = shift ;
+
+ my $source = shift ;
+ my $inputIsFilename = shift;
+
+ my $input = $source ;
+ if (! $inputIsFilename)
+ {
+ $input = \$source
+ if ! ref $source;
+ }
+
+ if ( ref $input && ref $input eq 'SCALAR' )
+ {
+ return $self->syswrite($input, @_) ;
+ }
+
+ if ( ! ref $input || isaFilehandle($input))
+ {
+ my $isFilehandle = isaFilehandle($input) ;
+
+ my $fh = $input ;
+
+ if ( ! $isFilehandle )
+ {
+ $fh = new IO::File "<$input"
+ or return $self->saveErrorString(undef, "cannot open file '$input': $!", $!) ;
+ }
+ binmode $fh if *$self->{Got}->valueOrDefault('BinModeIn') ;
+
+ my $status ;
+ my $buff ;
+ my $count = 0 ;
+ while (($status = read($fh, $buff, 4096)) > 0) {
+ $count += length $buff;
+ defined $self->syswrite($buff, @_)
+ or return undef ;
+ }
+
+ return $self->saveErrorString(undef, $!, $!)
+ if $status < 0 ;
+
+ if ( (!$isFilehandle || *$self->{AutoClose}) && $input ne '-')
+ {
+ $fh->close()
+ or return undef ;
+ }
+
+ return $count ;
+ }
+
+ croak "Should not be here";
+ return undef;
+}
+
+sub addInterStream
+{
+ my $self = shift ;
+ my $input = shift ;
+ my $inputIsFilename = shift ;
+
+ if (*$self->{Got}->value('MultiStream'))
+ {
+ $self->getFileInfo(*$self->{Got}, $input)
+ #if isaFilename($input) and $inputIsFilename ;
+ if isaFilename($input) ;
+
+ # TODO -- newStream needs to allow gzip/zip header to be modified
+ return $self->newStream();
+ }
+ elsif (*$self->{Got}->value('AutoFlush'))
+ {
+ #return $self->flush(Z_FULL_FLUSH);
+ }
+
+ return 1 ;
+}
+
+sub TIEHANDLE
+{
+ return $_[0] if ref($_[0]);
+ die "OOPS\n" ;
+}
+
+sub UNTIE
+{
+ my $self = shift ;
+}
+
+sub DESTROY
+{
+ my $self = shift ;
+ $self->close() ;
+
+ # TODO - memory leak with 5.8.0 - this isn't called until
+ # global destruction
+ #
+ %{ *$self } = () ;
+ undef $self ;
+}
+
+
+
+sub syswrite
+{
+ my $self = shift ;
+
+ my $buffer ;
+ if (ref $_[0] ) {
+ $self->croakError( *$self->{ClassName} . "::write: not a scalar reference" )
+ unless ref $_[0] eq 'SCALAR' ;
+ $buffer = $_[0] ;
+ }
+ else {
+ $buffer = \$_[0] ;
+ }
+
+
+ if (@_ > 1) {
+ my $slen = defined $$buffer ? length($$buffer) : 0;
+ my $len = $slen;
+ my $offset = 0;
+ $len = $_[1] if $_[1] < $len;
+
+ if (@_ > 2) {
+ $offset = $_[2] || 0;
+ $self->croakError(*$self->{ClassName} . "::write: offset outside string")
+ if $offset > $slen;
+ if ($offset < 0) {
+ $offset += $slen;
+ $self->croakError( *$self->{ClassName} . "::write: offset outside string") if $offset < 0;
+ }
+ my $rem = $slen - $offset;
+ $len = $rem if $rem < $len;
+ }
+
+ $buffer = \substr($$buffer, $offset, $len) ;
+ }
+
+ 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 ;
+ }
+
+# if (*$self->{Encoding}) {
+# $$buffer = *$self->{Encoding}->encode($$buffer);
+# }
+
+ #my $length = length $$buffer;
+ my $status = *$self->{Compress}->compr($buffer, *$self->{Buffer}) ;
+
+ return $self->saveErrorString(undef, *$self->{Compress}{Error},
+ *$self->{Compress}{ErrorNo})
+ if $status == STATUS_ERROR;
+
+
+
+ if ( defined *$self->{FH} and length ${ *$self->{Buffer} }) {
+ defined *$self->{FH}->write( ${ *$self->{Buffer} }, length ${ *$self->{Buffer} } )
+ or return $self->saveErrorString(undef, $!, $!);
+ ${ *$self->{Buffer} } = '' ;
+ }
+
+ return $buffer_length;
+}
+
+sub print
+{
+ my $self = shift;
+
+ #if (ref $self) {
+ # $self = *$self{GLOB} ;
+ #}
+
+ if (defined $\) {
+ if (defined $,) {
+ defined $self->syswrite(join($,, @_) . $\);
+ } else {
+ defined $self->syswrite(join("", @_) . $\);
+ }
+ } else {
+ if (defined $,) {
+ defined $self->syswrite(join($,, @_));
+ } else {
+ defined $self->syswrite(join("", @_));
+ }
+ }
+}
+
+sub printf
+{
+ my $self = shift;
+ my $fmt = shift;
+ defined $self->syswrite(sprintf($fmt, @_));
+}
+
+
+
+sub flush
+{
+ my $self = shift ;
+ my $opt = shift ;
+
+ my $status = *$self->{Compress}->flush(*$self->{Buffer}, $opt) ;
+ 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->{Buffer} } = '' ;
+ }
+
+ return 1;
+}
+
+sub newStream
+{
+ my $self = shift ;
+
+ $self->_writeTrailer()
+ or return 0 ;
+
+ my $got = $self->checkParams('newStream', *$self->{Got}, @_)
+ or return 0 ;
+
+ $self->ckParams($got)
+ 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} } = '' ;
+ }
+
+ my $status = *$self->{Compress}->reset() ;
+ return $self->saveErrorString(0, *$self->{Compress}{Error},
+ *$self->{Compress}{ErrorNo})
+ if $status == STATUS_ERROR;
+
+ *$self->{BytesWritten} = 0 ;
+ *$self->{UnCompSize_32bit} = 0 ;
+
+ return 1 ;
+}
+
+sub _writeTrailer
+{
+ my $self = shift ;
+
+ my $status = *$self->{Compress}->close(*$self->{Buffer}) ;
+ return $self->saveErrorString(0, *$self->{Compress}{Error}, *$self->{Compress}{ErrorNo})
+ if $status == STATUS_ERROR;
+
+ my $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;
+}
+
+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;
+}
+
+sub close
+{
+ my $self = shift ;
+
+ return 1 if *$self->{Closed} || ! *$self->{Compress} ;
+ *$self->{Closed} = 1 ;
+
+ untie *$self
+ if $] >= 5.008 ;
+
+ $self->_writeTrailer()
+ or return 0 ;
+
+ $self->_writeFinalTrailer()
+ or return 0 ;
+
+ if (defined *$self->{FH}) {
+ #if (! *$self->{Handle} || *$self->{AutoClose}) {
+ if ((! *$self->{Handle} || *$self->{AutoClose}) && ! *$self->{StdIO}) {
+ $! = 0 ;
+ *$self->{FH}->close()
+ or return $self->saveErrorString(0, $!, $!);
+ }
+ delete *$self->{FH} ;
+ # This delete can set $! in older Perls, so reset the errno
+ $! = 0 ;
+ }
+
+ return 1;
+}
+
+
+#sub total_in
+#sub total_out
+#sub msg
+#
+#sub crc
+#{
+# my $self = shift ;
+# return *$self->{Compress}->crc32() ;
+#}
+#
+#sub msg
+#{
+# my $self = shift ;
+# return *$self->{Compress}->msg() ;
+#}
+#
+#sub dict_adler
+#{
+# my $self = shift ;
+# return *$self->{Compress}->dict_adler() ;
+#}
+#
+#sub get_Level
+#{
+# my $self = shift ;
+# return *$self->{Compress}->get_Level() ;
+#}
+#
+#sub get_Strategy
+#{
+# my $self = shift ;
+# return *$self->{Compress}->get_Strategy() ;
+#}
+
+
+sub tell
+{
+ my $self = shift ;
+
+ #return *$self->{Compress}->total_in();
+ return *$self->{BytesWritten} ;
+}
+
+sub eof
+{
+ my $self = shift ;
+
+ return *$self->{Closed} ;
+}
+
+
+sub seek
+{
+ my $self = shift ;
+ my $position = shift;
+ my $whence = shift ;
+
+ my $here = $self->tell() ;
+ my $target = 0 ;
+
+ #use IO::Handle qw(SEEK_SET SEEK_CUR SEEK_END);
+ use IO::Handle ;
+
+ if ($whence == IO::Handle::SEEK_SET) {
+ $target = $position ;
+ }
+ elsif ($whence == IO::Handle::SEEK_CUR || $whence == IO::Handle::SEEK_END) {
+ $target = $here + $position ;
+ }
+ else {
+ $self->croakError(*$self->{ClassName} . "::seek: unknown value, $whence, for whence parameter");
+ }
+
+ # short circuit if seeking to current offset
+ return 1 if $target == $here ;
+
+ # Outlaw any attempt to seek backwards
+ $self->croakError(*$self->{ClassName} . "::seek: cannot seek backwards")
+ if $target < $here ;
+
+ # Walk the file to the new offset
+ my $offset = $target - $here ;
+
+ my $buffer ;
+ defined $self->syswrite("\x00" x $offset)
+ or return 0;
+
+ return 1 ;
+}
+
+sub binmode
+{
+ 1;
+# my $self = shift ;
+# return defined *$self->{FH}
+# ? binmode *$self->{FH}
+# : 1 ;
+}
+
+sub fileno
+{
+ my $self = shift ;
+ return defined *$self->{FH}
+ ? *$self->{FH}->fileno()
+ : undef ;
+}
+
+sub _notAvailable
+{
+ my $name = shift ;
+ return sub { croak "$name Not Available: File opened only for output" ; } ;
+}
+
+*read = _notAvailable('read');
+*READ = _notAvailable('read');
+*readline = _notAvailable('readline');
+*READLINE = _notAvailable('readline');
+*getc = _notAvailable('getc');
+*GETC = _notAvailable('getc');
+
+*FILENO = \&fileno;
+*PRINT = \&print;
+*PRINTF = \&printf;
+*WRITE = \&syswrite;
+*write = \&syswrite;
+*SEEK = \&seek;
+*TELL = \&tell;
+*EOF = \&eof;
+*CLOSE = \&close;
+*BINMODE = \&binmode;
+
+#*sysread = \&_notAvailable;
+#*syswrite = \&_write;
+
+1;
+
+__END__
+
diff --git a/ext/Compress/Zlib/lib/IO/Compress/Deflate.pm b/ext/Compress/Zlib/lib/IO/Compress/Deflate.pm
index 8e7e72438b..de438f363f 100644
--- a/ext/Compress/Zlib/lib/IO/Compress/Deflate.pm
+++ b/ext/Compress/Zlib/lib/IO/Compress/Deflate.pm
@@ -2,35 +2,162 @@ package IO::Compress::Deflate ;
use strict ;
use warnings;
+
require Exporter ;
-use IO::Compress::Gzip ;
+use IO::Compress::RawDeflate;
+
+use Compress::Zlib 2 ;
+use Compress::Zlib::FileConstants;
+use Compress::Zlib::Common qw(createSelfTiedObject);
our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $DeflateError);
-$VERSION = '2.000_05';
+$VERSION = '2.000_07';
$DeflateError = '';
-@ISA = qw(Exporter IO::BaseDeflate);
+@ISA = qw(Exporter IO::Compress::RawDeflate);
@EXPORT_OK = qw( $DeflateError deflate ) ;
-%EXPORT_TAGS = %IO::BaseDeflate::EXPORT_TAGS ;
+%EXPORT_TAGS = %IO::Compress::RawDeflate::DEFLATE_CONSTANTS ;
push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
Exporter::export_ok_tags('all');
-
sub new
{
- my $pkg = shift ;
- return IO::BaseDeflate::new($pkg, 'rfc1950', undef, \$DeflateError, @_);
+ my $class = shift ;
+
+ my $obj = createSelfTiedObject($class, \$DeflateError);
+ return $obj->_create(undef, @_);
}
sub deflate
{
- return IO::BaseDeflate::_def(__PACKAGE__, 'rfc1950', \$DeflateError, @_);
+ my $obj = createSelfTiedObject(undef, \$DeflateError);
+ return $obj->_def(@_);
+}
+
+
+sub bitmask($$$$)
+{
+ my $into = shift ;
+ my $value = shift ;
+ my $offset = shift ;
+ my $mask = shift ;
+
+ return $into | (($value & $mask) << $offset ) ;
}
+sub mkDeflateHdr($$$;$)
+{
+ my $method = shift ;
+ my $cinfo = shift;
+ my $level = shift;
+ my $fdict_adler = shift ;
+
+ my $cmf = 0;
+ my $flg = 0;
+ my $fdict = 0;
+ $fdict = 1 if defined $fdict_adler;
+
+ $cmf = bitmask($cmf, $method, ZLIB_CMF_CM_OFFSET, ZLIB_CMF_CM_BITS);
+ $cmf = bitmask($cmf, $cinfo, ZLIB_CMF_CINFO_OFFSET, ZLIB_CMF_CINFO_BITS);
+
+ $flg = bitmask($flg, $fdict, ZLIB_FLG_FDICT_OFFSET, ZLIB_FLG_FDICT_BITS);
+ $flg = bitmask($flg, $level, ZLIB_FLG_LEVEL_OFFSET, ZLIB_FLG_LEVEL_BITS);
+
+ my $fcheck = 31 - ($cmf * 256 + $flg) % 31 ;
+ $flg = bitmask($flg, $fcheck, ZLIB_FLG_FCHECK_OFFSET, ZLIB_FLG_FCHECK_BITS);
+
+ my $hdr = pack("CC", $cmf, $flg) ;
+ $hdr .= pack("N", $fdict_adler) if $fdict ;
+
+ return $hdr;
+}
+
+sub mkHeader
+{
+ my $self = shift ;
+ my $param = shift ;
+
+ my $level = $param->value('Level');
+ my $strategy = $param->value('Strategy');
+
+ my $lflag ;
+ $level = 6
+ if $level == Z_DEFAULT_COMPRESSION ;
+
+ if (ZLIB_VERNUM >= 0x1210)
+ {
+ if ($strategy >= Z_HUFFMAN_ONLY || $level < 2)
+ { $lflag = ZLIB_FLG_LEVEL_FASTEST }
+ elsif ($level < 6)
+ { $lflag = ZLIB_FLG_LEVEL_FAST }
+ elsif ($level == 6)
+ { $lflag = ZLIB_FLG_LEVEL_DEFAULT }
+ else
+ { $lflag = ZLIB_FLG_LEVEL_SLOWEST }
+ }
+ else
+ {
+ $lflag = ($level - 1) >> 1 ;
+ $lflag = 3 if $lflag > 3 ;
+ }
+
+ #my $wbits = (MAX_WBITS - 8) << 4 ;
+ my $wbits = 7;
+ mkDeflateHdr(ZLIB_CMF_CM_DEFLATED, $wbits, $lflag);
+}
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift;
+
+ $got->value('ADLER32' => 1);
+ return 1 ;
+}
+
+
+sub mkTrailer
+{
+ my $self = shift ;
+ return pack("N", *$self->{Compress}->adler32()) ;
+}
+
+sub mkFinalTrailer
+{
+ return '';
+}
+
+#sub newHeader
+#{
+# my $self = shift ;
+# return *$self->{Header};
+#}
+
+sub getExtraParams
+{
+ my $self = shift ;
+ return $self->getZlibParams(),
+}
+
+sub getInverseClass
+{
+ return ('IO::Uncompress::Inflate',
+ \$IO::Uncompress::Inflate::InflateError);
+}
+
+sub getFileInfo
+{
+ my $self = shift ;
+ my $params = shift;
+ my $file = shift ;
+
+}
+
+
1;
@@ -61,7 +188,7 @@ IO::Compress::Deflate - Perl interface to write RFC 1950 files/buffers
$z->seek($position, $whence);
$z->binmode();
$z->fileno();
- $z->newStream();
+ $z->newStream( [OPTS] );
$z->deflateParams();
$z->close() ;
@@ -114,24 +241,25 @@ L<IO::Uncompress::Inflate|IO::Uncompress::Inflate>.
=head1 Functional Interface
-A top-level function, C<deflate>, is provided to carry out "one-shot"
-compression between buffers and/or files. For finer control over the compression process, see the L</"OO Interface"> section.
+A top-level function, C<deflate>, is provided to carry out
+"one-shot" compression between buffers and/or files. For finer
+control over the compression process, see the L</"OO Interface">
+section.
use IO::Compress::Deflate qw(deflate $DeflateError) ;
deflate $input => $output [,OPTS]
or die "deflate failed: $DeflateError\n";
- deflate \%hash [,OPTS]
- or die "deflate failed: $DeflateError\n";
+
The functional interface needs Perl5.005 or better.
=head2 deflate $input => $output [, OPTS]
-If the first parameter is not a hash reference C<deflate> expects
-at least two parameters, C<$input> and C<$output>.
+
+C<deflate> expects at least two parameters, C<$input> and C<$output>.
=head3 The C<$input> parameter
@@ -161,13 +289,15 @@ from C<$$input>.
=item An array reference
-If C<$input> is an array reference, the input data will be read from each
-element of the array in turn. The action taken by C<deflate> with
-each element of the array will depend on the type of data stored
-in it. You can mix and match any of the types defined in this list,
-excluding other array or hash references.
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
The complete array will be walked to ensure that it only
-contains valid data types before any data is compressed.
+contains valid filenames before any data is compressed.
+
+
=item An Input FileGlob string
@@ -195,36 +325,28 @@ compressed data. This parameter can take one of these forms.
=item A filename
-If the C<$output> parameter is a simple scalar, it is assumed to be a filename.
-This file will be opened for writing and the compressed data will be
-written to it.
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the compressed
+data will be written to it.
=item A filehandle
-If the C<$output> parameter is a filehandle, the compressed data will
-be written to it.
+If the C<$output> parameter is a filehandle, the compressed data
+will be written to it.
The string '-' can be used as an alias for standard output.
=item A scalar reference
-If C<$output> is a scalar reference, the compressed data will be stored
-in C<$$output>.
-
-
-=item A Hash Reference
-
-If C<$output> is a hash reference, the compressed data will be written
-to C<$output{$input}> as a scalar reference.
+If C<$output> is a scalar reference, the compressed data will be
+stored in C<$$output>.
-When C<$output> is a hash reference, C<$input> must be either a filename or
-list of filenames. Anything else is an error.
=item An Array Reference
-If C<$output> is an array reference, the compressed data will be pushed
-onto the array.
+If C<$output> is an array reference, the compressed data will be
+pushed onto the array.
=item An Output FileGlob
@@ -239,60 +361,13 @@ string. Anything else is an error.
If the C<$output> parameter is any other type, C<undef> will be returned.
-=head2 deflate \%hash [, OPTS]
-If the first parameter is a hash reference, C<\%hash>, this will be used to
-define both the source of uncompressed data and to control where the
-compressed data is output. Each key/value pair in the hash defines a
-mapping between an input filename, stored in the key, and an output
-file/buffer, stored in the value. Although the input can only be a filename,
-there is more flexibility to control the destination of the compressed
-data. This is determined by the type of the value. Valid types are
-
-=over 5
-
-=item undef
-
-If the value is C<undef> the compressed data will be written to the
-value as a scalar reference.
-
-=item A filename
-
-If the value is a simple scalar, it is assumed to be a filename. This file will
-be opened for writing and the compressed data will be written to it.
-
-=item A filehandle
-
-If the value is a filehandle, the compressed data will be
-written to it.
-The string '-' can be used as an alias for standard output.
-
-
-=item A scalar reference
-
-If the value is a scalar reference, the compressed data will be stored
-in the buffer that is referenced by the scalar.
-
-
-=item A Hash Reference
-
-If the value is a hash reference, the compressed data will be written
-to C<$hash{$input}> as a scalar reference.
-
-=item An Array Reference
-
-If C<$output> is an array reference, the compressed data will be pushed
-onto the array.
-
-=back
-
-Any other type is a error.
=head2 Notes
When C<$input> maps to multiple files/buffers and C<$output> is a single
-file/buffer the compressed input files/buffers will all be stored in
-C<$output> as a single compressed stream.
+file/buffer the compressed input files/buffers will all be stored
+in C<$output> as a single compressed stream.
@@ -306,8 +381,8 @@ L</"Constructor Options"> section below.
=item AutoClose =E<gt> 0|1
-This option applies to any input or output data streams to C<deflate>
-that are filehandles.
+This option applies to any input or output data streams to
+C<deflate> that are filehandles.
If C<AutoClose> is specified, and the value is true, it will result in all
input and/or output filehandles being closed once C<deflate> has
@@ -317,6 +392,16 @@ This parameter defaults to 0.
+=item BinModeIn =E<gt> 0|1
+
+When reading from a file or filehandle, set C<binmode> before reading.
+
+Defaults to 0.
+
+
+
+
+
=item -Append =E<gt> 0|1
TODO
@@ -437,9 +522,9 @@ C<OPTS> is any combination of the following options:
=item -AutoClose =E<gt> 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 closed
-once either the C<close> method is called or the C<IO::Compress::Deflate> object is
-destroyed.
+specified, and the value is true, it will result in the C<$output> being
+closed once either the C<close> method is called or the C<IO::Compress::Deflate>
+object is destroyed.
This parameter defaults to 0.
@@ -447,27 +532,27 @@ This parameter defaults to 0.
Opens C<$output> in append mode.
-The behaviour of this option is dependant on the type of C<$output>.
+The behaviour of this option is dependent on the type of C<$output>.
=over 5
=item * A Buffer
-If C<$output> is a buffer and C<Append> is enabled, all compressed data will be
-append to the end if C<$output>. Otherwise C<$output> will be cleared before
-any data is written to it.
+If C<$output> is a buffer and C<Append> is enabled, all compressed data
+will be append to the end if C<$output>. Otherwise C<$output> will be
+cleared before any data is written to it.
=item * A Filename
-If C<$output> is a filename and C<Append> is enabled, the file will be opened
-in append mode. Otherwise the contents of the file, if any, will be truncated
-before any compressed data is written to it.
+If C<$output> is a filename and C<Append> is enabled, the file will be
+opened in append mode. Otherwise the contents of the file, if any, will be
+truncated before any compressed data is written to it.
=item * A Filehandle
-If C<$output> is a filehandle, the file pointer will be positioned to the end
-of the file via a call to C<seek> before any compressed data is written to it.
-Otherwise the file pointer will not be moved.
+If C<$output> is a filehandle, the file pointer will be positioned to the
+end of the file via a call to C<seek> before any compressed data is written
+to it. Otherwise the file pointer will not be moved.
=back
@@ -481,8 +566,8 @@ data stream stored in C<$output>.
-It is a fatal error to attempt to use this option when C<$output> is not an RFC
-1950 data stream.
+It is a fatal error to attempt to use this option when C<$output> is not an
+RFC 1950 data stream.
@@ -492,8 +577,9 @@ There are a number of other limitations with the C<Merge> option:
=item 1
-This module needs to have been built with zlib 1.2.1 or better to work. A fatal
-error will be thrown if C<Merge> is used with an older version of zlib.
+This module needs to have been built with zlib 1.2.1 or better to work. A
+fatal error will be thrown if C<Merge> is used with an older version of
+zlib.
=item 2
@@ -564,7 +650,7 @@ Usage is
print $z $data
Compresses and outputs the contents of the C<$data> parameter. This
-has the same behavior as the C<print> built-in.
+has the same behaviour as the C<print> built-in.
Returns true if successful.
@@ -727,13 +813,24 @@ underlying file will also be closed.
-=head2 newStream
+=head2 newStream([OPTS])
Usage is
- $z->newStream
+ $z->newStream( [OPTS] )
-TODO
+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
+
+=item * TODO
+
+=back
=head2 deflateParams
@@ -843,7 +940,7 @@ See the Changes file.
=head1 COPYRIGHT AND LICENSE
-Copyright (c) 2005 Paul Marquess. All rights reserved.
+Copyright (c) 2005-2006 Paul Marquess. All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
diff --git a/ext/Compress/Zlib/lib/IO/Compress/Gzip.pm b/ext/Compress/Zlib/lib/IO/Compress/Gzip.pm
index e8e070ba54..840a687f0d 100644
--- a/ext/Compress/Zlib/lib/IO/Compress/Gzip.pm
+++ b/ext/Compress/Zlib/lib/IO/Compress/Gzip.pm
@@ -6,216 +6,194 @@ require 5.004 ;
use strict ;
use warnings;
-# create RFC1952
+
+use IO::Compress::RawDeflate;
+
+use Compress::Zlib 2 ;
+use Compress::Zlib::Common qw(:Status createSelfTiedObject);
+use Compress::Gzip::Constants;
+
+BEGIN
+{
+ if (defined &utf8::downgrade )
+ { *noUTF8 = \&utf8::downgrade }
+ else
+ { *noUTF8 = sub {} }
+}
require Exporter ;
our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $GzipError);
-$VERSION = '2.000_05';
+$VERSION = '2.000_07';
$GzipError = '' ;
-@ISA = qw(Exporter IO::BaseDeflate);
+@ISA = qw(Exporter IO::Compress::RawDeflate);
@EXPORT_OK = qw( $GzipError gzip ) ;
-%EXPORT_TAGS = %IO::BaseDeflate::EXPORT_TAGS ;
+%EXPORT_TAGS = %IO::Compress::RawDeflate::DEFLATE_CONSTANTS ;
push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
Exporter::export_ok_tags('all');
sub new
{
- my $pkg = shift ;
- return IO::BaseDeflate::new($pkg, 'rfc1952', undef, \$GzipError, @_);
+ my $class = shift ;
+
+ my $obj = createSelfTiedObject($class, \$GzipError);
+
+ $obj->_create(undef, @_);
}
sub gzip
{
- return IO::BaseDeflate::_def(__PACKAGE__, 'rfc1952', \$GzipError, @_);
+ my $obj = createSelfTiedObject(undef, \$GzipError);
+ return $obj->_def(@_);
}
-package IO::BaseDeflate;
-
+#sub newHeader
+#{
+# my $self = shift ;
+# #return GZIP_MINIMUM_HEADER ;
+# return $self->mkHeader(*$self->{Got});
+#}
-use Compress::Zlib 2 ;
-use Compress::Zlib::Common;
-use Compress::Zlib::FileConstants;
-use Compress::Zlib::ParseParameters;
-use Compress::Gzip::Constants;
-use IO::Uncompress::Gunzip;
+sub getExtraParams
+{
+ my $self = shift ;
-use IO::File ;
-#use File::Glob;
-require Exporter ;
-use Carp ;
-use Symbol;
-use bytes;
-
-our (@ISA, $VERSION, @EXPORT_OK, %EXPORT_TAGS, $got_encode);
-@ISA = qw(Exporter IO::File);
-%EXPORT_TAGS = ( flush => [qw{
- Z_NO_FLUSH
- Z_PARTIAL_FLUSH
- Z_SYNC_FLUSH
- Z_FULL_FLUSH
- Z_FINISH
- Z_BLOCK
- }],
- level => [qw{
- Z_NO_COMPRESSION
- Z_BEST_SPEED
- Z_BEST_COMPRESSION
- Z_DEFAULT_COMPRESSION
- }],
- strategy => [qw{
- Z_FILTERED
- Z_HUFFMAN_ONLY
- Z_RLE
- Z_FIXED
- Z_DEFAULT_STRATEGY
- }],
-
- );
+ use Compress::Zlib::ParseParameters;
+
+ return (
+ # zlib behaviour
+ $self->getZlibParams(),
-{
- my %seen;
- foreach (keys %EXPORT_TAGS )
- {
- push @{$EXPORT_TAGS{constants}},
- grep { !$seen{$_}++ }
- @{ $EXPORT_TAGS{$_} }
- }
- $EXPORT_TAGS{all} = $EXPORT_TAGS{constants} ;
+ # Gzip header fields
+ 'Minimal' => [0, 1, Parse_boolean, 0],
+ 'Comment' => [0, 1, Parse_any, undef],
+ 'Name' => [0, 1, Parse_any, undef],
+ 'Time' => [0, 1, Parse_any, undef],
+ 'TextFlag' => [0, 1, Parse_boolean, 0],
+ 'HeaderCRC' => [0, 1, Parse_boolean, 0],
+ 'OS_Code' => [0, 1, Parse_unsigned, $Compress::Zlib::gzip_os_code],
+ 'ExtraField'=> [0, 1, Parse_string, undef],
+ 'ExtraFlags'=> [0, 1, Parse_any, undef],
+
+ );
}
-Exporter::export_ok_tags('all');
-
-BEGIN
+sub ckParams
{
- if (defined &utf8::downgrade )
- { *noUTF8 = \&utf8::downgrade }
- else
- { *noUTF8 = sub {} }
-}
-
+ my $self = shift ;
+ my $got = shift ;
-$VERSION = '2.000_03';
+ # gzip always needs crc32
+ $got->value('CRC32' => 1);
-#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.
+ return 1
+ if $got->value('Merge') ;
-#$got_encode = 0;
-#eval
-#{
-# require Encode;
-# Encode->import('encode', 'find_encoding');
-#};
-#
-#$got_encode = 1 unless $@;
+ my $lax = ! $got->value('Strict') ;
-sub saveStatus
-{
- my $self = shift ;
- ${ *$self->{ErrorNo} } = shift() + 0 ;
- ${ *$self->{Error} } = '' ;
- return ${ *$self->{ErrorNo} } ;
-}
+ {
+ if (! $got->parsed('Time') ) {
+ # Modification time defaults to now.
+ $got->value('Time' => time) ;
+ }
+ # Check that the Name & Comment don't have embedded NULLs
+ # Also check that they only contain ISO 8859-1 chars.
+ if ($got->parsed('Name') && defined $got->value('Name')) {
+ my $name = $got->value('Name');
+
+ return $self->saveErrorString(undef, "Null Character found in Name",
+ Z_DATA_ERROR)
+ if ! $lax && $name =~ /\x00/ ;
-sub saveErrorString
-{
- my $self = shift ;
- my $retval = shift ;
- ${ *$self->{Error} } = shift ;
- ${ *$self->{ErrorNo} } = shift() + 0 if @_ ;
+ return $self->saveErrorString(undef, "Non ISO 8859-1 Character found in Name",
+ Z_DATA_ERROR)
+ if ! $lax && $name =~ /$GZIP_FNAME_INVALID_CHAR_RE/o ;
+ }
- return $retval;
-}
+ if ($got->parsed('Comment') && defined $got->value('Comment')) {
+ my $comment = $got->value('Comment');
-sub error
-{
- my $self = shift ;
- return ${ *$self->{Error} } ;
-}
+ return $self->saveErrorString(undef, "Null Character found in Comment",
+ Z_DATA_ERROR)
+ if ! $lax && $comment =~ /\x00/ ;
-sub errorNo
-{
- my $self = shift ;
- return ${ *$self->{ErrorNo} } ;
-}
+ return $self->saveErrorString(undef, "Non ISO 8859-1 Character found in Comment",
+ Z_DATA_ERROR)
+ if ! $lax && $comment =~ /$GZIP_FCOMMENT_INVALID_CHAR_RE/o;
+ }
-sub bitmask($$$$)
-{
- my $into = shift ;
- my $value = shift ;
- my $offset = shift ;
- my $mask = shift ;
+ if ($got->parsed('OS_Code') ) {
+ my $value = $got->value('OS_Code');
- return $into | (($value & $mask) << $offset ) ;
-}
+ return $self->saveErrorString(undef, "OS_Code must be between 0 and 255, got '$value'")
+ if $value < 0 || $value > 255 ;
+
+ }
-sub mkDeflateHdr($$$;$)
-{
- my $method = shift ;
- my $cinfo = shift;
- my $level = shift;
- my $fdict_adler = shift ;
+ # gzip only supports Deflate at present
+ $got->value('Method' => Z_DEFLATED) ;
- my $cmf = 0;
- my $flg = 0;
- my $fdict = 0;
- $fdict = 1 if defined $fdict_adler;
+ if ( ! $got->parsed('ExtraFlags')) {
+ $got->value('ExtraFlags' => 2)
+ if $got->value('Level') == Z_BEST_SPEED ;
+ $got->value('ExtraFlags' => 4)
+ if $got->value('Level') == Z_BEST_COMPRESSION ;
+ }
- $cmf = bitmask($cmf, $method, ZLIB_CMF_CM_OFFSET, ZLIB_CMF_CM_BITS);
- $cmf = bitmask($cmf, $cinfo, ZLIB_CMF_CINFO_OFFSET, ZLIB_CMF_CINFO_BITS);
+ if ($got->parsed('ExtraField')) {
- $flg = bitmask($flg, $fdict, ZLIB_FLG_FDICT_OFFSET, ZLIB_FLG_FDICT_BITS);
- $flg = bitmask($flg, $level, ZLIB_FLG_LEVEL_OFFSET, ZLIB_FLG_LEVEL_BITS);
+ my $bad = $self->parseExtraField($got, $lax) ;
+ return $self->saveErrorString(undef, $bad, Z_DATA_ERROR)
+ if $bad ;
- my $fcheck = 31 - ($cmf * 256 + $flg) % 31 ;
- $flg = bitmask($flg, $fcheck, ZLIB_FLG_FCHECK_OFFSET, ZLIB_FLG_FCHECK_BITS);
+ my $len = length $got->value('ExtraField') ;
+ return $self->saveErrorString(undef, ExtraFieldError("Too Large"),
+ Z_DATA_ERROR)
+ if $len > GZIP_FEXTRA_MAX_SIZE;
+ }
+ }
- my $hdr = pack("CC", $cmf, $flg) ;
- $hdr .= pack("N", $fdict_adler) if $fdict ;
+ return 1;
+}
- return $hdr;
+sub mkTrailer
+{
+ my $self = shift ;
+ return pack("V V", *$self->{Compress}->crc32(),
+ *$self->{UnCompSize_32bit});
}
-sub mkDeflateHeader ($)
+sub getInverseClass
{
- my $param = shift ;
+ return ('IO::Uncompress::Gunzip',
+ \$IO::Uncompress::Gunzip::GunzipError);
+}
- my $level = $param->value('Level');
- my $strategy = $param->value('Strategy');
+sub getFileInfo
+{
+ my $self = shift ;
+ my $params = shift;
+ my $filename = shift ;
- my $lflag ;
- $level = 6
- if $level == Z_DEFAULT_COMPRESSION ;
+ my $defaultTime = (stat($filename))[9] ;
- if (ZLIB_VERNUM >= 0x1210)
- {
- if ($strategy >= Z_HUFFMAN_ONLY || $level < 2)
- { $lflag = ZLIB_FLG_LEVEL_FASTEST }
- elsif ($level < 6)
- { $lflag = ZLIB_FLG_LEVEL_FAST }
- elsif ($level == 6)
- { $lflag = ZLIB_FLG_LEVEL_DEFAULT }
- else
- { $lflag = ZLIB_FLG_LEVEL_SLOWEST }
- }
- else
- {
- $lflag = ($level - 1) >> 1 ;
- $lflag = 3 if $lflag > 3 ;
- }
+ $params->value('Name' => $filename)
+ if ! $params->parsed('Name') ;
- #my $wbits = (MAX_WBITS - 8) << 4 ;
- my $wbits = 7;
- mkDeflateHdr(ZLIB_CMF_CM_DEFLATED, $wbits, $lflag);
+ $params->value('Time' => $defaultTime)
+ if ! $params->parsed('Time') ;
}
-sub mkGzipHeader
+
+sub mkHeader
{
+ my $self = shift ;
my $param = shift ;
# stort-circuit if a minimal header is requested.
@@ -440,1084 +418,11 @@ sub parseExtraField
return undef;
}
-sub checkParams
-{
- my $class = shift ;
- my $type = shift ;
-
- my $rfc1952 = ($type eq 'rfc1952');
- my $rfc1950 = ($type eq 'rfc1950');
-
- my $got = Compress::Zlib::ParseParameters::new();
-
- $got->parse(
- $rfc1952 ?
- {
- 'AutoClose'=> [Parse_boolean, 0],
- #'Encoding'=> [Parse_any, undef],
- 'Strict' => [Parse_boolean, 1],
- 'Append' => [Parse_boolean, 0],
- 'Merge' => [Parse_boolean, 0],
- 'BinModeIn' => [Parse_boolean, 0],
-
- # zlib behaviour
- #'Method' => [Parse_unsigned, Z_DEFLATED],
- 'Level' => [Parse_signed, Z_DEFAULT_COMPRESSION],
- 'Strategy' => [Parse_signed, Z_DEFAULT_STRATEGY],
-
- # Gzip header fields
- 'Minimal' => [Parse_boolean, 0],
- 'Comment' => [Parse_any, undef],
- 'Name' => [Parse_any, undef],
- 'Time' => [Parse_any, undef],
- 'TextFlag' => [Parse_boolean, 0],
- 'HeaderCRC' => [Parse_boolean, 0],
- 'OS_Code' => [Parse_unsigned, $Compress::Zlib::gzip_os_code],
- 'ExtraField'=> [Parse_string, undef],
- 'ExtraFlags'=> [Parse_any, undef],
- }
- :
- {
- 'AutoClose' => [Parse_boolean, 0],
- #'Encoding' => [Parse_any, undef],
- 'CRC32' => [Parse_boolean, 0],
- 'ADLER32' => [Parse_boolean, 0],
- 'Strict' => [Parse_boolean, 1],
- 'Append' => [Parse_boolean, 0],
- 'Merge' => [Parse_boolean, 0],
- 'BinModeIn' => [Parse_boolean, 0],
-
- # zlib behaviour
- #'Method' => [Parse_unsigned, Z_DEFLATED],
- 'Level' => [Parse_signed, Z_DEFAULT_COMPRESSION],
- 'Strategy' => [Parse_signed, Z_DEFAULT_STRATEGY],
- },
- @_) or croak "${class}: $got->{Error}" ;
-
- return $got ;
-}
-
-sub new
-{
- my $class = shift ;
- my $type = shift ;
- my $got = shift;
- my $error_ref = shift ;
-
- croak("$class: Missing Output parameter")
- if ! @_ && ! $got ;
-
- my $outValue = shift ;
- my $oneShot = 1 ;
-
- if (! $got)
- {
- $oneShot = 0 ;
- $got = checkParams($class, $type, @_)
- or return undef ;
- }
-
- my $rfc1952 = ($type eq 'rfc1952');
- my $rfc1950 = ($type eq 'rfc1950');
- my $rfc1951 = ($type eq 'rfc1951');
-
- my $obj = bless Symbol::gensym(), ref($class) || $class;
- tie *$obj, $obj if $] >= 5.005;
-
- *$obj->{Closed} = 1 ;
- $$error_ref = '' ;
- *$obj->{Error} = $error_ref ;
-
- my $lax = ! $got->value('Strict') ;
-
- my $outType = whatIsOutput($outValue);
-
- ckOutputParam($class, $outValue, $error_ref)
- or return undef ;
-
- if ($outType eq 'buffer') {
- *$obj->{Buffer} = $outValue;
- }
- else {
- my $buff = "" ;
- *$obj->{Buffer} = \$buff ;
- }
-
- # Merge implies Append
- my $merge = $got->value('Merge') ;
- my $appendOutput = $got->value('Append') || $merge ;
-
- if ($merge)
- {
- # Switch off Merge mode if output file/buffer is empty/doesn't exist
- if (($outType eq 'buffer' && length $$outValue == 0 ) ||
- ($outType ne 'buffer' && (! -e $outValue || (-w _ && -z _))) )
- { $merge = 0 }
- }
-
- # If output is a file, check that it is writable
- if ($outType eq 'filename' && -e $outValue && ! -w _)
- { return $obj->saveErrorString(undef, "Output file '$outValue' is not writable" ) }
-
- elsif ($outType eq 'handle' && ! -w $outValue)
- { return $obj->saveErrorString(undef, "Output filehandle is not writable" ) }
-
-
-# TODO - encoding
-# if ($got->parsed('Encoding')) {
-# croak("$class: Encode module needed to use -Encoding")
-# if ! $got_encode;
-#
-# my $want_encoding = $got->value('Encoding');
-# my $encoding = find_encoding($want_encoding);
-#
-# croak("$class: Encoding '$want_encoding' is not available")
-# if ! $encoding;
-#
-# *$obj->{Encoding} = $encoding;
-# }
-
- if ($rfc1952 && ! $merge) {
-
- if (! $got->parsed('Time') ) {
- # Modification time defaults to now.
- $got->value('Time' => time) ;
- }
-
- # Check that the Name & Comment don't have embedded NULLs
- # Also check that they only contain ISO 8859-1 chars.
- if ($got->parsed('Name') && defined $got->value('Name')) {
- my $name = $got->value('Name');
-
- return $obj->saveErrorString(undef, "Null Character found in Name",
- Z_DATA_ERROR)
- if ! $lax && $name =~ /\x00/ ;
-
- return $obj->saveErrorString(undef, "Non ISO 8859-1 Character found in Name",
- Z_DATA_ERROR)
- if ! $lax && $name =~ /$GZIP_FNAME_INVALID_CHAR_RE/o ;
- }
-
- if ($got->parsed('Comment') && defined $got->value('Comment')) {
- my $comment = $got->value('Comment');
-
- return $obj->saveErrorString(undef, "Null Character found in Comment",
- Z_DATA_ERROR)
- if ! $lax && $comment =~ /\x00/ ;
-
- return $obj->saveErrorString(undef, "Non ISO 8859-1 Character found in Comment",
- Z_DATA_ERROR)
- if ! $lax && $comment =~ /$GZIP_FCOMMENT_INVALID_CHAR_RE/o;
- }
-
- if ($got->parsed('OS_Code') ) {
- my $value = $got->value('OS_Code');
-
- return $obj->saveErrorString(undef, "OS_Code must be between 0 and 255, got '$value'")
- if $value < 0 || $value > 255 ;
-
- }
-
- # gzip only supports Deflate at present
- $got->value('Method' => Z_DEFLATED) ;
-
- if ( ! $got->parsed('ExtraFlags')) {
- $got->value('ExtraFlags' => 2)
- if $got->value('Level') == Z_BEST_SPEED ;
- $got->value('ExtraFlags' => 4)
- if $got->value('Level') == Z_BEST_COMPRESSION ;
- }
-
- if ($got->parsed('ExtraField')) {
-
- my $bad = $obj->parseExtraField($got, $lax) ;
- return $obj->saveErrorString(undef, $bad, Z_DATA_ERROR)
- if $bad ;
-
- my $len = length $got->value('ExtraField') ;
- return $obj->saveErrorString(undef, ExtraFieldError("Too Large"),
- Z_DATA_ERROR)
- if $len > GZIP_FEXTRA_MAX_SIZE;
- }
- }
-
- $obj->saveStatus(Z_OK) ;
-
- my $end_offset = 0;
- my $status ;
- if (! $merge)
- {
- (*$obj->{Deflate}, $status) = new Compress::Zlib::Deflate
- -AppendOutput => 1,
- -CRC32 => $rfc1952 || $got->value('CRC32'),
- -ADLER32 => $rfc1950 || $got->value('ADLER32'),
- -Level => $got->value('Level'),
- -Strategy => $got->value('Strategy'),
- -WindowBits => - MAX_WBITS;
- return $obj->saveErrorString(undef, "Cannot create Deflate object: $status" )
- if $obj->saveStatus($status) != Z_OK ;
-
- *$obj->{BytesWritten} = 0 ;
- *$obj->{ISize} = 0 ;
-
- *$obj->{Header} = mkDeflateHeader($got)
- if $rfc1950 ;
- *$obj->{Header} = ''
- if $rfc1951 ;
- *$obj->{Header} = mkGzipHeader($got)
- if $rfc1952 ;
-
- if ( $outType eq 'buffer') {
- ${ *$obj->{Buffer} } = ''
- unless $appendOutput ;
- ${ *$obj->{Buffer} } .= *$obj->{Header};
- }
- else {
- if ($outType eq 'handle') {
- $outValue->flush() ;
- *$obj->{FH} = $outValue ;
- setBinModeOutput(*$obj->{FH}) ;
- *$obj->{Handle} = 1 ;
- if ($appendOutput)
- {
- seek(*$obj->{FH}, 0, SEEK_END)
- or return $obj->saveErrorString(undef, "Cannot seek to end of output filehandle: $!", $!) ;
-
- }
- }
- elsif ($outType eq 'filename') {
- my $mode = '>' ;
- $mode = '>>'
- if $appendOutput;
- *$obj->{FH} = new IO::File "$mode $outValue"
- or return $obj->saveErrorString(undef, "cannot open file '$outValue': $!", $!) ;
- *$obj->{StdIO} = ($outValue eq '-');
- setBinModeOutput(*$obj->{FH}) ;
- }
-
- if (!$rfc1951) {
- defined *$obj->{FH}->write(*$obj->{Header}, length(*$obj->{Header}))
- or return $obj->saveErrorString(undef, $!, $!) ;
- }
- }
- }
- else
- {
- my %mapping = ( 'rfc1952' => ['IO::Uncompress::Gunzip', \$IO::Uncompress::Gunzip::GunzipError],
- 'rfc1950' => ['IO::Uncompress::Inflate', \$IO::Uncompress::Inflate::InflateError],
- 'rfc1951' => ['IO::Uncompress::RawInflate', \$IO::Uncompress::RawInflate::RawInflateError],
- );
-
- my $inf = IO::BaseInflate::new($mapping{$type}[0],
- $type, undef,
- $error_ref, 0, $outValue,
- Transparent => 0,
- #Strict => 1,
- AutoClose => 0,
- Scan => 1);
-
- return $obj->saveErrorString(undef, "Cannot create InflateScan object: $$error_ref" )
- if ! defined $inf ;
-
- $inf->scan()
- or return $obj->saveErrorString(undef, "Error Scanning: $$error_ref", $inf->errorNo) ;
- $inf->zap($end_offset)
- or return $obj->saveErrorString(undef, "Error Zapping: $$error_ref", $inf->errorNo) ;
-
- (*$obj->{Deflate}, $status) = $inf->createDeflate();
-
- *$obj->{Header} = *$inf->{Info}{Header};
- *$obj->{ISize} =
- *$obj->{ISize} = *$obj->{BytesWritten} = *$inf->{ISize} ;
-
- if ( $outType eq 'buffer')
- { substr( ${ *$obj->{Buffer} }, $end_offset) = '' }
- elsif ($outType eq 'handle' || $outType eq 'filename') {
- *$obj->{FH} = *$inf->{FH} ;
- delete *$inf->{FH};
- *$obj->{FH}->flush() ;
- *$obj->{Handle} = 1 if $outType eq 'handle';
-
- #seek(*$obj->{FH}, $end_offset, SEEK_SET)
- *$obj->{FH}->seek($end_offset, SEEK_SET)
- or return $obj->saveErrorString(undef, $!, $!) ;
- }
- }
-
- *$obj->{Closed} = 0 ;
- *$obj->{AutoClose} = $got->value('AutoClose') ;
- *$obj->{OutputGzip} = $rfc1952;
- *$obj->{OutputDeflate} = $rfc1950;
- *$obj->{OutputRawDeflate} = $rfc1951;
- *$obj->{Output} = $outValue;
- *$obj->{ClassName} = $class;
- *$obj->{Got} = $got;
-
- return $obj ;
-}
-
-sub _def
-{
- my $class = shift ;
- my $type = shift ;
- my $error_ref = shift ;
-
- my $name = (caller(1))[3] ;
-
- croak "$name: expected at least 1 parameters\n"
- unless @_ >= 1 ;
-
- my $input = shift ;
- my $haveOut = @_ ;
- my $output = shift ;
-
- my $x = new Validator($class, $type, $error_ref, $name, $input, $output)
- or return undef ;
-
- push @_, $output if $haveOut && $x->{Hash};
-
- my $got = checkParams($name, $type, @_)
- or return undef ;
-
- $x->{Got} = $got ;
- $x->{ParsedTime} = $got->parsed('Time') ;
- $x->{ParsedName} = $got->parsed('Name') ;
-
- if ($x->{Hash})
- {
- while (my($k, $v) = each %$input)
- {
- $v = \$input->{$k}
- unless defined $v ;
-
- _singleTarget($x, 1, $k, $v, @_)
- or return undef ;
- }
-
- return keys %$input ;
- }
-
- if ($x->{GlobMap})
- {
- $x->{oneInput} = 1 ;
- foreach my $pair (@{ $x->{Pairs} })
- {
- my ($from, $to) = @$pair ;
- _singleTarget($x, 1, $from, $to, @_)
- or return undef ;
- }
-
- return scalar @{ $x->{Pairs} } ;
- }
-
- if (! $x->{oneOutput} )
- {
- my $inFile = ($x->{inType} eq 'filenames'
- || $x->{inType} eq 'filename');
-
- $x->{inType} = $inFile ? 'filename' : 'buffer';
-
- foreach my $in ($x->{oneInput} ? $input : @$input)
- {
- my $out ;
- $x->{oneInput} = 1 ;
-
- _singleTarget($x, $inFile, $in, \$out, @_)
- or return undef ;
-
- if ($x->{outType} eq 'array')
- { push @$output, \$out }
- else
- { $output->{$in} = \$out }
- }
-
- return 1 ;
- }
-
- # finally the 1 to 1 and n to 1
- return _singleTarget($x, 1, $input, $output, @_);
-
- croak "should not be here" ;
-}
-
-sub _singleTarget
-{
- my $x = shift ;
- my $inputIsFilename = shift;
- my $input = shift;
-
-
- # For gzip, if input is simple filename, populate Name & Time in
- # gzip header from filename by default.
- if ($x->{Type} eq 'rfc1952' and isaFilename($input) and $inputIsFilename)
- {
- my $defaultTime = (stat($input))[8] ;
-
- $x->{Got}->value('Name' => $input)
- if ! $x->{ParsedName};
-
- $x->{Got}->value('Time' => $defaultTime)
- if ! $x->{ParsedTime};
- }
-
- my $gzip = new($x->{Class}, $x->{Type}, $x->{Got}, $x->{Error}, @_)
- or return undef ;
-
-
- if ($x->{oneInput})
- {
- defined $gzip->_wr2($input, $inputIsFilename)
- or return undef ;
- }
- else
- {
- my $afterFirst = 0 ;
- my $inputIsFilename = ($x->{inType} ne 'array');
-
- for my $element ( ($x->{inType} eq 'hash') ? keys %$input : @$input)
- {
- if ( $afterFirst ++ )
- {
- defined addInterStream($gzip, $x, $element, $inputIsFilename)
- or return undef ;
- }
-
- defined $gzip->_wr2($element, $inputIsFilename)
- or return undef ;
- }
- }
-
- return $gzip->close() ;
-}
-
-sub _wr2
-{
- my $self = shift ;
-
- my $source = shift ;
- my $inputIsFilename = shift;
-
- my $input = $source ;
- if (! $inputIsFilename)
- {
- $input = \$source
- if ! ref $source;
- }
-
- if ( ref $input && ref $input eq 'SCALAR' )
- {
- return $self->syswrite($input, @_) ;
- }
-
- if ( ! ref $input || isaFilehandle($input))
- {
- my $isFilehandle = isaFilehandle($input) ;
-
- my $fh = $input ;
-
- if ( ! $isFilehandle )
- {
- $fh = new IO::File "<$input"
- or return $self->saveErrorString(undef, "cannot open file '$input': $!", $!) ;
- }
- binmode $fh if *$self->{Got}->valueOrDefault('BinModeIn') ;
-
- my $status ;
- my $buff ;
- my $count = 0 ;
- while (($status = read($fh, $buff, 4096)) > 0) {
- $count += length $buff;
- defined $self->syswrite($buff, @_)
- or return undef ;
- }
-
- return $self->saveErrorString(undef, $!, $!)
- if $status < 0 ;
-
- if ( (!$isFilehandle || *$self->{AutoClose}) && $input ne '-')
- {
- $fh->close()
- or return undef ;
- }
-
- return $count ;
- }
-
- croak "Should no be here";
- return undef;
-}
-
-sub addInterStream
+sub mkFinalTrailer
{
- my $gzip = shift ;
- my $x = shift ;
- my $input = shift ;
- my $inputIsFilename = shift ;
-
- if ($x->{Got}->value('MultiStream'))
- {
- # For gzip, if input is simple filename, populate Name & Time in
- # gzip header from filename by default.
- if ($x->{Type} eq 'rfc1952' and isaFilename($input) and $inputIsFilename)
- {
- my $defaultTime = (stat($input))[8] ;
-
- $x->{Got}->value('Name' => $input)
- if ! $x->{ParsedName};
-
- $x->{Got}->value('Time' => $defaultTime)
- if ! $x->{ParsedTime};
- }
-
- # TODO -- newStream needs to allow gzip header to be modified
- return $gzip->newStream();
- }
- elsif ($x->{Got}->value('AutoFlush'))
- {
- return $gzip->flush(Z_FULL_FLUSH);
- }
-
- return 1 ;
+ return '';
}
-sub TIEHANDLE
-{
- return $_[0] if ref($_[0]);
- die "OOPS\n" ;
-}
-
-sub UNTIE
-{
- my $self = shift ;
-}
-
-sub DESTROY
-{
- my $self = shift ;
- $self->close() ;
-
- # TODO - memory leak with 5.8.0 - this isn't called until
- # global destruction
- #
- %{ *$self } = () ;
- undef $self ;
-}
-
-
-#sub validateInput
-#{
-# my $class = shift ;
-#
-# #local $Carp::CarpLevel = 1;
-#
-# if ( ! ref $_[0] ||
-# ref $_[0] eq 'SCALAR' ||
-# #ref $_[0] eq 'CODE' ||
-# isaFilehandle($_[0]) )
-# {
-# my $inType = whatIs($_[0]);
-# my $outType = whatIs($_[1]);
-#
-# if ($inType eq 'filename' )
-# {
-# croak "$class: input filename is undef or null string"
-# if ! defined $_[0] || $_[0] eq '' ;
-#
-# if ($_[0] ne '-' && ! -e $_[0] )
-# {
-# ${$_[2]} = "input file '$_[0]' does not exist";
-# $_[3] = $!;
-# return undef;
-# }
-#
-# if (! -r $_[0] )
-# {
-# ${$_[2]} = "cannot open file '$_[0]': $!";
-# $_[3] = $!;
-# return undef;
-# }
-# }
-# elsif ($inType eq 'fileglob' )
-# {
-# # whatever...
-# }
-#
-# croak("$class: input and output $inType are identical")
-# if defined $outType && $inType eq $outType && $_[0] eq $_[1] ;
-#
-# return 1 ;
-# }
-#
-# croak "$class: input parameter not a filename, filehandle, array ref or scalar ref"
-# unless ref $_[0] eq 'ARRAY' ;
-#
-# my $array = shift @_ ;
-# foreach my $element ( @{ $array } )
-# {
-# return undef
-# unless validateInput($class, $element, @_);
-# }
-#
-# return 1 ;
-#}
-
-
-#sub write
-#{
-# my $self = shift ;
-#
-# if ( isaFilehandle $_[0] )
-# {
-# return $self->_wr(@_);
-# }
-#
-# if ( ref $_[0])
-# {
-# if ( ref $_[0] eq 'SCALAR' )
-# { return $self->syswrite(@_) }
-#
-# if ( ref $_[0] eq 'ARRAY' )
-# {
-# my ($str, $num);
-# validateInput(*$self->{ClassName} . "::write", $_[0], *$self->{Output}, \$str, $num)
-# or return $self->saveErrorString(undef, $str, $num);
-#
-# return $self->_wr(@_);
-# }
-#
-# croak *$self->{ClassName} . "::write: input parameter not a filename, filehandle, array ref or scalar ref";
-# }
-#
-# # Not a reference or a filehandle
-# return $self->syswrite(@_) ;
-#}
-#
-#sub _wr
-#{
-# my $self = shift ;
-#
-# if ( ref $_[0] && ref $_[0] eq 'SCALAR' )
-# {
-# return $self->syswrite(@_) ;
-# }
-#
-# if ( ! ref $_[0] || isaFilehandle($_[0]))
-# {
-# my $item = shift @_ ;
-# my $isFilehandle = isaFilehandle($item) ;
-#
-# my $fh = $item ;
-#
-# if ( ! $isFilehandle )
-# {
-# $fh = new IO::File "<$item"
-# or return $self->saveErrorString(undef, "cannot open file '$item': $!", $!) ;
-# }
-#
-# my $status ;
-# my $buff ;
-# my $count = 0 ;
-# while (($status = read($fh, $buff, 4096)) > 0) {
-# $count += length $buff;
-# defined $self->syswrite($buff, @_)
-# or return undef ;
-# }
-#
-# return $self->saveErrorString(undef, $!, $!)
-# if $status < 0 ;
-#
-#
-# if ( !$isFilehandle || *$self->{AutoClose} )
-# {
-# $fh->close()
-# or return undef ;
-# }
-#
-# return $count ;
-# }
-#
-# #if ref $_[0] eq 'CODE' ;
-#
-# # then must be ARRAY ref
-# my $count = 0 ;
-# my $array = shift @_ ;
-# foreach my $element ( @{ $array } )
-# {
-# my $got = $self->_wr($element, @_) ;
-#
-# return undef
-# unless defined $got ;
-#
-# $count += $got ;
-# }
-#
-# return $count ;
-#}
-
-
-sub syswrite
-{
- my $self = shift ;
-
- my $buffer ;
- if (ref $_[0] ) {
- croak *$self->{ClassName} . "::write: not a scalar reference"
- unless ref $_[0] eq 'SCALAR' ;
- $buffer = $_[0] ;
- }
- else {
- $buffer = \$_[0] ;
- }
-
- if (@_ > 1) {
- my $slen = defined $$buffer ? length($$buffer) : 0;
- my $len = $slen;
- my $offset = 0;
- $len = $_[1] if $_[1] < $len;
-
- if (@_ > 2) {
- $offset = $_[2] || 0;
- croak *$self->{ClassName} . "::write: offset outside string" if $offset > $slen;
- if ($offset < 0) {
- $offset += $slen;
- croak *$self->{ClassName} . "::write: offset outside string" if $offset < 0;
- }
- my $rem = $slen - $offset;
- $len = $rem if $rem < $len;
- }
-
- $buffer = \substr($$buffer, $offset, $len) ;
- }
-
- my $buffer_length = defined $$buffer ? length($$buffer) : 0 ;
- *$self->{BytesWritten} += $buffer_length ;
- my $rest = GZIP_ISIZE_MAX - *$self->{ISize} ;
- if ($buffer_length > $rest) {
- *$self->{ISize} = $buffer_length - $rest - 1;
- }
- else {
- *$self->{ISize} += $buffer_length ;
- }
-
-# if (*$self->{Encoding}) {
-# $$buffer = *$self->{Encoding}->encode($$buffer);
-# }
-
- #my $length = length $$buffer;
- my $status = *$self->{Deflate}->deflate($buffer, *$self->{Buffer}) ;
-
- return $self->saveErrorString(undef,"Deflate Error: $status")
- if $self->saveStatus($status) != Z_OK ;
-
- if ( defined *$self->{FH} and length ${ *$self->{Buffer} }) {
- defined *$self->{FH}->write( ${ *$self->{Buffer} }, length ${ *$self->{Buffer} } )
- or return $self->saveErrorString(undef, $!, $!);
- ${ *$self->{Buffer} } = '' ;
- }
-
- return $buffer_length;
-}
-
-sub print
-{
- my $self = shift;
-
- #if (ref $self) {
- # $self = *$self{GLOB} ;
- #}
-
- if (defined $\) {
- if (defined $,) {
- defined $self->syswrite(join($,, @_) . $\);
- } else {
- defined $self->syswrite(join("", @_) . $\);
- }
- } else {
- if (defined $,) {
- defined $self->syswrite(join($,, @_));
- } else {
- defined $self->syswrite(join("", @_));
- }
- }
-}
-
-sub printf
-{
- my $self = shift;
- my $fmt = shift;
- defined $self->syswrite(sprintf($fmt, @_));
-}
-
-
-
-sub flush
-{
- my $self = shift ;
- my $opt = shift || Z_FINISH ;
- my $status = *$self->{Deflate}->flush(*$self->{Buffer}, $opt) ;
- return $self->saveErrorString(0,"Deflate Error: $status")
- if $self->saveStatus($status) != Z_OK ;
-
- if ( defined *$self->{FH} ) {
- *$self->{FH}->clearerr();
- defined *$self->{FH}->write(${ *$self->{Buffer} }, length ${ *$self->{Buffer} })
- or return $self->saveErrorString(0, $!, $!);
- ${ *$self->{Buffer} } = '' ;
- }
-
- return 1;
-}
-
-sub newStream
-{
- my $self = shift ;
-
- $self->_writeTrailer(GZIP_MINIMUM_HEADER)
- or return 0 ;
-
- my $status = *$self->{Deflate}->deflateReset() ;
- return $self->saveErrorString(0,"Deflate Error: $status")
- if $self->saveStatus($status) != Z_OK ;
-
- *$self->{BytesWritten} = 0 ;
- *$self->{ISize} = 0 ;
-
- return 1 ;
-}
-
-sub _writeTrailer
-{
- my $self = shift ;
- my $nextHeader = shift || '' ;
-
- my $status = *$self->{Deflate}->flush(*$self->{Buffer}) ;
- return $self->saveErrorString(0,"Deflate Error: $status")
- if $self->saveStatus($status) != Z_OK ;
-
- if (*$self->{OutputGzip}) {
- ${ *$self->{Buffer} } .= pack("V V", *$self->{Deflate}->crc32(),
- *$self->{ISize} );
- ${ *$self->{Buffer} } .= $nextHeader ;
- }
-
- if (*$self->{OutputDeflate}) {
- ${ *$self->{Buffer} } .= pack("N", *$self->{Deflate}->adler32() );
- ${ *$self->{Buffer} } .= *$self->{Header} ;
- }
-
- return 1 if ! defined *$self->{FH} ;
-
- defined *$self->{FH}->write(${ *$self->{Buffer} }, length ${ *$self->{Buffer} })
- or return $self->saveErrorString(0, $!, $!);
-
- ${ *$self->{Buffer} } = '' ;
-
- return 1;
-}
-
-sub close
-{
- my $self = shift ;
-
- return 1 if *$self->{Closed} || ! *$self->{Deflate} ;
- *$self->{Closed} = 1 ;
-
- untie *$self
- if $] >= 5.008 ;
-
- if (0) {
- $self->_writeTrailer()
- or return 0 ;
- }
- else {
-
-
- my $status = *$self->{Deflate}->flush(*$self->{Buffer}) ;
- return $self->saveErrorString(0,"Deflate Error: $status")
- if $self->saveStatus($status) != Z_OK ;
-
- if (*$self->{OutputGzip}) {
- ${ *$self->{Buffer} } .= pack("V V", *$self->{Deflate}->crc32(),
- *$self->{ISize} );
- }
-
- if (*$self->{OutputDeflate}) {
- ${ *$self->{Buffer} } .= pack("N", *$self->{Deflate}->adler32() );
- }
-
-
- return 1 if ! defined *$self->{FH} ;
-
- defined *$self->{FH}->write(${ *$self->{Buffer} }, length( ${ *$self->{Buffer} } ))
- or return $self->saveErrorString(0, $!, $!);
-
- ${ *$self->{Buffer} } = '' ;
- }
-
- if (defined *$self->{FH}) {
- #if (! *$self->{Handle} || *$self->{AutoClose}) {
- if ((! *$self->{Handle} || *$self->{AutoClose}) && ! *$self->{StdIO}) {
- $! = 0 ;
- *$self->{FH}->close()
- or return $self->saveErrorString(0, $!, $!);
- }
- delete *$self->{FH} ;
- # This delete can set $! in older Perls, so reset the errno
- $! = 0 ;
- }
-
- return 1;
-}
-
-sub deflateParams
-{
- my $self = shift ;
- my $level = shift ;
- my $strategy = shift ;
-
- my $status = *$self->{Deflate}->deflateParams(-Level => $level,
- -Strategy => $strategy) ;
- return $self->saveErrorString(0,"deflateParams Error: $status")
- if $self->saveStatus($status) != Z_OK ;
-
- return 1;
-}
-
-
-#sub total_in
-#sub total_out
-#sub msg
-#
-#sub crc
-#{
-# my $self = shift ;
-# return *$self->{Deflate}->crc32() ;
-#}
-#
-#sub msg
-#{
-# my $self = shift ;
-# return *$self->{Deflate}->msg() ;
-#}
-#
-#sub dict_adler
-#{
-# my $self = shift ;
-# return *$self->{Deflate}->dict_adler() ;
-#}
-#
-#sub get_Level
-#{
-# my $self = shift ;
-# return *$self->{Deflate}->get_Level() ;
-#}
-#
-#sub get_Strategy
-#{
-# my $self = shift ;
-# return *$self->{Deflate}->get_Strategy() ;
-#}
-
-
-sub tell
-{
- my $self = shift ;
-
- #return *$self->{Deflate}->total_in();
- return *$self->{BytesWritten} ;
-}
-
-sub eof
-{
- my $self = shift ;
-
- return *$self->{Closed} ;
-}
-
-
-sub seek
-{
- my $self = shift ;
- my $position = shift;
- my $whence = shift ;
-
- my $here = $self->tell() ;
- my $target = 0 ;
-
- #use IO::Handle qw(SEEK_SET SEEK_CUR SEEK_END);
- use IO::Handle ;
-
- if ($whence == IO::Handle::SEEK_SET) {
- $target = $position ;
- }
- elsif ($whence == IO::Handle::SEEK_CUR || $whence == IO::Handle::SEEK_END) {
- $target = $here + $position ;
- }
- else {
- croak *$self->{ClassName} . "::seek: unknown value, $whence, for whence parameter";
- }
-
- # short circuit if seeking to current offset
- return 1 if $target == $here ;
-
- # Outlaw any attempt to seek backwards
- croak *$self->{ClassName} . "::seek: cannot seek backwards"
- if $target < $here ;
-
- # Walk the file to the new offset
- my $offset = $target - $here ;
-
- my $buffer ;
- defined $self->syswrite("\x00" x $offset)
- or return 0;
-
- return 1 ;
-}
-
-sub binmode
-{
- 1;
-# my $self = shift ;
-# return defined *$self->{FH}
-# ? binmode *$self->{FH}
-# : 1 ;
-}
-
-sub fileno
-{
- my $self = shift ;
- return defined *$self->{FH}
- ? *$self->{FH}->fileno()
- : undef ;
-}
-
-sub _notAvailable
-{
- my $name = shift ;
- return sub { croak "$name Not Available: File opened only for output" ; } ;
-}
-
-*read = _notAvailable('read');
-*READ = _notAvailable('read');
-*readline = _notAvailable('readline');
-*READLINE = _notAvailable('readline');
-*getc = _notAvailable('getc');
-*GETC = _notAvailable('getc');
-
-*FILENO = \&fileno;
-*PRINT = \&print;
-*PRINTF = \&printf;
-*WRITE = \&syswrite;
-*write = \&syswrite;
-*SEEK = \&seek;
-*TELL = \&tell;
-*EOF = \&eof;
-*CLOSE = \&close;
-*BINMODE = \&binmode;
-
-#*sysread = \&_notAvailable;
-#*syswrite = \&_write;
-
1;
__END__
@@ -1547,7 +452,7 @@ IO::Compress::Gzip - Perl interface to write RFC 1952 files/buffers
$z->seek($position, $whence);
$z->binmode();
$z->fileno();
- $z->newStream();
+ $z->newStream( [OPTS] );
$z->deflateParams();
$z->close() ;
@@ -1603,24 +508,25 @@ L<IO::Uncompress::Gunzip|IO::Uncompress::Gunzip>.
=head1 Functional Interface
-A top-level function, C<gzip>, is provided to carry out "one-shot"
-compression between buffers and/or files. For finer control over the compression process, see the L</"OO Interface"> section.
+A top-level function, C<gzip>, is provided to carry out
+"one-shot" compression between buffers and/or files. For finer
+control over the compression process, see the L</"OO Interface">
+section.
use IO::Compress::Gzip qw(gzip $GzipError) ;
gzip $input => $output [,OPTS]
or die "gzip failed: $GzipError\n";
- gzip \%hash [,OPTS]
- or die "gzip failed: $GzipError\n";
+
The functional interface needs Perl5.005 or better.
=head2 gzip $input => $output [, OPTS]
-If the first parameter is not a hash reference C<gzip> expects
-at least two parameters, C<$input> and C<$output>.
+
+C<gzip> expects at least two parameters, C<$input> and C<$output>.
=head3 The C<$input> parameter
@@ -1650,13 +556,15 @@ from C<$$input>.
=item An array reference
-If C<$input> is an array reference, the input data will be read from each
-element of the array in turn. The action taken by C<gzip> with
-each element of the array will depend on the type of data stored
-in it. You can mix and match any of the types defined in this list,
-excluding other array or hash references.
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
The complete array will be walked to ensure that it only
-contains valid data types before any data is compressed.
+contains valid filenames before any data is compressed.
+
+
=item An Input FileGlob string
@@ -1680,10 +588,11 @@ two of the gzip header fields created by this function will be sourced
from that file -- the NAME gzip header field will be populated with
the filename itself, and the MTIME header field will be set to the
modification time of the file.
-The intention here is to mirror part of the behavior of the gzip
+The intention here is to mirror part of the behaviour of the gzip
executable.
If you do not want to use these defaults they can be overridden by
-explicitly setting the C<Name> and C<Time> options.
+explicitly setting the C<Name> and C<Time> options or by setting the
+C<Minimal> parameter.
@@ -1696,36 +605,28 @@ compressed data. This parameter can take one of these forms.
=item A filename
-If the C<$output> parameter is a simple scalar, it is assumed to be a filename.
-This file will be opened for writing and the compressed data will be
-written to it.
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the compressed
+data will be written to it.
=item A filehandle
-If the C<$output> parameter is a filehandle, the compressed data will
-be written to it.
+If the C<$output> parameter is a filehandle, the compressed data
+will be written to it.
The string '-' can be used as an alias for standard output.
=item A scalar reference
-If C<$output> is a scalar reference, the compressed data will be stored
-in C<$$output>.
-
+If C<$output> is a scalar reference, the compressed data will be
+stored in C<$$output>.
-=item A Hash Reference
-
-If C<$output> is a hash reference, the compressed data will be written
-to C<$output{$input}> as a scalar reference.
-
-When C<$output> is a hash reference, C<$input> must be either a filename or
-list of filenames. Anything else is an error.
=item An Array Reference
-If C<$output> is an array reference, the compressed data will be pushed
-onto the array.
+If C<$output> is an array reference, the compressed data will be
+pushed onto the array.
=item An Output FileGlob
@@ -1740,60 +641,13 @@ string. Anything else is an error.
If the C<$output> parameter is any other type, C<undef> will be returned.
-=head2 gzip \%hash [, OPTS]
-
-If the first parameter is a hash reference, C<\%hash>, this will be used to
-define both the source of uncompressed data and to control where the
-compressed data is output. Each key/value pair in the hash defines a
-mapping between an input filename, stored in the key, and an output
-file/buffer, stored in the value. Although the input can only be a filename,
-there is more flexibility to control the destination of the compressed
-data. This is determined by the type of the value. Valid types are
-
-=over 5
-
-=item undef
-
-If the value is C<undef> the compressed data will be written to the
-value as a scalar reference.
-
-=item A filename
-
-If the value is a simple scalar, it is assumed to be a filename. This file will
-be opened for writing and the compressed data will be written to it.
-
-=item A filehandle
-
-If the value is a filehandle, the compressed data will be
-written to it.
-The string '-' can be used as an alias for standard output.
-
-
-=item A scalar reference
-If the value is a scalar reference, the compressed data will be stored
-in the buffer that is referenced by the scalar.
-
-
-=item A Hash Reference
-
-If the value is a hash reference, the compressed data will be written
-to C<$hash{$input}> as a scalar reference.
-
-=item An Array Reference
-
-If C<$output> is an array reference, the compressed data will be pushed
-onto the array.
-
-=back
-
-Any other type is a error.
=head2 Notes
When C<$input> maps to multiple files/buffers and C<$output> is a single
-file/buffer the compressed input files/buffers will all be stored in
-C<$output> as a single compressed stream.
+file/buffer the compressed input files/buffers will all be stored
+in C<$output> as a single compressed stream.
@@ -1807,8 +661,8 @@ L</"Constructor Options"> section below.
=item AutoClose =E<gt> 0|1
-This option applies to any input or output data streams to C<gzip>
-that are filehandles.
+This option applies to any input or output data streams to
+C<gzip> that are filehandles.
If C<AutoClose> is specified, and the value is true, it will result in all
input and/or output filehandles being closed once C<gzip> has
@@ -1818,6 +672,16 @@ This parameter defaults to 0.
+=item BinModeIn =E<gt> 0|1
+
+When reading from a file or filehandle, set C<binmode> before reading.
+
+Defaults to 0.
+
+
+
+
+
=item -Append =E<gt> 0|1
TODO
@@ -1938,9 +802,9 @@ C<OPTS> is any combination of the following options:
=item -AutoClose =E<gt> 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 closed
-once either the C<close> method is called or the C<IO::Compress::Gzip> object is
-destroyed.
+specified, and the value is true, it will result in the C<$output> being
+closed once either the C<close> method is called or the C<IO::Compress::Gzip>
+object is destroyed.
This parameter defaults to 0.
@@ -1948,27 +812,27 @@ This parameter defaults to 0.
Opens C<$output> in append mode.
-The behaviour of this option is dependant on the type of C<$output>.
+The behaviour of this option is dependent on the type of C<$output>.
=over 5
=item * A Buffer
-If C<$output> is a buffer and C<Append> is enabled, all compressed data will be
-append to the end if C<$output>. Otherwise C<$output> will be cleared before
-any data is written to it.
+If C<$output> is a buffer and C<Append> is enabled, all compressed data
+will be append to the end if C<$output>. Otherwise C<$output> will be
+cleared before any data is written to it.
=item * A Filename
-If C<$output> is a filename and C<Append> is enabled, the file will be opened
-in append mode. Otherwise the contents of the file, if any, will be truncated
-before any compressed data is written to it.
+If C<$output> is a filename and C<Append> is enabled, the file will be
+opened in append mode. Otherwise the contents of the file, if any, will be
+truncated before any compressed data is written to it.
=item * A Filehandle
-If C<$output> is a filehandle, the file pointer will be positioned to the end
-of the file via a call to C<seek> before any compressed data is written to it.
-Otherwise the file pointer will not be moved.
+If C<$output> is a filehandle, the file pointer will be positioned to the
+end of the file via a call to C<seek> before any compressed data is written
+to it. Otherwise the file pointer will not be moved.
=back
@@ -1982,8 +846,8 @@ data stream stored in C<$output>.
-It is a fatal error to attempt to use this option when C<$output> is not an RFC
-1952 data stream.
+It is a fatal error to attempt to use this option when C<$output> is not an
+RFC 1952 data stream.
@@ -1993,8 +857,9 @@ There are a number of other limitations with the C<Merge> option:
=item 1
-This module needs to have been built with zlib 1.2.1 or better to work. A fatal
-error will be thrown if C<Merge> is used with an older version of zlib.
+This module needs to have been built with zlib 1.2.1 or better to work. A
+fatal error will be thrown if C<Merge> is used with an older version of
+zlib.
=item 2
@@ -2041,7 +906,7 @@ The default is Z_DEFAULT_STRATEGY.
-=item -Mimimal =E<gt> 0|1
+=item -Minimal =E<gt> 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
@@ -2089,29 +954,29 @@ if this option is not specified.
=item -TextFlag =E<gt> 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 is probably
-text.
+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
+is probably text.
The default is 0.
=item -HeaderCRC =E<gt> 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 except the
-CRC16 field itself.
+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
+except the CRC16 field itself.
-B<Note> that gzip files created with the C<HeaderCRC> flag set to 1 cannot be
-read by most, if not all, of the the standard gunzip utilities, most notably
-gzip version 1.2.4. You should therefore avoid using this option if you want to
-maximise the portability of your gzip files.
+B<Note> that gzip files created with the C<HeaderCRC> flag set to 1 cannot
+be read by most, if not all, of the the standard gunzip utilities, most
+notably gzip version 1.2.4. You should therefore avoid using this option if
+you want to maximize the portability of your gzip files.
This parameter defaults to 0.
=item -OS_Code =E<gt> $value
-Stores C<$value> in the gzip OS header field. A number between 0 and
-255 is valid.
+Stores C<$value> in the gzip OS header field. A number between 0 and 255 is
+valid.
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
@@ -2119,10 +984,10 @@ Unix variants and unknown Operating Systems.
=item -ExtraField =E<gt> $data
-This parameter allows additional metadata to be stored in the ExtraField in the
-gzip header. An RFC1952 compliant ExtraField consists of zero or more
-subfields. Each subfield consists of a two byte header followed by the subfield
-data.
+This parameter allows additional metadata to be stored in the ExtraField in
+the gzip header. An RFC1952 compliant ExtraField consists of zero or more
+subfields. Each subfield consists of a two byte header followed by the
+subfield data.
The list of subfields can be supplied in any of the following formats
@@ -2161,8 +1026,8 @@ The maximum size of the Extra Field 65535 bytes.
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<Level> option.
+If this option is not present, the value stored in XFL field will be
+determined by the setting of the C<Level> option.
If C<Level =E<gt> Z_BEST_SPEED> has been specified then XFL is set to 2.
If C<Level =E<gt> Z_BEST_COMPRESSION> has been specified then XFL is set to 4.
@@ -2179,7 +1044,7 @@ to ensure they are compliant with RFC1952.
This option is enabled by default.
-If C<Strict> is enabled the following behavior will be policed:
+If C<Strict> is enabled the following behaviour will be policed:
=over 5
@@ -2211,7 +1076,7 @@ value 0x00.
=back
-When C<Strict> is disabled the following behavior will be policed:
+When C<Strict> is disabled the following behaviour will be policed:
=over 5
@@ -2261,7 +1126,7 @@ Usage is
print $z $data
Compresses and outputs the contents of the C<$data> parameter. This
-has the same behavior as the C<print> built-in.
+has the same behaviour as the C<print> built-in.
Returns true if successful.
@@ -2424,13 +1289,24 @@ underlying file will also be closed.
-=head2 newStream
+=head2 newStream([OPTS])
Usage is
- $z->newStream
+ $z->newStream( [OPTS] )
-TODO
+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
+
+=item * TODO
+
+=back
=head2 deflateParams
@@ -2540,7 +1416,7 @@ See the Changes file.
=head1 COPYRIGHT AND LICENSE
-Copyright (c) 2005 Paul Marquess. All rights reserved.
+Copyright (c) 2005-2006 Paul Marquess. All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
diff --git a/ext/Compress/Zlib/lib/IO/Compress/RawDeflate.pm b/ext/Compress/Zlib/lib/IO/Compress/RawDeflate.pm
index 096f5e626b..e100ee2b95 100644
--- a/ext/Compress/Zlib/lib/IO/Compress/RawDeflate.pm
+++ b/ext/Compress/Zlib/lib/IO/Compress/RawDeflate.pm
@@ -4,34 +4,243 @@ package IO::Compress::RawDeflate ;
#
use strict ;
use warnings;
-use IO::Uncompress::RawInflate;
+
+
+use IO::Compress::Base;
+use CompressPlugin::Deflate ;
require Exporter ;
+use Compress::Zlib::Common qw(:Status createSelfTiedObject);
-our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $RawDeflateError);
-$VERSION = '2.000_05';
+our ($VERSION, @ISA, @EXPORT_OK, %DEFLATE_CONSTANTS, %EXPORT_TAGS, $RawDeflateError);
+
+$VERSION = '2.000_07';
$RawDeflateError = '';
-@ISA = qw(Exporter IO::BaseDeflate);
+@ISA = qw(Exporter IO::Compress::Base);
@EXPORT_OK = qw( $RawDeflateError rawdeflate ) ;
-%EXPORT_TAGS = %IO::BaseDeflate::EXPORT_TAGS ;
push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
-Exporter::export_ok_tags('all');
+%EXPORT_TAGS = ( flush => [qw{
+ Z_NO_FLUSH
+ Z_PARTIAL_FLUSH
+ Z_SYNC_FLUSH
+ Z_FULL_FLUSH
+ Z_FINISH
+ Z_BLOCK
+ }],
+ level => [qw{
+ Z_NO_COMPRESSION
+ Z_BEST_SPEED
+ Z_BEST_COMPRESSION
+ Z_DEFAULT_COMPRESSION
+ }],
+ strategy => [qw{
+ Z_FILTERED
+ Z_HUFFMAN_ONLY
+ Z_RLE
+ Z_FIXED
+ Z_DEFAULT_STRATEGY
+ }],
+
+ );
+
+{
+ my %seen;
+ foreach (keys %EXPORT_TAGS )
+ {
+ push @{$EXPORT_TAGS{constants}},
+ grep { !$seen{$_}++ }
+ @{ $EXPORT_TAGS{$_} }
+ }
+ $EXPORT_TAGS{all} = $EXPORT_TAGS{constants} ;
+}
+
+%DEFLATE_CONSTANTS = %EXPORT_TAGS;
+
+Exporter::export_ok_tags('all');
+
sub new
{
- my $pkg = shift ;
- return IO::BaseDeflate::new($pkg, 'rfc1951', undef, \$RawDeflateError, @_);
+ my $class = shift ;
+
+ my $obj = createSelfTiedObject($class, \$RawDeflateError);
+
+ return $obj->_create(undef, @_);
}
sub rawdeflate
{
- return IO::BaseDeflate::_def(__PACKAGE__, 'rfc1951', \$RawDeflateError, @_);
+ my $obj = createSelfTiedObject(undef, \$RawDeflateError);
+ return $obj->_def(@_);
+}
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift;
+
+ return 1 ;
+}
+
+sub mkComp
+{
+ my $self = shift ;
+ my $class = shift ;
+ my $got = shift ;
+
+ #return CompressPlugin::Deflate::mkCompObject($self, $class, $got)
+ my ($obj, $errstr, $errno) = CompressPlugin::Deflate::mkCompObject(
+ $got->value('CRC32'),
+ $got->value('Adler32'),
+ $got->value('Level'),
+ $got->value('Strategy')
+ );
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ return $obj;
+}
+
+
+sub mkHeader
+{
+ my $self = shift ;
+ return '';
+}
+
+sub mkTrailer
+{
+ my $self = shift ;
+ return '';
+}
+
+sub mkFinalTrailer
+{
+ return '';
}
+
+#sub newHeader
+#{
+# my $self = shift ;
+# return '';
+#}
+
+sub getExtraParams
+{
+ my $self = shift ;
+ return $self->getZlibParams();
+}
+
+sub getZlibParams
+{
+ my $self = shift ;
+
+ use Compress::Zlib::ParseParameters;
+ use Compress::Zlib qw(Z_DEFLATED Z_DEFAULT_COMPRESSION Z_DEFAULT_STRATEGY);
+
+
+ return (
+
+ # zlib behaviour
+ #'Method' => [0, 1, Parse_unsigned, Z_DEFLATED],
+ 'Level' => [0, 1, Parse_signed, Z_DEFAULT_COMPRESSION],
+ 'Strategy' => [0, 1, Parse_signed, Z_DEFAULT_STRATEGY],
+
+ 'CRC32' => [0, 1, Parse_boolean, 0],
+ 'ADLER32' => [0, 1, Parse_boolean, 0],
+ 'Merge' => [1, 1, Parse_boolean, 0],
+ );
+
+
+}
+
+sub getInverseClass
+{
+ return ('IO::Uncompress::RawInflate',
+ \$IO::Uncompress::RawInflate::RawInflateError);
+}
+
+sub getFileInfo
+{
+ my $self = shift ;
+ my $params = shift;
+ my $file = shift ;
+
+}
+
+use IO::Seekable qw(SEEK_SET);
+
+sub createMerge
+{
+ my $self = shift ;
+ my $outValue = shift ;
+ my $outType = shift ;
+
+ my ($invClass, $error_ref) = $self->getInverseClass();
+ eval "require $invClass"
+ or die "aaaahhhh" ;
+
+ my $inf = $invClass->new( $outValue,
+ Transparent => 0,
+ #Strict => 1,
+ AutoClose => 0,
+ Scan => 1)
+ or return $self->saveErrorString(undef, "Cannot create InflateScan object: $$error_ref" ) ;
+
+ my $end_offset = 0;
+ $inf->scan()
+ or return $self->saveErrorString(undef, "Error Scanning: $$error_ref", $inf->errorNo) ;
+ $inf->zap($end_offset)
+ or return $self->saveErrorString(undef, "Error Zapping: $$error_ref", $inf->errorNo) ;
+
+ my $def = *$self->{Compress} = $inf->createDeflate();
+
+ *$self->{Header} = *$inf->{Info}{Header};
+ *$self->{UnCompSize_32bit} =
+ *$self->{BytesWritten} = *$inf->{UnCompSize_32bit} ;
+
+
+ if ( $outType eq 'buffer')
+ { substr( ${ *$self->{Buffer} }, $end_offset) = '' }
+ elsif ($outType eq 'handle' || $outType eq 'filename') {
+ *$self->{FH} = *$inf->{FH} ;
+ delete *$inf->{FH};
+ *$self->{FH}->flush() ;
+ *$self->{Handle} = 1 if $outType eq 'handle';
+
+ #seek(*$self->{FH}, $end_offset, SEEK_SET)
+ *$self->{FH}->seek($end_offset, SEEK_SET)
+ or return $self->saveErrorString(undef, $!, $!) ;
+ }
+
+ return $def ;
+}
+
+#### zlib specific methods
+
+sub deflateParams
+{
+ my $self = shift ;
+
+ my $level = shift ;
+ my $strategy = shift ;
+
+ my $status = *$self->{Compress}->deflateParams(Level => $level, Strategy => $strategy) ;
+ return $self->saveErrorString(0, *$self->{Compress}{Error}, *$self->{Compress}{ErrorNo})
+ if $status == STATUS_ERROR;
+
+ return 1;
+}
+
+
+
+
1;
__END__
@@ -61,7 +270,7 @@ IO::Compress::RawDeflate - Perl interface to write RFC 1951 files/buffers
$z->seek($position, $whence);
$z->binmode();
$z->fileno();
- $z->newStream();
+ $z->newStream( [OPTS] );
$z->deflateParams();
$z->close() ;
@@ -117,24 +326,25 @@ L<IO::Uncompress::RawInflate|IO::Uncompress::RawInflate>.
=head1 Functional Interface
-A top-level function, C<rawdeflate>, is provided to carry out "one-shot"
-compression between buffers and/or files. For finer control over the compression process, see the L</"OO Interface"> section.
+A top-level function, C<rawdeflate>, is provided to carry out
+"one-shot" compression between buffers and/or files. For finer
+control over the compression process, see the L</"OO Interface">
+section.
use IO::Compress::RawDeflate qw(rawdeflate $RawDeflateError) ;
rawdeflate $input => $output [,OPTS]
or die "rawdeflate failed: $RawDeflateError\n";
- rawdeflate \%hash [,OPTS]
- or die "rawdeflate failed: $RawDeflateError\n";
+
The functional interface needs Perl5.005 or better.
=head2 rawdeflate $input => $output [, OPTS]
-If the first parameter is not a hash reference C<rawdeflate> expects
-at least two parameters, C<$input> and C<$output>.
+
+C<rawdeflate> expects at least two parameters, C<$input> and C<$output>.
=head3 The C<$input> parameter
@@ -164,13 +374,15 @@ from C<$$input>.
=item An array reference
-If C<$input> is an array reference, the input data will be read from each
-element of the array in turn. The action taken by C<rawdeflate> with
-each element of the array will depend on the type of data stored
-in it. You can mix and match any of the types defined in this list,
-excluding other array or hash references.
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
The complete array will be walked to ensure that it only
-contains valid data types before any data is compressed.
+contains valid filenames before any data is compressed.
+
+
=item An Input FileGlob string
@@ -198,36 +410,28 @@ compressed data. This parameter can take one of these forms.
=item A filename
-If the C<$output> parameter is a simple scalar, it is assumed to be a filename.
-This file will be opened for writing and the compressed data will be
-written to it.
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the compressed
+data will be written to it.
=item A filehandle
-If the C<$output> parameter is a filehandle, the compressed data will
-be written to it.
+If the C<$output> parameter is a filehandle, the compressed data
+will be written to it.
The string '-' can be used as an alias for standard output.
=item A scalar reference
-If C<$output> is a scalar reference, the compressed data will be stored
-in C<$$output>.
-
+If C<$output> is a scalar reference, the compressed data will be
+stored in C<$$output>.
-=item A Hash Reference
-
-If C<$output> is a hash reference, the compressed data will be written
-to C<$output{$input}> as a scalar reference.
-
-When C<$output> is a hash reference, C<$input> must be either a filename or
-list of filenames. Anything else is an error.
=item An Array Reference
-If C<$output> is an array reference, the compressed data will be pushed
-onto the array.
+If C<$output> is an array reference, the compressed data will be
+pushed onto the array.
=item An Output FileGlob
@@ -242,60 +446,13 @@ string. Anything else is an error.
If the C<$output> parameter is any other type, C<undef> will be returned.
-=head2 rawdeflate \%hash [, OPTS]
-
-If the first parameter is a hash reference, C<\%hash>, this will be used to
-define both the source of uncompressed data and to control where the
-compressed data is output. Each key/value pair in the hash defines a
-mapping between an input filename, stored in the key, and an output
-file/buffer, stored in the value. Although the input can only be a filename,
-there is more flexibility to control the destination of the compressed
-data. This is determined by the type of the value. Valid types are
-
-=over 5
-
-=item undef
-
-If the value is C<undef> the compressed data will be written to the
-value as a scalar reference.
-
-=item A filename
-
-If the value is a simple scalar, it is assumed to be a filename. This file will
-be opened for writing and the compressed data will be written to it.
-
-=item A filehandle
-
-If the value is a filehandle, the compressed data will be
-written to it.
-The string '-' can be used as an alias for standard output.
-
-
-=item A scalar reference
-
-If the value is a scalar reference, the compressed data will be stored
-in the buffer that is referenced by the scalar.
-
-
-=item A Hash Reference
-
-If the value is a hash reference, the compressed data will be written
-to C<$hash{$input}> as a scalar reference.
-
-=item An Array Reference
-
-If C<$output> is an array reference, the compressed data will be pushed
-onto the array.
-
-=back
-Any other type is a error.
=head2 Notes
When C<$input> maps to multiple files/buffers and C<$output> is a single
-file/buffer the compressed input files/buffers will all be stored in
-C<$output> as a single compressed stream.
+file/buffer the compressed input files/buffers will all be stored
+in C<$output> as a single compressed stream.
@@ -309,8 +466,8 @@ L</"Constructor Options"> section below.
=item AutoClose =E<gt> 0|1
-This option applies to any input or output data streams to C<rawdeflate>
-that are filehandles.
+This option applies to any input or output data streams to
+C<rawdeflate> that are filehandles.
If C<AutoClose> is specified, and the value is true, it will result in all
input and/or output filehandles being closed once C<rawdeflate> has
@@ -320,6 +477,16 @@ This parameter defaults to 0.
+=item BinModeIn =E<gt> 0|1
+
+When reading from a file or filehandle, set C<binmode> before reading.
+
+Defaults to 0.
+
+
+
+
+
=item -Append =E<gt> 0|1
TODO
@@ -440,9 +607,9 @@ C<OPTS> is any combination of the following options:
=item -AutoClose =E<gt> 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 closed
-once either the C<close> method is called or the C<IO::Compress::RawDeflate> object is
-destroyed.
+specified, and the value is true, it will result in the C<$output> being
+closed once either the C<close> method is called or the C<IO::Compress::RawDeflate>
+object is destroyed.
This parameter defaults to 0.
@@ -450,27 +617,27 @@ This parameter defaults to 0.
Opens C<$output> in append mode.
-The behaviour of this option is dependant on the type of C<$output>.
+The behaviour of this option is dependent on the type of C<$output>.
=over 5
=item * A Buffer
-If C<$output> is a buffer and C<Append> is enabled, all compressed data will be
-append to the end if C<$output>. Otherwise C<$output> will be cleared before
-any data is written to it.
+If C<$output> is a buffer and C<Append> is enabled, all compressed data
+will be append to the end if C<$output>. Otherwise C<$output> will be
+cleared before any data is written to it.
=item * A Filename
-If C<$output> is a filename and C<Append> is enabled, the file will be opened
-in append mode. Otherwise the contents of the file, if any, will be truncated
-before any compressed data is written to it.
+If C<$output> is a filename and C<Append> is enabled, the file will be
+opened in append mode. Otherwise the contents of the file, if any, will be
+truncated before any compressed data is written to it.
=item * A Filehandle
-If C<$output> is a filehandle, the file pointer will be positioned to the end
-of the file via a call to C<seek> before any compressed data is written to it.
-Otherwise the file pointer will not be moved.
+If C<$output> is a filehandle, the file pointer will be positioned to the
+end of the file via a call to C<seek> before any compressed data is written
+to it. Otherwise the file pointer will not be moved.
=back
@@ -484,8 +651,8 @@ data stream stored in C<$output>.
-It is a fatal error to attempt to use this option when C<$output> is not an RFC
-1951 data stream.
+It is a fatal error to attempt to use this option when C<$output> is not an
+RFC 1951 data stream.
@@ -495,8 +662,9 @@ There are a number of other limitations with the C<Merge> option:
=item 1
-This module needs to have been built with zlib 1.2.1 or better to work. A fatal
-error will be thrown if C<Merge> is used with an older version of zlib.
+This module needs to have been built with zlib 1.2.1 or better to work. A
+fatal error will be thrown if C<Merge> is used with an older version of
+zlib.
=item 2
@@ -567,7 +735,7 @@ Usage is
print $z $data
Compresses and outputs the contents of the C<$data> parameter. This
-has the same behavior as the C<print> built-in.
+has the same behaviour as the C<print> built-in.
Returns true if successful.
@@ -730,13 +898,24 @@ underlying file will also be closed.
-=head2 newStream
+=head2 newStream([OPTS])
Usage is
- $z->newStream
+ $z->newStream( [OPTS] )
-TODO
+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
+
+=item * TODO
+
+=back
=head2 deflateParams
@@ -846,7 +1025,7 @@ See the Changes file.
=head1 COPYRIGHT AND LICENSE
-Copyright (c) 2005 Paul Marquess. All rights reserved.
+Copyright (c) 2005-2006 Paul Marquess. All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
diff --git a/ext/Compress/Zlib/lib/IO/Compress/Zip.pm b/ext/Compress/Zlib/lib/IO/Compress/Zip.pm
new file mode 100644
index 0000000000..87b61f49df
--- /dev/null
+++ b/ext/Compress/Zlib/lib/IO/Compress/Zip.pm
@@ -0,0 +1,290 @@
+package IO::Compress::Zip ;
+
+use strict ;
+use warnings;
+
+use Compress::Zlib::Common qw(createSelfTiedObject);
+use CompressPlugin::Deflate;
+use CompressPlugin::Identity;
+use IO::Compress::RawDeflate;
+
+require Exporter ;
+
+our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $ZipError);
+
+$VERSION = '2.000_04';
+$ZipError = '';
+
+@ISA = qw(Exporter IO::Compress::RawDeflate);
+@EXPORT_OK = qw( $ZipError zip ) ;
+%EXPORT_TAGS = %IO::Compress::RawDeflate::DEFLATE_CONSTANTS ;
+push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
+Exporter::export_ok_tags('all');
+
+
+sub new
+{
+ my $class = shift ;
+
+ my $obj = createSelfTiedObject($class, \$ZipError);
+ $obj->_create(undef, @_);
+}
+
+sub zip
+{
+ my $obj = createSelfTiedObject(undef, \$ZipError);
+ return $obj->_def(@_);
+}
+
+sub mkComp
+{
+ my $self = shift ;
+ my $class = shift ;
+ my $got = shift ;
+
+ my ($obj, $errstr, $errno) ;
+
+ if (*$self->{ZipData}{Store}) {
+ #return CompressPlugin::Deflate::mkCompObject($self, $class, $got)
+ ($obj, $errstr, $errno) = CompressPlugin::Identity::mkCompObject(
+ $got->value('CRC32'),
+ $got->value('Adler32'),
+ $got->value('Level'),
+ $got->value('Strategy')
+ );
+ }
+ else {
+ #return CompressPlugin::Deflate::mkCompObject($self, $class, $got)
+ ($obj, $errstr, $errno) = CompressPlugin::Deflate::mkCompObject(
+ $got->value('CRC32'),
+ $got->value('Adler32'),
+ $got->value('Level'),
+ $got->value('Strategy')
+ );
+ }
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ return $obj;
+}
+
+
+
+sub mkHeader
+{
+ my $self = shift;
+ my $param = shift ;
+
+ my $filename = '';
+ $filename = $param->value('Name') || '';
+
+ my $comment = '';
+ $comment = $param->value('Comment') || '';
+
+ my $extract = $param->value('OS_Code') << 8 + 20 ;
+ my $hdr = '';
+
+ my $time = _unixToDosTime($param->value('Time'));
+ *$self->{ZipData}{StartOffset} = *$self->{ZipData}{Offset} ;
+
+ my $strm = *$self->{ZipData}{Stream} ? 8 : 0 ;
+ my $method = *$self->{ZipData}{Store} ? 0 : 8 ;
+
+ $hdr .= pack "V", 0x04034b50 ; # signature
+ $hdr .= pack 'v', $extract ; # extract Version & OS
+ $hdr .= pack 'v', $strm ; # general purpose flag (set streaming mode)
+ $hdr .= pack 'v', $method ; # compression method (deflate)
+ $hdr .= pack 'V', $time ; # last mod date/time
+ $hdr .= pack 'V', 0 ; # crc32 - 0 when streaming
+ $hdr .= pack 'V', 0 ; # compressed length - 0 when streaming
+ $hdr .= pack 'V', 0 ; # uncompressed length - 0 when streaming
+ $hdr .= pack 'v', length $filename ; # filename length
+ $hdr .= pack 'v', 0 ; # extra length
+
+ $hdr .= $filename ;
+
+
+ my $ctl = '';
+
+ $ctl .= pack "V", 0x02014b50 ; # signature
+ $ctl .= pack 'v', $extract ; # version made by
+ $ctl .= pack 'v', $extract ; # extract Version
+ $ctl .= pack 'v', $strm ; # general purpose flag (streaming mode)
+ $ctl .= pack 'v', $method ; # compression method (deflate)
+ $ctl .= pack 'V', $time ; # last mod date/time
+ $ctl .= pack 'V', 0 ; # crc32
+ $ctl .= pack 'V', 0 ; # compressed length
+ $ctl .= pack 'V', 0 ; # uncompressed length
+ $ctl .= pack 'v', length $filename ; # filename length
+ $ctl .= pack 'v', 0 ; # extra length
+ $ctl .= pack 'v', length $comment ; # file comment length
+ $ctl .= pack 'v', 0 ; # disk number start
+ $ctl .= pack 'v', 0 ; # internal file attributes
+ $ctl .= pack 'V', 0 ; # external file attributes
+ $ctl .= pack 'V', *$self->{ZipData}{Offset} ; # offset to local header
+
+ $ctl .= $filename ;
+ #$ctl .= $extra ;
+ $ctl .= $comment ;
+
+ *$self->{ZipData}{Offset} += length $hdr ;
+
+ *$self->{ZipData}{CentralHeader} = $ctl;
+
+ return $hdr;
+}
+
+sub mkTrailer
+{
+ my $self = shift ;
+
+ my $crc32 = *$self->{Compress}->crc32();
+ my $compressedBytes = *$self->{Compress}->compressedBytes();
+ my $uncompressedBytes = *$self->{Compress}->uncompressedBytes();
+
+ my $data ;
+ $data .= pack "V", $crc32 ; # CRC32
+ $data .= pack "V", $compressedBytes ; # Compressed Size
+ $data .= pack "V", $uncompressedBytes; # Uncompressed Size
+
+ my $hdr = '';
+
+ if (*$self->{ZipData}{Stream}) {
+ $hdr = pack "V", 0x08074b50 ; # signature
+ $hdr .= $data ;
+ }
+ else {
+ $self->writeAt(*$self->{ZipData}{StartOffset} + 14, $data)
+ or return undef;
+ }
+
+ my $ctl = *$self->{ZipData}{CentralHeader} ;
+ substr($ctl, 16, 12) = $data ;
+ #substr($ctl, 16, 4) = pack "V", $crc32 ; # CRC32
+ #substr($ctl, 20, 4) = pack "V", $compressedBytes ; # Compressed Size
+ #substr($ctl, 24, 4) = pack "V", $uncompressedBytes ; # Uncompressed Size
+
+ *$self->{ZipData}{Offset} += length($hdr) + $compressedBytes;
+ push @{ *$self->{ZipData}{CentralDir} }, $ctl ;
+
+ return $hdr;
+}
+
+sub mkFinalTrailer
+{
+ my $self = shift ;
+
+ my $entries = @{ *$self->{ZipData}{CentralDir} };
+ my $cd = join '', @{ *$self->{ZipData}{CentralDir} };
+
+ my $ecd = '';
+ $ecd .= pack "V", 0x06054b50 ; # signature
+ $ecd .= pack 'v', 0 ; # number of disk
+ $ecd .= pack 'v', 0 ; # number if 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', 0 ; # zipfile comment length
+ #$ecd .= $comment;
+
+ return $cd . $ecd ;
+}
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift;
+
+ $got->value('CRC32' => 1);
+
+ if (! $got->parsed('Time') ) {
+ # Modification time defaults to now.
+ $got->value('Time' => time) ;
+ }
+
+ *$self->{ZipData}{Stream} = $got->value('Stream');
+ *$self->{ZipData}{Store} = $got->value('Store');
+ *$self->{ZipData}{StartOffset} = *$self->{ZipData}{Offset} = 0;
+
+ return 1 ;
+}
+
+#sub newHeader
+#{
+# my $self = shift ;
+#
+# return $self->mkHeader(*$self->{Got});
+#}
+
+sub getExtraParams
+{
+ my $self = shift ;
+
+ use Compress::Zlib::ParseParameters;
+ use Compress::Zlib qw(Z_DEFLATED Z_DEFAULT_COMPRESSION Z_DEFAULT_STRATEGY);
+
+
+ return (
+ # zlib behaviour
+ $self->getZlibParams(),
+
+ 'Stream' => [1, 1, Parse_boolean, 1],
+ 'Store' => [0, 1, Parse_boolean, 0],
+
+# # Zip header fields
+# 'Minimal' => [0, 1, Parse_boolean, 0],
+ 'Comment' => [0, 1, Parse_any, undef],
+ 'ZipComment'=> [0, 1, Parse_any, undef],
+ 'Name' => [0, 1, Parse_any, undef],
+ 'Time' => [0, 1, Parse_any, undef],
+ 'OS_Code' => [0, 1, Parse_unsigned, $Compress::Zlib::gzip_os_code],
+
+# 'TextFlag' => [0, 1, Parse_boolean, 0],
+# 'ExtraField'=> [0, 1, Parse_string, undef],
+ );
+}
+
+sub getInverseClass
+{
+ return ('IO::Uncompress::Unzip',
+ \$IO::Uncompress::Unzip::UnzipError);
+}
+
+sub getFileInfo
+{
+ my $self = shift ;
+ my $params = shift;
+ my $filename = shift ;
+
+ my $defaultTime = (stat($filename))[9] ;
+
+ $params->value('Name' => $filename)
+ if ! $params->parsed('Name') ;
+
+ $params->value('Time' => $defaultTime)
+ if ! $params->parsed('Time') ;
+
+
+}
+
+# from Archive::Zip
+sub _unixToDosTime # Archive::Zip::Member
+{
+ my $time_t = shift;
+ # TODO - add something to cope with unix time < 1980
+ my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime($time_t);
+ my $dt = 0;
+ $dt += ( $sec >> 1 );
+ $dt += ( $min << 5 );
+ $dt += ( $hour << 11 );
+ $dt += ( $mday << 16 );
+ $dt += ( ( $mon + 1 ) << 21 );
+ $dt += ( ( $year - 80 ) << 25 );
+ return $dt;
+}
+
+1;
+
+__END__
diff --git a/ext/Compress/Zlib/lib/IO/Uncompress/AnyInflate.pm b/ext/Compress/Zlib/lib/IO/Uncompress/AnyInflate.pm
index 0ec9bd2ee5..12f592be00 100644
--- a/ext/Compress/Zlib/lib/IO/Uncompress/AnyInflate.pm
+++ b/ext/Compress/Zlib/lib/IO/Uncompress/AnyInflate.pm
@@ -4,35 +4,117 @@ package IO::Uncompress::AnyInflate ;
use strict;
use warnings;
+
+use Compress::Zlib::Common qw(createSelfTiedObject);
+
+use UncompressPlugin::Inflate ();
+#use UncompressPlugin::Bunzip2 ();
+
+
+#use IO::Uncompress::Base ;
use IO::Uncompress::Gunzip ;
+use IO::Uncompress::Inflate ;
+use IO::Uncompress::RawInflate ;
+use IO::Uncompress::Unzip ;
+#use IO::Uncompress::Bunzip2 ;
+#use IO::Uncompress::UnLzop ;
require Exporter ;
our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $AnyInflateError);
-$VERSION = '2.000_05';
+$VERSION = '2.000_07';
$AnyInflateError = '';
-@ISA = qw(Exporter IO::BaseInflate);
+@ISA = qw( Exporter IO::Uncompress::Base );
@EXPORT_OK = qw( $AnyInflateError anyinflate ) ;
-%EXPORT_TAGS = %IO::BaseInflate::EXPORT_TAGS ;
+%EXPORT_TAGS = %IO::Uncompress::Base::DEFLATE_CONSTANTS ;
push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
Exporter::export_ok_tags('all');
-
-
# TODO - allow the user to pick a set of the three formats to allow
# or just assume want to auto-detect any of the three formats.
sub new
{
- my $pkg = shift ;
- return IO::BaseInflate::new($pkg, 'any', undef, \$AnyInflateError, 0, @_);
+ my $class = shift ;
+ my $obj = createSelfTiedObject($class, \$AnyInflateError);
+ $obj->_create(undef, 0, @_);
}
sub anyinflate
{
- return IO::BaseInflate::_inf(__PACKAGE__, 'any', \$AnyInflateError, @_) ;
+ my $obj = createSelfTiedObject(undef, \$AnyInflateError);
+ return $obj->_inf(@_) ;
+}
+
+sub getExtraParams
+{
+ return ();
+}
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ # any always needs both crc32 and adler32
+ $got->value('CRC32' => 1);
+ $got->value('ADLER32' => 1);
+
+ return 1;
+}
+
+sub mkUncomp
+{
+ my $self = shift ;
+ my $class = shift ;
+ my $got = shift ;
+
+ my ($obj, $errstr, $errno) = UncompressPlugin::Inflate::mkUncompObject();
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ *$self->{Uncomp} = $obj;
+
+ my $magic = $self->ckMagic( qw( RawInflate Inflate Gunzip Unzip ) );
+
+ if ($magic) {
+ *$self->{Info} = $self->readHeader($magic)
+ or return undef ;
+
+ return 1;
+ }
+
+ return 0 ;
+}
+
+
+
+sub ckMagic
+{
+ my $self = shift;
+ my @names = @_ ;
+
+ my $keep = ref $self ;
+ for my $class ( map { "IO::Uncompress::$_" } @names)
+ {
+ bless $self => $class;
+ my $magic = $self->ckMagic();
+
+ if ($magic)
+ {
+ #bless $self => $class;
+ return $magic ;
+ }
+
+ $self->pushBack(*$self->{HeaderPending}) ;
+ *$self->{HeaderPending} = '' ;
+ }
+
+ bless $self => $keep;
+ return undef;
}
1 ;
@@ -108,34 +190,35 @@ B<WARNING -- This is a Beta release>.
-This module provides a Perl interface that allows the reading of files/buffers
-that conform to RFC's 1950, 1951 and 1952.
+This module provides a Perl interface that allows the reading of
+files/buffers that conform to RFC's 1950, 1951 and 1952.
-The module will auto-detect which, if any, of the three supported compression
-formats is being used.
+The module will auto-detect which, if any, of the three supported
+compression formats is being used.
=head1 Functional Interface
-A top-level function, C<anyinflate>, is provided to carry out "one-shot"
-uncompression between buffers and/or files. For finer control over the uncompression process, see the L</"OO Interface"> section.
+A top-level function, C<anyinflate>, is provided to carry out
+"one-shot" uncompression between buffers and/or files. For finer
+control over the uncompression process, see the L</"OO Interface">
+section.
use IO::Uncompress::AnyInflate qw(anyinflate $AnyInflateError) ;
anyinflate $input => $output [,OPTS]
or die "anyinflate failed: $AnyInflateError\n";
- anyinflate \%hash [,OPTS]
- or die "anyinflate failed: $AnyInflateError\n";
+
The functional interface needs Perl5.005 or better.
=head2 anyinflate $input => $output [, OPTS]
-If the first parameter is not a hash reference C<anyinflate> expects
-at least two parameters, C<$input> and C<$output>.
+
+C<anyinflate> expects at least two parameters, C<$input> and C<$output>.
=head3 The C<$input> parameter
@@ -165,13 +248,15 @@ from C<$$input>.
=item An array reference
-If C<$input> is an array reference, the input data will be read from each
-element of the array in turn. The action taken by C<anyinflate> with
-each element of the array will depend on the type of data stored
-in it. You can mix and match any of the types defined in this list,
-excluding other array or hash references.
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
The complete array will be walked to ensure that it only
-contains valid data types before any data is uncompressed.
+contains valid filenames before any data is uncompressed.
+
+
=item An Input FileGlob string
@@ -199,36 +284,28 @@ uncompressed data. This parameter can take one of these forms.
=item A filename
-If the C<$output> parameter is a simple scalar, it is assumed to be a filename.
-This file will be opened for writing and the uncompressed data will be
-written to it.
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the uncompressed
+data will be written to it.
=item A filehandle
-If the C<$output> parameter is a filehandle, the uncompressed data will
-be written to it.
+If the C<$output> parameter is a filehandle, the uncompressed data
+will be written to it.
The string '-' can be used as an alias for standard output.
=item A scalar reference
-If C<$output> is a scalar reference, the uncompressed data will be stored
-in C<$$output>.
-
-
-=item A Hash Reference
-
-If C<$output> is a hash reference, the uncompressed data will be written
-to C<$output{$input}> as a scalar reference.
+If C<$output> is a scalar reference, the uncompressed data will be
+stored in C<$$output>.
-When C<$output> is a hash reference, C<$input> must be either a filename or
-list of filenames. Anything else is an error.
=item An Array Reference
-If C<$output> is an array reference, the uncompressed data will be pushed
-onto the array.
+If C<$output> is an array reference, the uncompressed data will be
+pushed onto the array.
=item An Output FileGlob
@@ -243,60 +320,13 @@ string. Anything else is an error.
If the C<$output> parameter is any other type, C<undef> will be returned.
-=head2 anyinflate \%hash [, OPTS]
-If the first parameter is a hash reference, C<\%hash>, this will be used to
-define both the source of compressed data and to control where the
-uncompressed data is output. Each key/value pair in the hash defines a
-mapping between an input filename, stored in the key, and an output
-file/buffer, stored in the value. Although the input can only be a filename,
-there is more flexibility to control the destination of the uncompressed
-data. This is determined by the type of the value. Valid types are
-
-=over 5
-
-=item undef
-
-If the value is C<undef> the uncompressed data will be written to the
-value as a scalar reference.
-
-=item A filename
-
-If the value is a simple scalar, it is assumed to be a filename. This file will
-be opened for writing and the uncompressed data will be written to it.
-
-=item A filehandle
-
-If the value is a filehandle, the uncompressed data will be
-written to it.
-The string '-' can be used as an alias for standard output.
-
-
-=item A scalar reference
-
-If the value is a scalar reference, the uncompressed data will be stored
-in the buffer that is referenced by the scalar.
-
-
-=item A Hash Reference
-
-If the value is a hash reference, the uncompressed data will be written
-to C<$hash{$input}> as a scalar reference.
-
-=item An Array Reference
-
-If C<$output> is an array reference, the uncompressed data will be pushed
-onto the array.
-
-=back
-
-Any other type is a error.
=head2 Notes
When C<$input> maps to multiple files/buffers and C<$output> is a single
-file/buffer the uncompressed input files/buffers will all be stored in
-C<$output> as a single uncompressed stream.
+file/buffer the uncompressed input files/buffers will all be stored
+in C<$output> as a single uncompressed stream.
@@ -310,8 +340,8 @@ L</"Constructor Options"> section below.
=item AutoClose =E<gt> 0|1
-This option applies to any input or output data streams to C<anyinflate>
-that are filehandles.
+This option applies to any input or output data streams to
+C<anyinflate> that are filehandles.
If C<AutoClose> is specified, and the value is true, it will result in all
input and/or output filehandles being closed once C<anyinflate> has
@@ -321,10 +351,27 @@ This parameter defaults to 0.
+=item BinModeOut =E<gt> 0|1
+
+When writing to a file or filehandle, set C<binmode> before writing to the
+file.
+
+Defaults to 0.
+
+
+
+
+
=item -Append =E<gt> 0|1
TODO
+=item -MultiStream =E<gt> 0|1
+
+Creates a new stream after each file.
+
+Defaults to 1.
+
=back
@@ -397,11 +444,11 @@ The format of the constructor for IO::Uncompress::AnyInflate is shown below
Returns an C<IO::Uncompress::AnyInflate> object on success and undef on failure.
The variable C<$AnyInflateError> will contain an error message on failure.
-If you are running Perl 5.005 or better the object, C<$z>, returned from
-IO::Uncompress::AnyInflate can be used exactly like an L<IO::File|IO::File> filehandle.
-This means that all normal input file operations can be carried out with C<$z>.
-For example, to read a line from a compressed file/buffer you can use either
-of these forms
+If you are running Perl 5.005 or better the object, C<$z>, returned from
+IO::Uncompress::AnyInflate can be used exactly like an L<IO::File|IO::File> filehandle.
+This means that all normal input file operations can be carried out with
+C<$z>. For example, to read a line from a compressed file/buffer you can
+use either of these forms
$line = $z->getline();
$line = <$z>;
@@ -475,8 +522,9 @@ input file/buffer.
This option can be useful when the compressed data is embedded in another
file/data structure and it is not possible to work out where the compressed
-data begins without having to read the first few bytes. If this is the case,
-the uncompression can be I<primed> with these bytes using this option.
+data begins without having to read the first few bytes. If this is the
+case, the uncompression can be I<primed> with these bytes using this
+option.
=item -Transparent =E<gt> 0|1
@@ -487,20 +535,21 @@ This option defaults to 1.
=item -BlockSize =E<gt> $num
-When reading the compressed input data, IO::Uncompress::AnyInflate will read it in blocks
-of C<$num> bytes.
+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<gt> $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 situation
-where there is useful data directly after the compressed data stream and you
-know beforehand the exact length of the compressed data stream.
+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
+situation where there is useful data directly after the compressed data
+stream and you know beforehand the exact length of the compressed data
+stream.
-This option is mostly used when reading from a filehandle, in which case the
-file pointer will be left pointing to the first byte directly after the
+This option is mostly used when reading from a filehandle, in which case
+the file pointer will be left pointing to the first byte directly after the
compressed data stream.
@@ -511,11 +560,11 @@ This option defaults to off.
This option controls what the C<read> method does with uncompressed data.
-If set to 1, all uncompressed data will be appended to the output parameter of
-the C<read> method.
+If set to 1, all uncompressed data will be appended to the output parameter
+of the C<read> method.
-If set to 0, the contents of the output parameter of the C<read> method will be
-overwritten by the uncompressed data.
+If set to 0, the contents of the output parameter of the C<read> method
+will be overwritten by the uncompressed data.
Defaults to 0.
@@ -524,8 +573,8 @@ Defaults to 0.
This option controls whether the extra checks defined below are used when
-carrying out the decompression. When Strict is on, the extra tests are carried
-out, when Strict is off they are not.
+carrying out the decompression. When Strict is on, the extra tests are
+carried out, when Strict is off they are not.
The default for this option is off.
@@ -569,8 +618,8 @@ If the gzip header contains a name field (FNAME) it consists solely of ISO
=item 3
-If the gzip header contains a comment field (FCOMMENT) it consists solely of
-ISO 8859-1 characters plus line-feed.
+If the gzip header contains a comment field (FCOMMENT) it consists solely
+of ISO 8859-1 characters plus line-feed.
=item 4
@@ -588,8 +637,8 @@ uncompressed data actually contained in the gzip file.
=item 7
-The value of the ISIZE fields read must match the length of the uncompressed
-data actually read from the file.
+The value of the ISIZE fields read must match the length of the
+uncompressed data actually read from the file.
=back
@@ -626,12 +675,12 @@ Usage is
Reads a block of compressed data (the size the the compressed block is
determined by the C<Buffer> option in the constructor), uncompresses it and
-writes any uncompressed data into C<$buffer>. If the C<Append> parameter is set
-in the constructor, the uncompressed data will be appended to the C<$buffer>
-parameter. Otherwise C<$buffer> will be overwritten.
+writes any uncompressed data into C<$buffer>. If the C<Append> parameter is
+set in the constructor, the uncompressed data will be appended to the
+C<$buffer> parameter. Otherwise C<$buffer> will be overwritten.
-Returns the number of uncompressed bytes written to C<$buffer>, zero if eof or
-a negative number on error.
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
=head2 read
@@ -645,13 +694,13 @@ Usage is
Attempt to read C<$length> bytes of uncompressed data into C<$buffer>.
-The main difference between this form of the C<read> method and the previous
-one, is that this one will attempt to return I<exactly> C<$length> bytes. The
-only circumstances that this function will not is if end-of-file or an IO error
-is encountered.
+The main difference between this form of the C<read> method and the
+previous one, is that this one will attempt to return I<exactly> C<$length>
+bytes. The only circumstances that this function will not is if end-of-file
+or an IO error is encountered.
-Returns the number of uncompressed bytes written to C<$buffer>, zero if eof or
-a negative number on error.
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
=head2 getline
@@ -696,14 +745,12 @@ TODO
Usage is
- $hdr = $z->getHeaderInfo()
-
-TODO
-
-
-
-
+ $hdr = $z->getHeaderInfo();
+ @hdrs = $z->getHeaderInfo();
+This method returns either a hash reference (in scalar context) or a list
+or hash references (in array context) that contains information about each
+of the header fields in the compressed data stream(s).
@@ -856,7 +903,7 @@ See the Changes file.
=head1 COPYRIGHT AND LICENSE
-Copyright (c) 2005 Paul Marquess. All rights reserved.
+Copyright (c) 2005-2006 Paul Marquess. All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
diff --git a/ext/Compress/Zlib/lib/IO/Uncompress/AnyUncompress.pm b/ext/Compress/Zlib/lib/IO/Uncompress/AnyUncompress.pm
new file mode 100644
index 0000000000..9e3708bd22
--- /dev/null
+++ b/ext/Compress/Zlib/lib/IO/Uncompress/AnyUncompress.pm
@@ -0,0 +1,156 @@
+package IO::Uncompress::AnyUncompress ;
+
+use strict;
+use warnings;
+
+use Compress::Zlib::Common qw(createSelfTiedObject);
+
+#use IO::Uncompress::Base ;
+use IO::Uncompress::Gunzip ;
+use IO::Uncompress::Inflate ;
+use IO::Uncompress::RawInflate ;
+use IO::Uncompress::Unzip ;
+
+BEGIN
+{
+ eval { require UncompressPlugin::Bunzip2; import UncompressPlugin::Bunzip2 };
+ eval { require UncompressPlugin::LZO; import UncompressPlugin::LZO };
+ eval { require IO::Uncompress::Bunzip2; import IO::Uncompress::Bunzip2 };
+ eval { require IO::Uncompress::UnLzop; import IO::Uncompress::UnLzop };
+}
+
+require Exporter ;
+
+our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $AnyUncompressError);
+
+$VERSION = '2.000_05';
+$AnyUncompressError = '';
+
+@ISA = qw( Exporter IO::Uncompress::Base );
+@EXPORT_OK = qw( $AnyUncompressError anyuncompress ) ;
+%EXPORT_TAGS = %IO::Uncompress::Base::DEFLATE_CONSTANTS ;
+push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
+Exporter::export_ok_tags('all');
+
+# TODO - allow the user to pick a set of the three formats to allow
+# or just assume want to auto-detect any of the three formats.
+
+sub new
+{
+ my $class = shift ;
+ my $obj = createSelfTiedObject($class, \$AnyUncompressError);
+ $obj->_create(undef, 0, @_);
+}
+
+sub anyuncompress
+{
+ my $obj = createSelfTiedObject(undef, \$AnyUncompressError);
+ return $obj->_inf(@_) ;
+}
+
+sub getExtraParams
+{
+ return ();
+}
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ # any always needs both crc32 and adler32
+ $got->value('CRC32' => 1);
+ $got->value('ADLER32' => 1);
+
+ return 1;
+}
+
+sub mkUncomp
+{
+ my $self = shift ;
+ my $class = shift ;
+ my $got = shift ;
+
+ # try zlib first
+ my ($obj, $errstr, $errno) = UncompressPlugin::Inflate::mkUncompObject();
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ *$self->{Uncomp} = $obj;
+
+ my $magic = $self->ckMagic( qw( RawInflate Inflate Gunzip Unzip ) );
+
+ if ($magic) {
+ *$self->{Info} = $self->readHeader($magic)
+ or return undef ;
+
+ return 1;
+ }
+
+ #foreach my $type ( qw( Bunzip2 UnLzop ) ) {
+ if (defined $IO::Uncompress::Bunzip2::VERSION and
+ $magic = $self->ckMagic('Bunzip2')) {
+ *$self->{Info} = $self->readHeader($magic)
+ or return undef ;
+
+ my ($obj, $errstr, $errno) = UncompressPlugin::Bunzip2::mkUncompObject();
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ *$self->{Uncomp} = $obj;
+
+ return 1;
+ }
+ elsif (defined $IO::Uncompress::UnLzop::VERSION and
+ $magic = $self->ckMagic('UnLzop')) {
+
+ *$self->{Info} = $self->readHeader($magic)
+ or return undef ;
+
+ my ($obj, $errstr, $errno) = UncompressPlugin::LZO::mkUncompObject();
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ *$self->{Uncomp} = $obj;
+
+ return 1;
+ }
+
+ return 0 ;
+}
+
+
+
+sub ckMagic
+{
+ my $self = shift;
+ my @names = @_ ;
+
+ my $keep = ref $self ;
+ for my $class ( map { "IO::Uncompress::$_" } @names)
+ {
+ bless $self => $class;
+ my $magic = $self->ckMagic();
+
+ if ($magic)
+ {
+ #bless $self => $class;
+ return $magic ;
+ }
+
+ $self->pushBack(*$self->{HeaderPending}) ;
+ *$self->{HeaderPending} = '' ;
+ }
+
+ bless $self => $keep;
+ return undef;
+}
+
+1 ;
+
+__END__
+
+
diff --git a/ext/Compress/Zlib/lib/IO/Uncompress/Base.pm b/ext/Compress/Zlib/lib/IO/Uncompress/Base.pm
new file mode 100644
index 0000000000..db21ab0bfc
--- /dev/null
+++ b/ext/Compress/Zlib/lib/IO/Uncompress/Base.pm
@@ -0,0 +1,1250 @@
+
+package IO::Uncompress::Base ;
+
+use strict ;
+use warnings;
+use bytes;
+
+our ($VERSION, @EXPORT_OK, %EXPORT_TAGS);
+
+$VERSION = '2.000_05';
+
+use constant G_EOF => 0 ;
+use constant G_ERR => -1 ;
+
+use Compress::Zlib::Common ;
+use Compress::Zlib::ParseParameters ;
+
+use IO::File ;
+use Symbol;
+use Scalar::Util qw(readonly);
+use List::Util qw(min);
+use Carp ;
+
+%EXPORT_TAGS = ( );
+push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
+#Exporter::export_ok_tags('all') ;
+
+
+sub smartRead
+{
+ my $self = $_[0];
+ my $out = $_[1];
+ my $size = $_[2];
+ $$out = "" ;
+
+ my $offset = 0 ;
+
+
+ if ( length *$self->{Prime} ) {
+ #$$out = substr(*$self->{Prime}, 0, $size, '') ;
+ $$out = substr(*$self->{Prime}, 0, $size) ;
+ substr(*$self->{Prime}, 0, $size) = '' ;
+ if (length $$out == $size) {
+ #*$self->{InputLengthRemaining} -= length $$out;
+ return length $$out ;
+ }
+ $offset = length $$out ;
+ }
+
+ my $get_size = $size - $offset ;
+
+ if ( defined *$self->{InputLength} ) {
+ #*$self->{InputLengthRemaining} += length *$self->{Prime} ;
+ #*$self->{InputLengthRemaining} = *$self->{InputLength}
+ # if *$self->{InputLengthRemaining} > *$self->{InputLength};
+ $get_size = min($get_size, *$self->{InputLengthRemaining});
+ }
+
+ if (defined *$self->{FH})
+ { *$self->{FH}->read($$out, $get_size, $offset) }
+ elsif (defined *$self->{InputEvent}) {
+ my $got = 1 ;
+ while (length $$out < $size) {
+ last
+ if ($got = *$self->{InputEvent}->($$out, $get_size)) <= 0;
+ }
+
+ if (length $$out > $size ) {
+ #*$self->{Prime} = substr($$out, $size, length($$out), '');
+ *$self->{Prime} = substr($$out, $size, length($$out));
+ substr($$out, $size, length($$out)) = '';
+ }
+
+ *$self->{EventEof} = 1 if $got <= 0 ;
+ }
+ else {
+ no warnings 'uninitialized';
+ my $buf = *$self->{Buffer} ;
+ $$buf = '' unless defined $$buf ;
+ #$$out = '' unless defined $$out ;
+ substr($$out, $offset) = substr($$buf, *$self->{BufferOffset}, $get_size);
+ *$self->{BufferOffset} += length($$out) - $offset ;
+ }
+
+ *$self->{InputLengthRemaining} -= length $$out;
+
+ $self->saveStatus(length $$out < 0 ? STATUS_ERROR : 0) ;
+
+ return length $$out;
+}
+
+sub pushBack
+{
+ my $self = shift ;
+
+ return if ! defined $_[0] || length $_[0] == 0 ;
+
+ if (defined *$self->{FH} || defined *$self->{InputEvent} ) {
+ *$self->{Prime} = $_[0] . *$self->{Prime} ;
+ }
+ else {
+ my $len = length $_[0];
+
+ if($len > *$self->{BufferOffset}) {
+ *$self->{Prime} = substr($_[0], 0, $len - *$self->{BufferOffset}) . *$self->{Prime} ;
+ *$self->{InputLengthRemaining} = *$self->{InputLength};
+ *$self->{BufferOffset} = 0
+ }
+ else {
+ *$self->{InputLengthRemaining} += length($_[0]);
+ *$self->{BufferOffset} -= length($_[0]) ;
+ }
+ }
+}
+
+sub smartSeek
+{
+ my $self = shift ;
+ my $offset = shift ;
+ my $truncate = shift;
+ #print "smartSeek to $offset\n";
+
+ # TODO -- need to take prime into account
+ if (defined *$self->{FH})
+ { *$self->{FH}->seek($offset, SEEK_SET) }
+ else {
+ *$self->{BufferOffset} = $offset ;
+ substr(${ *$self->{Buffer} }, *$self->{BufferOffset}) = ''
+ if $truncate;
+ return 1;
+ }
+}
+
+sub smartWrite
+{
+ my $self = shift ;
+ my $out_data = shift ;
+
+ if (defined *$self->{FH}) {
+ # flush needed for 5.8.0
+ defined *$self->{FH}->write($out_data, length $out_data) &&
+ defined *$self->{FH}->flush() ;
+ }
+ else {
+ my $buf = *$self->{Buffer} ;
+ substr($$buf, *$self->{BufferOffset}, length $out_data) = $out_data ;
+ *$self->{BufferOffset} += length($out_data) ;
+ return 1;
+ }
+}
+
+sub smartReadExact
+{
+ return $_[0]->smartRead($_[1], $_[2]) == $_[2];
+}
+
+sub smartEof
+{
+ my ($self) = $_[0];
+
+ return 0 if length *$self->{Prime};
+
+ if (defined *$self->{FH})
+ { *$self->{FH}->eof() }
+ elsif (defined *$self->{InputEvent})
+ { *$self->{EventEof} }
+ else
+ { *$self->{BufferOffset} >= length(${ *$self->{Buffer} }) }
+}
+
+sub clearError
+{
+ my $self = shift ;
+
+ *$self->{ErrorNo} = 0 ;
+ ${ *$self->{Error} } = '' ;
+}
+
+sub saveStatus
+{
+ my $self = shift ;
+ my $errno = shift() + 0 ;
+ #return $errno unless $errno || ! defined *$self->{ErrorNo};
+ #return $errno unless $errno ;
+
+ *$self->{ErrorNo} = $errno;
+ ${ *$self->{Error} } = '' ;
+
+ return *$self->{ErrorNo} ;
+}
+
+
+sub saveErrorString
+{
+ my $self = shift ;
+ my $retval = shift ;
+
+ #return $retval if ${ *$self->{Error} };
+
+ ${ *$self->{Error} } = shift ;
+ *$self->{ErrorNo} = shift() + 0 if @_ ;
+
+ #warn "saveErrorString: " . ${ *$self->{Error} } . " " . *$self->{Error} . "\n" ;
+ return $retval;
+}
+
+sub croakError
+{
+ my $self = shift ;
+ $self->saveErrorString(0, $_[0]);
+ croak $_[0];
+}
+
+
+sub closeError
+{
+ my $self = shift ;
+ my $retval = shift ;
+
+ my $errno = *$self->{ErrorNo};
+ my $error = ${ *$self->{Error} };
+
+ $self->close();
+
+ *$self->{ErrorNo} = $errno ;
+ ${ *$self->{Error} } = $error ;
+
+ return $retval;
+}
+
+sub error
+{
+ my $self = shift ;
+ return ${ *$self->{Error} } ;
+}
+
+sub errorNo
+{
+ my $self = shift ;
+ return *$self->{ErrorNo};
+}
+
+sub HeaderError
+{
+ my ($self) = shift;
+ return $self->saveErrorString(undef, "Header Error: $_[0]", STATUS_ERROR);
+}
+
+sub TrailerError
+{
+ my ($self) = shift;
+ return $self->saveErrorString(G_ERR, "Trailer Error: $_[0]", STATUS_ERROR);
+}
+
+sub TruncatedHeader
+{
+ my ($self) = shift;
+ return $self->HeaderError("Truncated in $_[0] Section");
+}
+
+sub checkParams
+{
+ my $self = shift ;
+ my $class = shift ;
+
+ my $got = shift || Compress::Zlib::ParseParameters::new();
+
+ my $Valid = {
+ 'BlockSize' => [1, 1, Parse_unsigned, 16 * 1024],
+ 'AutoClose' => [1, 1, Parse_boolean, 0],
+ 'Strict' => [1, 1, Parse_boolean, 0],
+ #'Lax' => [1, 1, Parse_boolean, 1],
+ 'Append' => [1, 1, Parse_boolean, 0],
+ 'Prime' => [1, 1, Parse_any, undef],
+ 'MultiStream' => [1, 1, Parse_boolean, 0],
+ 'Transparent' => [1, 1, Parse_any, 1],
+ 'Scan' => [1, 1, Parse_boolean, 0],
+ 'InputLength' => [1, 1, Parse_unsigned, undef],
+ 'BinModeOut' => [1, 1, Parse_boolean, 0],
+
+ $self->getExtraParams(),
+
+
+ #'Todo - Revert to ordinary file on end Z_STREAM_END'=> 0,
+ # ContinueAfterEof
+ } ;
+
+
+ $got->parse($Valid, @_ )
+ or $self->croakError("${class}: $got->{Error}") ;
+
+
+ return $got;
+}
+
+sub _create
+{
+ my $obj = shift;
+ my $got = shift;
+ my $append_mode = shift ;
+
+ my $class = ref $obj;
+ $obj->croakError("$class: Missing Input parameter")
+ if ! @_ && ! $got ;
+
+ my $inValue = shift ;
+
+ if (! $got)
+ {
+ $got = $obj->checkParams($class, undef, @_)
+ or return undef ;
+ }
+
+ my $inType = whatIsInput($inValue, 1);
+
+ $obj->ckInputParam($class, $inValue, 1)
+ or return undef ;
+
+ *$obj->{InNew} = 1;
+
+ $obj->ckParams($got)
+ or $obj->croakError("${class}: $obj->{Error}");
+
+ if ($inType eq 'buffer' || $inType eq 'code') {
+ *$obj->{Buffer} = $inValue ;
+ *$obj->{InputEvent} = $inValue
+ if $inType eq 'code' ;
+ }
+ else {
+ if ($inType eq 'handle') {
+ *$obj->{FH} = $inValue ;
+ *$obj->{Handle} = 1 ;
+ # Need to rewind for Scan
+ #seek(*$obj->{FH}, 0, SEEK_SET) if $got->value('Scan');
+ *$obj->{FH}->seek(0, SEEK_SET) if $got->value('Scan');
+ }
+ else {
+ my $mode = '<';
+ $mode = '+<' if $got->value('Scan');
+ *$obj->{StdIO} = ($inValue eq '-');
+ *$obj->{FH} = new IO::File "$mode $inValue"
+ or return $obj->saveErrorString(undef, "cannot open file '$inValue': $!", $!) ;
+ *$obj->{LineNo} = 0;
+ }
+
+ setBinModeInput(*$obj->{FH}) ;
+
+ my $buff = "" ;
+ *$obj->{Buffer} = \$buff ;
+ }
+
+
+ *$obj->{InputLength} = $got->parsed('InputLength')
+ ? $got->value('InputLength')
+ : undef ;
+ *$obj->{InputLengthRemaining} = $got->value('InputLength');
+ *$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->{Transparent} = $got->value('Transparent');
+ *$obj->{MultiStream} = $got->value('MultiStream');
+
+ # TODO - move these two into RawDeflate
+ *$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->{TotalInflatedBytesRead} = 0;
+ *$obj->{NewStream} = 0 ;
+ *$obj->{EventEof} = 0 ;
+ *$obj->{ClassName} = $class ;
+ *$obj->{Params} = $got ;
+
+ my $status = $obj->mkUncomp($class, $got);
+
+ return undef
+ unless defined $status;
+
+ if ( ! $status) {
+ return undef
+ unless *$obj->{Transparent};
+
+ $obj->clearError();
+ *$obj->{Type} = 'plain';
+ *$obj->{Plain} = 1;
+ #$status = $obj->mkIdentityUncomp($class, $got);
+ $obj->pushBack(*$obj->{HeaderPending}) ;
+ }
+
+ push @{ *$obj->{InfoList} }, *$obj->{Info} ;
+
+ $obj->saveStatus(0) ;
+ *$obj->{InNew} = 0;
+ *$obj->{Closed} = 0;
+
+ return $obj;
+}
+
+sub ckInputParam
+{
+ my $self = shift ;
+ my $from = shift ;
+ my $inType = whatIsInput($_[0], $_[1]);
+
+ $self->croakError("$from: input parameter not a filename, filehandle, array ref or scalar ref")
+ if ! $inType ;
+
+ if ($inType eq 'filename' )
+ {
+ $self->croakError("$from: input filename is undef or null string")
+ if ! defined $_[0] || $_[0] eq '' ;
+
+ if ($_[0] ne '-' && ! -e $_[0] )
+ {
+ return $self->saveErrorString(undef,
+ "input file '$_[0]' does not exist", STATUS_ERROR);
+ }
+ }
+
+ return 1;
+}
+
+
+sub _inf
+{
+ my $obj = shift ;
+
+ my $class = (caller)[0] ;
+ my $name = (caller(1))[3] ;
+
+ $obj->croakError("$name: expected at least 1 parameters\n")
+ unless @_ >= 1 ;
+
+ my $input = shift ;
+ my $haveOut = @_ ;
+ my $output = shift ;
+
+
+ my $x = new Validator($class, *$obj->{Error}, $name, $input, $output)
+ or return undef ;
+
+ push @_, $output if $haveOut && $x->{Hash};
+
+ 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->_singleTarget($x, 1, $k, $v, @_)
+ or return undef ;
+ }
+
+ return keys %$input ;
+ }
+
+ if ($x->{GlobMap})
+ {
+ $x->{oneInput} = 1 ;
+ foreach my $pair (@{ $x->{Pairs} })
+ {
+ my ($from, $to) = @$pair ;
+ $obj->_singleTarget($x, 1, $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, @_)
+ 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, @_);
+
+ croak "should not be here" ;
+}
+
+sub retErr
+{
+ my $x = shift ;
+ my $string = shift ;
+
+ ${ $x->{Error} } = $string ;
+
+ return undef ;
+}
+
+sub _singleTarget
+{
+ my $self = shift ;
+ my $x = shift ;
+ my $inputIsFilename = shift;
+ my $input = shift;
+ my $output = shift;
+
+ $x->{buff} = '' ;
+
+ my $fh ;
+ if ($x->{outType} eq 'filename') {
+ my $mode = '>' ;
+ $mode = '>>'
+ if $x->{Got}->value('Append') ;
+ $x->{fh} = new IO::File "$mode $output"
+ or return retErr($x, "cannot open file '$output': $!") ;
+ binmode $x->{fh} if $x->{Got}->valueOrDefault('BinModeOut');
+
+ }
+
+ elsif ($x->{outType} eq 'handle') {
+ $x->{fh} = $output;
+ binmode $x->{fh} if $x->{Got}->valueOrDefault('BinModeOut');
+ if ($x->{Got}->value('Append')) {
+ seek($x->{fh}, 0, SEEK_END)
+ or return retErr($x, "Cannot seek to end of output filehandle: $!") ;
+ }
+ }
+
+
+ elsif ($x->{outType} eq 'buffer' )
+ {
+ $$output = ''
+ unless $x->{Got}->value('Append');
+ $x->{buff} = $output ;
+ }
+
+ if ($x->{oneInput})
+ {
+ defined $self->_rd2($x, $input, $inputIsFilename)
+ 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)
+ or return undef ;
+ }
+ }
+
+
+ if ( ($x->{outType} eq 'filename' && $output ne '-') ||
+ ($x->{outType} eq 'handle' && $x->{Got}->value('AutoClose'))) {
+ $x->{fh}->close()
+ or return retErr($x, $!);
+ #or return $gunzip->saveErrorString(undef, $!, $!);
+ delete $x->{fh};
+ }
+
+ return 1 ;
+}
+
+sub _rd2
+{
+ my $self = shift ;
+ my $x = shift ;
+ my $input = shift;
+ my $inputIsFilename = shift;
+
+ my $z = createSelfTiedObject($x->{Class}, *$self->{Error});
+
+ $z->_create($x->{Got}, 1, $input, @_)
+ or return undef ;
+
+ 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} = '' ;
+ }
+ }
+
+ return $z->closeError(undef)
+ if $status < 0 ;
+
+ $z->close()
+ or return undef ;
+
+ return 1 ;
+}
+
+sub TIEHANDLE
+{
+ return $_[0] if ref($_[0]);
+ die "OOPS\n" ;
+
+}
+
+sub UNTIE
+{
+ my $self = shift ;
+}
+
+
+sub getHeaderInfo
+{
+ my $self = shift ;
+ wantarray ? @{ *$self->{InfoList} } : *$self->{Info};
+}
+
+sub readBlock
+{
+ my $self = shift ;
+ my $buff = shift ;
+ my $size = shift ;
+
+ if (defined *$self->{CompressedInputLength}) {
+ if (*$self->{CompressedInputLengthRemaining} == 0) {
+ delete *$self->{CompressedInputLength};
+ #$$buff = '';
+ return STATUS_OK ;
+ }
+ $size = min($size, *$self->{CompressedInputLengthRemaining} );
+ *$self->{CompressedInputLengthRemaining} -= $size ;
+ }
+
+ my $status = $self->smartRead($buff, $size) ;
+ return $self->saveErrorString(STATUS_ERROR, "Error Reading Data")
+ if $status < 0 ;
+
+ if ($status == 0 ) {
+ *$self->{Closed} = 1 ;
+ *$self->{EndStream} = 1 ;
+ return $self->saveErrorString(STATUS_ERROR, "unexpected end of file", STATUS_ERROR);
+ }
+
+ return STATUS_OK;
+
+}
+
+sub postBlockChk
+{
+ return STATUS_OK;
+}
+
+sub _raw_read
+{
+ # return codes
+ # >0 - ok, number of bytes read
+ # =0 - ok, eof
+ # <0 - not ok
+
+ my $self = shift ;
+
+ return G_EOF if *$self->{Closed} ;
+ #return G_EOF if !length *$self->{Pending} && *$self->{EndStream} ;
+ return G_EOF if *$self->{EndStream} ;
+
+ my $buffer = shift ;
+ my $scan_mode = shift ;
+
+ if (*$self->{Plain}) {
+ my $tmp_buff ;
+ my $len = $self->smartRead(\$tmp_buff, *$self->{BlockSize}) ;
+
+ return $self->saveErrorString(G_ERR, "Error reading data: $!", $!)
+ if $len < 0 ;
+
+ if ($len == 0 ) {
+ *$self->{EndStream} = 1 ;
+ }
+ else {
+ *$self->{PlainBytesRead} += $len ;
+ $$buffer .= $tmp_buff;
+ }
+
+ return $len ;
+ }
+
+ if (*$self->{NewStream}) {
+
+ *$self->{NewStream} = 0 ;
+ *$self->{EndStream} = 0 ;
+ *$self->{Uncomp}->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} ;
+
+ # For the headers that actually uncompressed data, put the
+ # uncompressed data into the output buffer.
+ $$buffer .= *$self->{Pending} ;
+ my $len = length *$self->{Pending} ;
+ *$self->{Pending} = '';
+ return $len;
+ }
+
+ 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 $before_len = defined $$buffer ? length $$buffer : 0 ;
+ $status = *$self->{Uncomp}->uncompr(\$temp_buf, $buffer,
+ (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;
+
+ $self->postBlockChk($buffer) == STATUS_OK
+ or return G_ERR;
+
+ #$buf_len = *$self->{Uncomp}->count();
+ $buf_len = length($$buffer) - $before_len;
+
+
+ *$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 ;
+ }
+ }
+
+ if ($status == STATUS_ENDSTREAM) {
+
+ *$self->{EndStream} = 1 ;
+ $self->pushBack($temp_buf) ;
+ $temp_buf = '';
+
+ my $trailer;
+ if (*$self->{Info}{TrailerLength})
+ {
+ my $trailer_size = *$self->{Info}{TrailerLength} ;
+
+ my $got = $self->smartRead(\$trailer, $trailer_size) ;
+ if ($got != $trailer_size) {
+ return $self->TrailerError("trailer truncated. Expected " .
+ "$trailer_size bytes, got $got")
+ if *$self->{Strict};
+ $self->pushBack($trailer) ;
+ }
+ }
+
+ $self->chkTrailer($trailer) == G_ERR
+ and return G_ERR;
+
+ if (*$self->{MultiStream} && ! $self->smartEof()) {
+ #&& (length $temp_buf || ! $self->smartEof())){
+ *$self->{NewStream} = 1 ;
+ *$self->{EndStream} = 0 ;
+ return $buf_len ;
+ }
+
+ }
+
+
+ # return the number of uncompressed bytes read
+ return $buf_len ;
+}
+
+#sub isEndStream
+#{
+# my $self = shift ;
+# return *$self->{NewStream} ||
+# *$self->{EndStream} ;
+#}
+
+sub streamCount
+{
+ my $self = shift ;
+ return 1 if ! defined *$self->{InfoList};
+ return scalar @{ *$self->{InfoList} } ;
+}
+
+sub read
+{
+ # return codes
+ # >0 - ok, number of bytes read
+ # =0 - ok, eof
+ # <0 - not ok
+
+ my $self = shift ;
+
+ return G_EOF if *$self->{Closed} ;
+ return G_EOF if !length *$self->{Pending} && *$self->{EndStream} ;
+
+ my $buffer ;
+
+ #$self->croakError(*$self->{ClassName} .
+ # "::read: buffer parameter is read-only")
+ # if Compress::Zlib::_readonly_ref($_[0]);
+
+ if (ref $_[0] ) {
+ $self->croakError(*$self->{ClassName} . "::read: buffer parameter is read-only")
+ if readonly(${ $_[0] });
+
+ $self->croakError(*$self->{ClassName} . "::read: not a scalar reference $_[0]" )
+ unless ref $_[0] eq 'SCALAR' ;
+ $buffer = $_[0] ;
+ }
+ else {
+ $self->croakError(*$self->{ClassName} . "::read: buffer parameter is read-only")
+ if readonly($_[0]);
+
+ $buffer = \$_[0] ;
+ }
+
+ my $length = $_[1] ;
+ my $offset = $_[2] || 0;
+
+ # the core read will return 0 if asked for 0 bytes
+ return 0 if defined $length && $length == 0 ;
+
+ $length = $length || 0;
+
+ $self->croakError(*$self->{ClassName} . "::read: length parameter is negative")
+ if $length < 0 ;
+
+ $$buffer = '' unless *$self->{AppendOutput} || $offset ;
+
+ # Short-circuit if this is a simple read, with no length
+ # or offset specified.
+ unless ( $length || $offset) {
+ if (length *$self->{Pending}) {
+ $$buffer .= *$self->{Pending} ;
+ my $len = length *$self->{Pending};
+ *$self->{Pending} = '' ;
+ return $len ;
+ }
+ else {
+ my $len = 0;
+ $len = $self->_raw_read($buffer)
+ while ! *$self->{EndStream} && $len == 0 ;
+ return $len ;
+ }
+ }
+
+ # Need to jump through more hoops - either length or offset
+ # or both are specified.
+ my $out_buffer = \*$self->{Pending} ;
+
+ while (! *$self->{EndStream} && length($$out_buffer) < $length)
+ {
+ my $buf_len = $self->_raw_read($out_buffer);
+ return $buf_len
+ if $buf_len < 0 ;
+ }
+
+ $length = length $$out_buffer
+ if length($$out_buffer) < $length ;
+
+ if ($offset) {
+ $$buffer .= "\x00" x ($offset - length($$buffer))
+ if $offset > length($$buffer) ;
+ #substr($$buffer, $offset) = substr($$out_buffer, 0, $length, '') ;
+ substr($$buffer, $offset) = substr($$out_buffer, 0, $length) ;
+ substr($$out_buffer, 0, $length) = '' ;
+ }
+ else {
+ #$$buffer .= substr($$out_buffer, 0, $length, '') ;
+ $$buffer .= substr($$out_buffer, 0, $length) ;
+ substr($$out_buffer, 0, $length) = '' ;
+ }
+
+ return $length ;
+}
+
+sub _getline
+{
+ my $self = shift ;
+
+ # Slurp Mode
+ if ( ! defined $/ ) {
+ my $data ;
+ 1 while $self->read($data) > 0 ;
+ return \$data ;
+ }
+
+ # Paragraph Mode
+ if ( ! length $/ ) {
+ my $paragraph ;
+ while ($self->read($paragraph) > 0 ) {
+ if ($paragraph =~ s/^(.*?\n\n+)//s) {
+ *$self->{Pending} = $paragraph ;
+ my $par = $1 ;
+ return \$par ;
+ }
+ }
+ return \$paragraph;
+ }
+
+ # Line Mode
+ {
+ my $line ;
+ my $endl = quotemeta($/); # quote in case $/ contains RE meta chars
+ while ($self->read($line) > 0 ) {
+ if ($line =~ s/^(.*?$endl)//s) {
+ *$self->{Pending} = $line ;
+ $. = ++ *$self->{LineNo} ;
+ my $l = $1 ;
+ return \$l ;
+ }
+ }
+ $. = ++ *$self->{LineNo} if defined($line);
+ return \$line;
+ }
+}
+
+sub getline
+{
+ my $self = shift;
+ my $current_append = *$self->{AppendOutput} ;
+ *$self->{AppendOutput} = 1;
+ my $lineref = $self->_getline();
+ *$self->{AppendOutput} = $current_append;
+ return $$lineref ;
+}
+
+sub getlines
+{
+ my $self = shift;
+ $self->croakError(*$self->{ClassName} .
+ "::getlines: called in scalar context\n") unless wantarray;
+ my($line, @lines);
+ push(@lines, $line) while defined($line = $self->getline);
+ return @lines;
+}
+
+sub READLINE
+{
+ goto &getlines if wantarray;
+ goto &getline;
+}
+
+sub getc
+{
+ my $self = shift;
+ my $buf;
+ return $buf if $self->read($buf, 1);
+ return undef;
+}
+
+sub ungetc
+{
+ my $self = shift;
+ *$self->{Pending} = "" unless defined *$self->{Pending} ;
+ *$self->{Pending} = $_[0] . *$self->{Pending} ;
+}
+
+
+sub trailingData
+{
+ my $self = shift ;
+ #return \"" if ! defined *$self->{Trailing} ;
+ #return \*$self->{Trailing} ;
+
+ if (defined *$self->{FH} || defined *$self->{InputEvent} ) {
+ return *$self->{Prime} ;
+ }
+ else {
+ my $buf = *$self->{Buffer} ;
+ my $offset = *$self->{BufferOffset} ;
+ return substr($$buf, $offset, -1) ;
+ }
+}
+
+
+sub eof
+{
+ my $self = shift ;
+
+ return (*$self->{Closed} ||
+ (!length *$self->{Pending}
+ && ( $self->smartEof() || *$self->{EndStream}))) ;
+}
+
+sub tell
+{
+ my $self = shift ;
+
+ my $in ;
+ if (*$self->{Plain}) {
+ $in = *$self->{PlainBytesRead} ;
+ }
+ else {
+ $in = *$self->{TotalInflatedBytesRead} ;
+ }
+
+ my $pending = length *$self->{Pending} ;
+
+ return 0 if $pending > $in ;
+ return $in - $pending ;
+}
+
+sub close
+{
+ # todo - what to do if close is called before the end of the gzip file
+ # do we remember any trailing data?
+ my $self = shift ;
+
+ return 1 if *$self->{Closed} ;
+
+ untie *$self
+ if $] >= 5.008 ;
+
+ my $status = 1 ;
+
+ if (defined *$self->{FH}) {
+ if ((! *$self->{Handle} || *$self->{AutoClose}) && ! *$self->{StdIO}) {
+ #if ( *$self->{AutoClose}) {
+ $! = 0 ;
+ $status = *$self->{FH}->close();
+ return $self->saveErrorString(0, $!, $!)
+ if !*$self->{InNew} && $self->saveStatus($!) != 0 ;
+ }
+ delete *$self->{FH} ;
+ $! = 0 ;
+ }
+ *$self->{Closed} = 1 ;
+
+ return 1;
+}
+
+sub DESTROY
+{
+ my $self = shift ;
+ $self->close() ;
+}
+
+sub seek
+{
+ my $self = shift ;
+ my $position = shift;
+ my $whence = shift ;
+
+ my $here = $self->tell() ;
+ my $target = 0 ;
+
+
+ if ($whence == SEEK_SET) {
+ $target = $position ;
+ }
+ elsif ($whence == SEEK_CUR) {
+ $target = $here + $position ;
+ }
+ elsif ($whence == SEEK_END) {
+ $target = $position ;
+ $self->croakError(*$self->{ClassName} . "::seek: SEEK_END not allowed") ;
+ }
+ else {
+ $self->croakError(*$self->{ClassName} ."::seek: unknown value, $whence, for whence parameter");
+ }
+
+ # short circuit if seeking to current offset
+ return 1 if $target == $here ;
+
+ # Outlaw any attempt to seek backwards
+ $self->croakError( *$self->{ClassName} ."::seek: cannot seek backwards")
+ if $target < $here ;
+
+ # Walk the file to the new offset
+ my $offset = $target - $here ;
+
+ my $buffer ;
+ $self->read($buffer, $offset) == $offset
+ or return 0 ;
+
+ return 1 ;
+}
+
+sub fileno
+{
+ my $self = shift ;
+ return defined *$self->{FH}
+ ? fileno *$self->{FH}
+ : undef ;
+}
+
+sub binmode
+{
+ 1;
+# my $self = shift ;
+# return defined *$self->{FH}
+# ? binmode *$self->{FH}
+# : 1 ;
+}
+
+*BINMODE = \&binmode;
+*SEEK = \&seek;
+*READ = \&read;
+*sysread = \&read;
+*TELL = \&tell;
+*EOF = \&eof;
+
+*FILENO = \&fileno;
+*CLOSE = \&close;
+
+sub _notAvailable
+{
+ my $name = shift ;
+ #return sub { croak "$name Not Available" ; } ;
+ return sub { croak "$name Not Available: File opened only for intput" ; } ;
+}
+
+
+*print = _notAvailable('print');
+*PRINT = _notAvailable('print');
+*printf = _notAvailable('printf');
+*PRINTF = _notAvailable('printf');
+*write = _notAvailable('write');
+*WRITE = _notAvailable('write');
+
+#*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 ;
+#}
+#
+#
+#sub reset
+#{
+# return STATUS_OK ;
+#}
+
+
+package IO::Uncompress::Base ;
+
+
+1 ;
+__END__
+
diff --git a/ext/Compress/Zlib/lib/IO/Uncompress/Gunzip.pm b/ext/Compress/Zlib/lib/IO/Uncompress/Gunzip.pm
index 17003725bf..d6d3846c98 100644
--- a/ext/Compress/Zlib/lib/IO/Uncompress/Gunzip.pm
+++ b/ext/Compress/Zlib/lib/IO/Uncompress/Gunzip.pm
@@ -8,243 +8,108 @@ require 5.004 ;
use strict ;
use warnings;
+use IO::Uncompress::RawInflate ;
+
+use Compress::Zlib qw( crc32 ) ;
+use Compress::Zlib::Common qw(createSelfTiedObject);
+use Compress::Gzip::Constants;
+
require Exporter ;
our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $GunzipError);
-@ISA = qw(Exporter IO::BaseInflate);
+@ISA = qw( Exporter IO::Uncompress::RawInflate );
@EXPORT_OK = qw( $GunzipError gunzip );
-%EXPORT_TAGS = %IO::BaseInflate::EXPORT_TAGS ;
+%EXPORT_TAGS = %IO::Uncompress::RawInflate::DEFLATE_CONSTANTS ;
push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
Exporter::export_ok_tags('all');
-
$GunzipError = '';
-$VERSION = '2.000_05';
+$VERSION = '2.000_07';
sub new
{
- my $pkg = shift ;
- return IO::BaseInflate::new($pkg, 'rfc1952', undef, \$GunzipError, 0, @_);
-}
+ my $class = shift ;
+ $GunzipError = '';
+ my $obj = createSelfTiedObject($class, \$GunzipError);
-sub gunzip
-{
- return IO::BaseInflate::_inf(__PACKAGE__, 'rfc1952', \$GunzipError, @_) ;
+ $obj->_create(undef, 0, @_);
}
-package IO::BaseInflate ;
-
-use strict ;
-use warnings;
-use bytes;
-
-our ($VERSION, @EXPORT_OK, %EXPORT_TAGS);
-
-$VERSION = '2.000_03';
-
-use Compress::Zlib 2 ;
-use Compress::Zlib::Common ;
-use Compress::Zlib::ParseParameters ;
-use Compress::Gzip::Constants;
-use Compress::Zlib::FileConstants;
-
-use IO::File ;
-use Symbol;
-use Scalar::Util qw(readonly);
-use List::Util qw(min);
-use Carp ;
-
-%EXPORT_TAGS = ( );
-push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
-#Exporter::export_ok_tags('all') ;
-
-
-use constant G_EOF => 0 ;
-use constant G_ERR => -1 ;
-
-sub smartRead
+sub gunzip
{
- my $self = $_[0];
- my $out = $_[1];
- my $size = $_[2];
- $$out = "" ;
-
- my $offset = 0 ;
-
-
- if ( length *$self->{Prime} ) {
- #$$out = substr(*$self->{Prime}, 0, $size, '') ;
- $$out = substr(*$self->{Prime}, 0, $size) ;
- substr(*$self->{Prime}, 0, $size) = '' ;
- if (length $$out == $size) {
- #*$self->{InputLengthRemaining} -= length $$out;
- return length $$out ;
- }
- $offset = length $$out ;
- }
-
- my $get_size = $size - $offset ;
-
- if ( defined *$self->{InputLength} ) {
- #*$self->{InputLengthRemaining} += length *$self->{Prime} ;
- #*$self->{InputLengthRemaining} = *$self->{InputLength}
- # if *$self->{InputLengthRemaining} > *$self->{InputLength};
- $get_size = min($get_size, *$self->{InputLengthRemaining});
- }
-
- if (defined *$self->{FH})
- { *$self->{FH}->read($$out, $get_size, $offset) }
- elsif (defined *$self->{InputEvent}) {
- my $got = 1 ;
- while (length $$out < $size) {
- last
- if ($got = *$self->{InputEvent}->($$out, $get_size)) <= 0;
- }
-
- if (length $$out > $size ) {
- #*$self->{Prime} = substr($$out, $size, length($$out), '');
- *$self->{Prime} = substr($$out, $size, length($$out));
- substr($$out, $size, length($$out)) = '';
- }
-
- *$self->{EventEof} = 1 if $got <= 0 ;
- }
- else {
- no warnings 'uninitialized';
- my $buf = *$self->{Buffer} ;
- $$buf = '' unless defined $$buf ;
- #$$out = '' unless defined $$out ;
- substr($$out, $offset) = substr($$buf, *$self->{BufferOffset}, $get_size);
- *$self->{BufferOffset} += length($$out) - $offset ;
- }
-
- *$self->{InputLengthRemaining} -= length $$out;
-
- $self->saveStatus(length $$out < 0 ? Z_DATA_ERROR : 0) ;
-
- return length $$out;
+ my $obj = createSelfTiedObject(undef, \$GunzipError);
+ return $obj->_inf(@_) ;
}
-sub smartSeek
+sub getExtraParams
{
- my $self = shift ;
- my $offset = shift ;
- my $truncate = shift;
- #print "smartSeek to $offset\n";
-
- if (defined *$self->{FH})
- { *$self->{FH}->seek($offset, SEEK_SET) }
- else {
- *$self->{BufferOffset} = $offset ;
- substr(${ *$self->{Buffer} }, *$self->{BufferOffset}) = ''
- if $truncate;
- return 1;
- }
+ use Compress::Zlib::ParseParameters ;
+ return ( 'ParseExtra' => [1, 1, Parse_boolean, 0] ) ;
}
-sub smartWrite
+sub ckParams
{
- my $self = shift ;
- my $out_data = shift ;
+ my $self = shift ;
+ my $got = shift ;
- if (defined *$self->{FH}) {
- # flush needed for 5.8.0
- defined *$self->{FH}->write($out_data, length $out_data) &&
- defined *$self->{FH}->flush() ;
- }
- else {
- my $buf = *$self->{Buffer} ;
- substr($$buf, *$self->{BufferOffset}, length $out_data) = $out_data ;
- *$self->{BufferOffset} += length($out_data) ;
- return 1;
- }
-}
+ # gunzip always needs crc32
+ $got->value('CRC32' => 1);
-sub smartReadExact
-{
- return $_[0]->smartRead($_[1], $_[2]) == $_[2];
+ return 1;
}
-sub getTrailingBuffer
+sub ckMagic
{
- my ($self) = $_[0];
- return "" if defined *$self->{FH} || defined *$self->{InputEvent} ;
-
- my $buf = *$self->{Buffer} ;
- my $offset = *$self->{BufferOffset} ;
- return substr($$buf, $offset, -1) ;
-}
+ my $self = shift;
-sub smartEof
-{
- my ($self) = $_[0];
- if (defined *$self->{FH})
- { *$self->{FH}->eof() }
- elsif (defined *$self->{InputEvent})
- { *$self->{EventEof} }
- else
- { *$self->{BufferOffset} >= length(${ *$self->{Buffer} }) }
-}
+ my $magic ;
+ $self->smartReadExact(\$magic, GZIP_ID_SIZE);
-sub saveStatus
-{
- my $self = shift ;
- *$self->{ErrorNo} = shift() + 0 ;
- ${ *$self->{Error} } = '' ;
+ *$self->{HeaderPending} = $magic ;
- return *$self->{ErrorNo} ;
-}
+ return $self->HeaderError("Minimum header size is " .
+ GZIP_MIN_HEADER_SIZE . " bytes")
+ if length $magic != GZIP_ID_SIZE ;
+ return $self->HeaderError("Bad Magic")
+ if ! isGzipMagic($magic) ;
-sub saveErrorString
-{
- my $self = shift ;
- my $retval = shift ;
- ${ *$self->{Error} } = shift ;
- *$self->{ErrorNo} = shift() + 0 if @_ ;
+ *$self->{Type} = 'rfc1952';
- #print "saveErrorString: " . ${ *$self->{Error} } . "\n" ;
- return $retval;
+ return $magic ;
}
-sub error
+sub readHeader
{
- my $self = shift ;
- return ${ *$self->{Error} } ;
-}
+ my $self = shift;
+ my $magic = shift;
-sub errorNo
-{
- my $self = shift ;
- return *$self->{ErrorNo};
+ return $self->_readGzipHeader($magic);
}
-sub HeaderError
+sub chkTrailer
{
- my ($self) = shift;
- return $self->saveErrorString(undef, "Header Error: $_[0]", Z_DATA_ERROR);
-}
+ my $self = shift;
+ my $trailer = shift;
-sub TrailerError
-{
- my ($self) = shift;
- return $self->saveErrorString(G_ERR, "Trailer Error: $_[0]", Z_DATA_ERROR);
-}
+ # Check CRC & ISIZE
+ my ($CRC32, $ISIZE) = unpack("V V", $trailer) ;
+ *$self->{Info}{CRC32} = $CRC32;
+ *$self->{Info}{ISIZE} = $ISIZE;
-sub TruncatedHeader
-{
- my ($self) = shift;
- return $self->HeaderError("Truncated in $_[0] Section");
-}
+ if (*$self->{Strict}) {
+ return $self->TrailerError("CRC mismatch")
+ if $CRC32 != *$self->{Uncomp}->crc32() ;
-sub isZipMagic
-{
- my $buffer = shift ;
- return 0 if length $buffer < 4 ;
- my $sig = unpack("V", $buffer) ;
- return $sig == 0x04034b50 ;
+ my $exp_isize = *$self->{Uncomp}->uncompressedBytes();
+ return $self->TrailerError("ISIZE mismatch. Got $ISIZE"
+ . ", expected $exp_isize")
+ if $ISIZE != $exp_isize ;
+ }
+
+ return 1;
}
sub isGzipMagic
@@ -255,108 +120,6 @@ sub isGzipMagic
return $id1 == GZIP_ID1 && $id2 == GZIP_ID2 ;
}
-sub isZlibMagic
-{
- my $buffer = shift ;
- return 0 if length $buffer < ZLIB_HEADER_SIZE ;
- my $hdr = unpack("n", $buffer) ;
- return $hdr % 31 == 0 ;
-}
-
-sub _isRaw
-{
- my $self = shift ;
- my $magic = shift ;
-
- $magic = '' unless defined $magic ;
-
- my $buffer = '';
-
- $self->smartRead(\$buffer, *$self->{BlockSize}) >= 0
- or return $self->saveErrorString(undef, "No data to read");
-
- my $temp_buf = $magic . $buffer ;
- *$self->{HeaderPending} = $temp_buf ;
- $buffer = '';
- my $status = *$self->{Inflate}->inflate($temp_buf, $buffer) ;
- my $buf_len = *$self->{Inflate}->inflateCount();
-
- # zlib before 1.2 needs an extra byte after the compressed data
- # for RawDeflate
- if ($status == Z_OK && $self->smartEof()) {
- my $byte = ' ';
- $status = *$self->{Inflate}->inflate(\$byte, $buffer) ;
- return $self->saveErrorString(undef, "Inflation Error: $status", $status)
- unless $self->saveStatus($status) == Z_OK || $status == Z_STREAM_END ;
- $buf_len += *$self->{Inflate}->inflateCount();
- }
-
- return $self->saveErrorString(undef, "unexpected end of file", Z_DATA_ERROR)
- if $self->saveStatus($status) != Z_STREAM_END && $self->smartEof() ;
-
- return $self->saveErrorString(undef, "Inflation Error: $status", $status)
- unless $status == Z_OK || $status == Z_STREAM_END ;
-
- if ($status == Z_STREAM_END) {
- if (*$self->{MultiStream}
- && (length $temp_buf || ! $self->smartEof())){
- *$self->{NewStream} = 1 ;
- *$self->{EndStream} = 0 ;
- *$self->{Prime} = $temp_buf . *$self->{Prime} ;
- }
- else {
- *$self->{EndStream} = 1 ;
- *$self->{Trailing} = $temp_buf . $self->getTrailingBuffer();
- }
- }
- *$self->{HeaderPending} = $buffer ;
- *$self->{InflatedBytesRead} = $buf_len ;
- *$self->{TotalInflatedBytesRead} += $buf_len ;
- *$self->{Type} = 'rfc1951';
-
- $self->saveStatus(Z_OK);
-
- return {
- 'Type' => 'rfc1951',
- 'HeaderLength' => 0,
- 'TrailerLength' => 0,
- 'Header' => ''
- };
-}
-
-sub _guessCompression
-{
- my $self = shift ;
-
- # Check raw first in case the first few bytes happen to match
- # the signatures of gzip/deflate.
- my $got = $self->_isRaw() ;
- return $got if defined $got ;
-
- *$self->{Prime} = *$self->{HeaderPending} . *$self->{Prime} ;
- *$self->{HeaderPending} = '';
- *$self->{Inflate}->inflateReset();
-
- my $magic = '' ;
- my $status ;
- $self->smartReadExact(\$magic, GZIP_ID_SIZE)
- or return $self->HeaderError("Minimum header size is " .
- GZIP_ID_SIZE . " bytes") ;
-
- if (isGzipMagic($magic)) {
- $status = $self->_readGzipHeader($magic);
- delete *$self->{Transparent} if ! defined $status ;
- return $status ;
- }
- elsif ( $status = $self->_readDeflateHeader($magic) ) {
- return $status ;
- }
-
- *$self->{Prime} = $magic . *$self->{HeaderPending} . *$self->{Prime} ;
- *$self->{HeaderPending} = '';
- $self->saveErrorString(undef, "unknown compression format", Z_DATA_ERROR);
-}
-
sub _readFullGzipHeader($)
{
my ($self) = @_ ;
@@ -491,6 +254,7 @@ sub _readGzipHeader($)
return {
'Type' => 'rfc1952',
+ 'FingerprintLength' => 2,
'HeaderLength' => length $keep,
'TrailerLength' => GZIP_TRAILER_SIZE,
'Header' => $keep,
@@ -522,1299 +286,9 @@ sub _readGzipHeader($)
}
}
-sub _readFullZipHeader($)
-{
- my ($self) = @_ ;
- my $magic = '' ;
-
- $self->smartReadExact(\$magic, 4);
-
- *$self->{HeaderPending} = $magic ;
-
- return $self->HeaderError("Minimum header size is " .
- 30 . " bytes")
- if length $magic != 4 ;
-
-
- return $self->HeaderError("Bad Magic")
- if ! isZipMagic($magic) ;
-
- my $status = $self->_readZipHeader($magic);
- delete *$self->{Transparent} if ! defined $status ;
- return $status ;
-}
-
-sub _readZipHeader($)
-{
- my ($self, $magic) = @_ ;
- my ($HeaderCRC) ;
- my ($buffer) = '' ;
-
- $self->smartReadExact(\$buffer, 30 - 4)
- or return $self->HeaderError("Minimum header size is " .
- 30 . " bytes") ;
-
- my $keep = $magic . $buffer ;
- *$self->{HeaderPending} = $keep ;
-
- my $extractVersion = unpack ("v", substr($buffer, 4-4, 2));
- my $gpFlag = unpack ("v", substr($buffer, 6-4, 2));
- my $compressedMethod = unpack ("v", substr($buffer, 8-4, 2));
- my $lastModTime = unpack ("v", substr($buffer, 10-4, 2));
- my $lastModDate = unpack ("v", substr($buffer, 12-4, 2));
- 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 $filename_length = unpack ("v", substr($buffer, 26-4, 2));
- my $extra_length = unpack ("v", substr($buffer, 28-4, 2));
-
- my $filename;
- my $extraField;
-
- if ($filename_length)
- {
- $self->smartReadExact(\$filename, $filename_length)
- or return $self->HeaderError("xxx");
- $keep .= $filename ;
- }
-
- if ($extra_length)
- {
- $self->smartReadExact(\$extraField, $extra_length)
- or return $self->HeaderError("xxx");
- $keep .= $extraField ;
- }
-
- *$self->{Type} = 'zip';
-
- return {
- 'Type' => 'zip',
- 'HeaderLength' => length $keep,
- 'TrailerLength' => $gpFlag & 0x08 ? 16 : 0,
- 'Header' => $keep,
-
-# 'MethodID' => $cm,
-# 'MethodName' => $cm == GZIP_CM_DEFLATED ? "Deflated" : "Unknown" ,
-# 'TextFlag' => $flag & GZIP_FLG_FTEXT ? 1 : 0,
-# 'HeaderCRCFlag' => $flag & GZIP_FLG_FHCRC ? 1 : 0,
-# 'NameFlag' => $flag & GZIP_FLG_FNAME ? 1 : 0,
-# 'CommentFlag' => $flag & GZIP_FLG_FCOMMENT ? 1 : 0,
-# 'ExtraFlag' => $flag & GZIP_FLG_FEXTRA ? 1 : 0,
-# 'Name' => $origname,
-# 'Comment' => $comment,
-# 'Time' => $mtime,
-# 'OsID' => $os,
-# 'OsName' => defined $GZIP_OS_Names{$os}
-# ? $GZIP_OS_Names{$os} : "Unknown",
-# 'HeaderCRC' => $HeaderCRC,
-# 'Flags' => $flag,
-# 'ExtraFlags' => $xfl,
-# 'ExtraFieldRaw' => $EXTRA,
-# 'ExtraField' => [ @EXTRA ],
-
-
- #'CompSize'=> $compsize,
- #'CRC32'=> $CRC32,
- #'OrigSize'=> $ISIZE,
- }
-}
-
-sub bits
-{
- my $data = shift ;
- my $offset = shift ;
- my $mask = shift ;
-
- ($data >> $offset ) & $mask & 0xFF ;
-}
-
-
-sub _readDeflateHeader
-{
- my ($self, $buffer) = @_ ;
-
- if (! $buffer) {
- $self->smartReadExact(\$buffer, ZLIB_HEADER_SIZE);
-
- *$self->{HeaderPending} = $buffer ;
-
- return $self->HeaderError("Header size is " .
- ZLIB_HEADER_SIZE . " bytes")
- if length $buffer != ZLIB_HEADER_SIZE;
-
- return $self->HeaderError("CRC mismatch.")
- if ! isZlibMagic($buffer) ;
- }
-
- my ($CMF, $FLG) = unpack "C C", $buffer;
- my $FDICT = bits($FLG, ZLIB_FLG_FDICT_OFFSET, ZLIB_FLG_FDICT_BITS ),
-
- my $cm = bits($CMF, ZLIB_CMF_CM_OFFSET, ZLIB_CMF_CM_BITS) ;
- $cm == ZLIB_CMF_CM_DEFLATED
- or return $self->HeaderError("Not Deflate (CM is $cm)") ;
-
- my $DICTID;
- if ($FDICT) {
- $self->smartReadExact(\$buffer, ZLIB_FDICT_SIZE)
- or return $self->TruncatedHeader("FDICT");
-
- $DICTID = unpack("N", $buffer) ;
- }
-
- *$self->{Type} = 'rfc1950';
-
- return {
- 'Type' => 'rfc1950',
- 'HeaderLength' => ZLIB_HEADER_SIZE,
- 'TrailerLength' => ZLIB_TRAILER_SIZE,
- 'Header' => $buffer,
-
- CMF => $CMF ,
- CM => bits($CMF, ZLIB_CMF_CM_OFFSET, ZLIB_CMF_CM_BITS ),
- CINFO => bits($CMF, ZLIB_CMF_CINFO_OFFSET, ZLIB_CMF_CINFO_BITS ),
- FLG => $FLG ,
- FCHECK => bits($FLG, ZLIB_FLG_FCHECK_OFFSET, ZLIB_FLG_FCHECK_BITS),
- FDICT => bits($FLG, ZLIB_FLG_FDICT_OFFSET, ZLIB_FLG_FDICT_BITS ),
- FLEVEL => bits($FLG, ZLIB_FLG_LEVEL_OFFSET, ZLIB_FLG_LEVEL_BITS ),
- DICTID => $DICTID ,
-
-};
-}
-
-
-sub checkParams
-{
- my $class = shift ;
- my $type = shift ;
-
-
- my $Valid = {
- #'Input' => [Parse_store_ref, undef],
-
- 'BlockSize' => [Parse_unsigned, 16 * 1024],
- 'AutoClose' => [Parse_boolean, 0],
- 'Strict' => [Parse_boolean, 0],
- #'Lax' => [Parse_boolean, 1],
- 'Append' => [Parse_boolean, 0],
- 'Prime' => [Parse_any, undef],
- 'MultiStream' => [Parse_boolean, 0],
- 'Transparent' => [Parse_any, 1],
- 'Scan' => [Parse_boolean, 0],
- 'InputLength' => [Parse_unsigned, undef],
- 'BinModeOut' => [Parse_boolean, 0],
- #'Todo - Revert to ordinary file on end Z_STREAM_END'=> 0,
- # ContinueAfterEof
- } ;
-
- $Valid->{'ParseExtra'} = [Parse_boolean, 0]
- if $type eq 'rfc1952' ;
-
- my $got = Compress::Zlib::ParseParameters::new();
-
- $got->parse($Valid, @_ )
- or croak "$class: $got->{Error}" ;
-
- return $got;
-}
-
-sub new
-{
- my $class = shift ;
- my $type = shift ;
- my $got = shift;
- my $error_ref = shift ;
- my $append_mode = shift ;
-
- croak("$class: Missing Input parameter")
- if ! @_ && ! $got ;
-
- my $inValue = shift ;
-
- if (! $got)
- {
- $got = checkParams($class, $type, @_)
- or return undef ;
- }
-
- my $inType = whatIsInput($inValue, 1);
-
- ckInputParam($class, $inValue, $error_ref, 1)
- or return undef ;
-
- my $obj = bless Symbol::gensym(), ref($class) || $class;
- tie *$obj, $obj if $] >= 5.005;
-
-
- $$error_ref = '' ;
- *$obj->{Error} = $error_ref ;
- *$obj->{InNew} = 1;
-
- if ($inType eq 'buffer' || $inType eq 'code') {
- *$obj->{Buffer} = $inValue ;
- *$obj->{InputEvent} = $inValue
- if $inType eq 'code' ;
- }
- else {
- if ($inType eq 'handle') {
- *$obj->{FH} = $inValue ;
- *$obj->{Handle} = 1 ;
- # Need to rewind for Scan
- #seek(*$obj->{FH}, 0, SEEK_SET) if $got->value('Scan');
- *$obj->{FH}->seek(0, SEEK_SET) if $got->value('Scan');
- }
- else {
- my $mode = '<';
- $mode = '+<' if $got->value('Scan');
- *$obj->{StdIO} = ($inValue eq '-');
- *$obj->{FH} = new IO::File "$mode $inValue"
- or return $obj->saveErrorString(undef, "cannot open file '$inValue': $!", $!) ;
- *$obj->{LineNo} = 0;
- }
-
- setBinModeInput(*$obj->{FH}) ;
-
- my $buff = "" ;
- *$obj->{Buffer} = \$buff ;
- }
-
-
- *$obj->{InputLength} = $got->parsed('InputLength')
- ? $got->value('InputLength')
- : undef ;
- *$obj->{InputLengthRemaining} = $got->value('InputLength');
- *$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->{Transparent} = $got->value('Transparent');
- *$obj->{MultiStream} = $got->value('MultiStream');
- *$obj->{Scan} = $got->value('Scan');
- *$obj->{ParseExtra} = $got->value('ParseExtra')
- || $got->value('Strict') ;
- #|| ! $got->value('Lax') ;
- *$obj->{Type} = $type;
- *$obj->{Prime} = $got->value('Prime') || '' ;
- *$obj->{Pending} = '';
- *$obj->{Plain} = 0;
- *$obj->{PlainBytesRead} = 0;
- *$obj->{InflatedBytesRead} = 0;
- *$obj->{ISize} = 0;
- *$obj->{TotalInflatedBytesRead} = 0;
- *$obj->{NewStream} = 0 ;
- *$obj->{EventEof} = 0 ;
- *$obj->{ClassName} = $class ;
-
- my $status;
-
- if (*$obj->{Scan})
- {
- (*$obj->{Inflate}, $status) = new Compress::Zlib::InflateScan
- -CRC32 => $type eq 'rfc1952' ||
- $type eq 'any',
- -ADLER32 => $type eq 'rfc1950' ||
- $type eq 'any',
- -WindowBits => - MAX_WBITS ;
- }
- else
- {
- (*$obj->{Inflate}, $status) = new Compress::Zlib::Inflate
- -AppendOutput => 1,
- -CRC32 => $type eq 'rfc1952' ||
- $type eq 'any',
- -ADLER32 => $type eq 'rfc1950' ||
- $type eq 'any',
- -WindowBits => - MAX_WBITS ;
- }
-
- return $obj->saveErrorString(undef, "Could not create Inflation object: $status")
- if $obj->saveStatus($status) != Z_OK ;
-
- if ($type eq 'rfc1952')
- {
- *$obj->{Info} = $obj->_readFullGzipHeader() ;
- }
- elsif ($type eq 'zip')
- {
- *$obj->{Info} = $obj->_readFullZipHeader() ;
- }
- elsif ($type eq 'rfc1950')
- {
- *$obj->{Info} = $obj->_readDeflateHeader() ;
- }
- elsif ($type eq 'rfc1951')
- {
- *$obj->{Info} = $obj->_isRaw() ;
- }
- elsif ($type eq 'any')
- {
- *$obj->{Info} = $obj->_guessCompression() ;
- }
-
- if (! defined *$obj->{Info})
- {
- return undef unless *$obj->{Transparent};
-
- *$obj->{Type} = 'plain';
- *$obj->{Plain} = 1;
- *$obj->{PlainBytesRead} = length *$obj->{HeaderPending} ;
- }
-
- push @{ *$obj->{InfoList} }, *$obj->{Info} ;
- *$obj->{Pending} = *$obj->{HeaderPending}
- if *$obj->{Plain} || *$obj->{Type} eq 'rfc1951';
-
- $obj->saveStatus(0) ;
- *$obj->{InNew} = 0;
-
- return $obj;
-}
-
-#sub _inf
-#{
-# my $class = shift ;
-# my $type = shift ;
-# my $error_ref = shift ;
-#
-# my $name = (caller(1))[3] ;
-#
-# croak "$name: expected at least 2 parameters\n"
-# unless @_ >= 2 ;
-#
-# my $input = shift ;
-# my $output = shift ;
-#
-# ckInOutParams($name, $input, $output, $error_ref)
-# or return undef ;
-#
-# my $outType = whatIs($output);
-#
-# my $gunzip = new($class, $type, $error_ref, 1, $input, @_)
-# or return undef ;
-#
-# my $fh ;
-# if ($outType eq 'filename') {
-# my $mode = '>' ;
-# $mode = '>>'
-# if *$gunzip->{Append} ;
-# $fh = new IO::File "$mode $output"
-# or return $gunzip->saveErrorString(undef, "cannot open file '$output': $!", $!) ;
-# }
-#
-# if ($outType eq 'handle') {
-# $fh = $output;
-# if (*$gunzip->{Append}) {
-# seek($fh, 0, SEEK_END)
-# or return $gunzip->saveErrorString(undef, "Cannot seek to end of output filehandle: $!", $!) ;
-# }
-# }
-#
-# my $buff = '' ;
-# $buff = $output if $outType eq 'buffer' ;
-# my $status ;
-# while (($status = $gunzip->read($buff)) > 0) {
-# if ($fh) {
-# print $fh $buff
-# or return $gunzip->saveErrorString(undef, "Error writing to output file: $!", $!);
-# }
-# }
-#
-# return undef
-# if $status < 0 ;
-#
-# $gunzip->close()
-# or return undef ;
-#
-# if ( $outType eq 'filename' ||
-# ($outType eq 'handle' && *$gunzip->{AutoClose})) {
-# $fh->close()
-# or return $gunzip->saveErrorString(undef, $!, $!);
-# }
-#
-# return 1 ;
-#}
-
-sub _inf
-{
- my $class = shift ;
- my $type = shift ;
- my $error_ref = shift ;
-
- my $name = (caller(1))[3] ;
-
- croak "$name: expected at least 1 parameters\n"
- unless @_ >= 1 ;
-
- my $input = shift ;
- my $haveOut = @_ ;
- my $output = shift ;
-
- my $x = new Validator($class, $type, $error_ref, $name, $input, $output)
- or return undef ;
-
- push @_, $output if $haveOut && $x->{Hash};
-
- my $got = checkParams($name, $type, @_)
- or return undef ;
-
- $x->{Got} = $got ;
-
- if ($x->{Hash})
- {
- while (my($k, $v) = each %$input)
- {
- $v = \$input->{$k}
- unless defined $v ;
-
- _singleTarget($x, 1, $k, $v, @_)
- or return undef ;
- }
-
- return keys %$input ;
- }
-
- if ($x->{GlobMap})
- {
- $x->{oneInput} = 1 ;
- foreach my $pair (@{ $x->{Pairs} })
- {
- my ($from, $to) = @$pair ;
- _singleTarget($x, 1, $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 ;
-
- _singleTarget($x, $inFile, $in, \$out, @_)
- 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 _singleTarget($x, 1, $input, $output, @_);
-
- croak "should not be here" ;
-}
-
-sub retErr
-{
- my $x = shift ;
- my $string = shift ;
-
- ${ $x->{Error} } = $string ;
-
- return undef ;
-}
-
-sub _singleTarget
-{
- my $x = shift ;
- my $inputIsFilename = shift;
- my $input = shift;
- my $output = shift;
-
- $x->{buff} = '' ;
-
- my $fh ;
- if ($x->{outType} eq 'filename') {
- my $mode = '>' ;
- $mode = '>>'
- if $x->{Got}->value('Append') ;
- $x->{fh} = new IO::File "$mode $output"
- or return retErr($x, "cannot open file '$output': $!") ;
- binmode $x->{fh} if $x->{Got}->valueOrDefault('BinModeOut');
-
- }
-
- elsif ($x->{outType} eq 'handle') {
- $x->{fh} = $output;
- binmode $x->{fh} if $x->{Got}->valueOrDefault('BinModeOut');
- if ($x->{Got}->value('Append')) {
- seek($x->{fh}, 0, SEEK_END)
- or return retErr($x, "Cannot seek to end of output filehandle: $!") ;
- }
- }
-
-
- elsif ($x->{outType} eq 'buffer' )
- {
- $$output = ''
- unless $x->{Got}->value('Append');
- $x->{buff} = $output ;
- }
-
- if ($x->{oneInput})
- {
- defined _rd2($x, $input, $inputIsFilename)
- or return undef;
- }
- else
- {
- my $inputIsFilename = ($x->{inType} ne 'array');
-
- for my $element ( ($x->{inType} eq 'hash') ? keys %$input : @$input)
- {
- defined _rd2($x, $element, $inputIsFilename)
- or return undef ;
- }
- }
-
-
- if ( ($x->{outType} eq 'filename' && $output ne '-') ||
- ($x->{outType} eq 'handle' && $x->{Got}->value('AutoClose'))) {
- $x->{fh}->close()
- or return retErr($x, $!);
- #or return $gunzip->saveErrorString(undef, $!, $!);
- delete $x->{fh};
- }
-
- return 1 ;
-}
-
-sub _rd2
-{
- my $x = shift ;
- my $input = shift;
- my $inputIsFilename = shift;
-
- my $gunzip = new($x->{Class}, $x->{Type}, $x->{Got}, $x->{Error}, 1, $input, @_)
- or return undef ;
-
- my $status ;
- my $fh = $x->{fh};
-
- while (($status = $gunzip->read($x->{buff})) > 0) {
- if ($fh) {
- print $fh $x->{buff}
- or return $gunzip->saveErrorString(undef, "Error writing to output file: $!", $!);
- $x->{buff} = '' ;
- }
- }
-
- return undef
- if $status < 0 ;
-
- $gunzip->close()
- or return undef ;
-
- return 1 ;
-}
-
-sub TIEHANDLE
-{
- return $_[0] if ref($_[0]);
- die "OOPS\n" ;
-
-}
-
-sub UNTIE
-{
- my $self = shift ;
-}
-
-
-sub getHeaderInfo
-{
- my $self = shift ;
- return *$self->{Info};
-}
-
-sub _raw_read
-{
- # return codes
- # >0 - ok, number of bytes read
- # =0 - ok, eof
- # <0 - not ok
-
- my $self = shift ;
-
- return G_EOF if *$self->{Closed} ;
- #return G_EOF if !length *$self->{Pending} && *$self->{EndStream} ;
- return G_EOF if *$self->{EndStream} ;
-
- my $buffer = shift ;
- my $scan_mode = shift ;
-
- if (*$self->{Plain}) {
- my $tmp_buff ;
- my $len = $self->smartRead(\$tmp_buff, *$self->{BlockSize}) ;
-
- return $self->saveErrorString(G_ERR, "Error reading data: $!", $!)
- if $len < 0 ;
-
- if ($len == 0 ) {
- *$self->{EndStream} = 1 ;
- }
- else {
- *$self->{PlainBytesRead} += $len ;
- $$buffer .= $tmp_buff;
- }
-
- return $len ;
- }
-
- if (*$self->{NewStream}) {
- *$self->{NewStream} = 0 ;
- *$self->{EndStream} = 0 ;
- *$self->{Inflate}->inflateReset();
-
- if (*$self->{Type} eq 'rfc1952')
- {
- *$self->{Info} = $self->_readFullGzipHeader() ;
- }
- elsif (*$self->{Type} eq 'zip')
- {
- *$self->{Info} = $self->_readFullZipHeader() ;
- }
- elsif (*$self->{Type} eq 'rfc1950')
- {
- *$self->{Info} = $self->_readDeflateHeader() ;
- }
- elsif (*$self->{Type} eq 'rfc1951')
- {
- *$self->{Info} = $self->_isRaw() ;
- *$self->{Pending} = *$self->{HeaderPending}
- if defined *$self->{Info} ;
- }
-
- return G_ERR unless defined *$self->{Info} ;
-
- push @{ *$self->{InfoList} }, *$self->{Info} ;
-
- if (*$self->{Type} eq 'rfc1951') {
- $$buffer .= *$self->{Pending} ;
- my $len = length *$self->{Pending} ;
- *$self->{Pending} = '';
- return $len;
- }
- }
-
- my $temp_buf ;
- my $status = $self->smartRead(\$temp_buf, *$self->{BlockSize}) ;
- return $self->saveErrorString(G_ERR, "Error Reading Data")
- if $status < 0 ;
-
- if ($status == 0 ) {
- *$self->{Closed} = 1 ;
- *$self->{EndStream} = 1 ;
- return $self->saveErrorString(G_ERR, "unexpected end of file", Z_DATA_ERROR);
- }
-
- my $before_len = defined $$buffer ? length $$buffer : 0 ;
- $status = *$self->{Inflate}->inflate(\$temp_buf, $buffer) ;
-
- return $self->saveErrorString(G_ERR, "Inflation Error: $status")
- unless $self->saveStatus($status) == Z_OK || $status == Z_STREAM_END ;
-
- my $buf_len = *$self->{Inflate}->inflateCount();
-
- # zlib before 1.2 needs an extra byte after the compressed data
- # for RawDeflate
- if ($status == Z_OK && *$self->{Type} eq 'rfc1951' && $self->smartEof()) {
- my $byte = ' ';
- $status = *$self->{Inflate}->inflate(\$byte, $buffer) ;
-
- $buf_len += *$self->{Inflate}->inflateCount();
-
- return $self->saveErrorString(G_ERR, "Inflation Error: $status")
- unless $self->saveStatus($status) == Z_OK || $status == Z_STREAM_END ;
- }
-
-
- return $self->saveErrorString(G_ERR, "unexpected end of file", Z_DATA_ERROR)
- if $status != Z_STREAM_END && $self->smartEof() ;
-
- *$self->{InflatedBytesRead} += $buf_len ;
- *$self->{TotalInflatedBytesRead} += $buf_len ;
- my $rest = GZIP_ISIZE_MAX - *$self->{ISize} ;
- if ($buf_len > $rest) {
- *$self->{ISize} = $buf_len - $rest - 1;
- }
- else {
- *$self->{ISize} += $buf_len ;
- }
-
- if ($status == Z_STREAM_END) {
-
- *$self->{EndStream} = 1 ;
-
- if (*$self->{Type} eq 'rfc1951' || ! *$self->{Info}{TrailerLength})
- {
- *$self->{Trailing} = $temp_buf . $self->getTrailingBuffer();
- }
- else
- {
- # Only rfc1950 & 1952 have a trailer
-
- my $trailer_size = *$self->{Info}{TrailerLength} ;
-
- #if ($scan_mode) {
- # my $offset = *$self->{Inflate}->getLastBufferOffset();
- # substr($temp_buf, 0, $offset) = '' ;
- #}
-
- if (length $temp_buf < $trailer_size) {
- my $buff;
- my $want = $trailer_size - length $temp_buf;
- my $got = $self->smartRead(\$buff, $want) ;
- if ($got != $want && *$self->{Strict} ) {
- my $len = length($temp_buf) + length($buff);
- return $self->TrailerError("trailer truncated. Expected " .
- "$trailer_size bytes, got $len");
- }
- $temp_buf .= $buff;
- }
-
- if (length $temp_buf >= $trailer_size) {
-
- #my $trailer = substr($temp_buf, 0, $trailer_size, '') ;
- my $trailer = substr($temp_buf, 0, $trailer_size) ;
- substr($temp_buf, 0, $trailer_size) = '' ;
-
- if (*$self->{Type} eq 'rfc1952') {
- # Check CRC & ISIZE
- my ($CRC32, $ISIZE) = unpack("V V", $trailer) ;
- *$self->{Info}{CRC32} = $CRC32;
- *$self->{Info}{ISIZE} = $ISIZE;
-
- if (*$self->{Strict}) {
- return $self->TrailerError("CRC mismatch")
- if $CRC32 != *$self->{Inflate}->crc32() ;
-
- my $exp_isize = *$self->{ISize};
- return $self->TrailerError("ISIZE mismatch. Got $ISIZE"
- . ", expected $exp_isize")
- if $ISIZE != $exp_isize ;
- }
- }
- elsif (*$self->{Type} eq 'zip') {
- # Check CRC & ISIZE
- my ($sig, $CRC32, $cSize, $uSize) = unpack("V V V V", $trailer) ;
- return $self->TrailerError("Data Descriptor signature")
- if $sig != 0x08074b50;
-
- if (*$self->{Strict}) {
- return $self->TrailerError("CRC mismatch")
- if $CRC32 != *$self->{Inflate}->crc32() ;
-
- }
- }
- elsif (*$self->{Type} eq 'rfc1950') {
- my $ADLER32 = unpack("N", $trailer) ;
- *$self->{Info}{ADLER32} = $ADLER32;
- return $self->TrailerError("CRC mismatch")
- if *$self->{Strict} && $ADLER32 != *$self->{Inflate}->adler32() ;
-
- }
-
- if (*$self->{MultiStream}
- && (length $temp_buf || ! $self->smartEof())){
- *$self->{NewStream} = 1 ;
- *$self->{EndStream} = 0 ;
- *$self->{Prime} = $temp_buf . *$self->{Prime} ;
- return $buf_len ;
- }
- }
-
- *$self->{Trailing} = $temp_buf .$self->getTrailingBuffer();
- }
- }
-
-
- # return the number of uncompressed bytes read
- return $buf_len ;
-}
-
-#sub isEndStream
-#{
-# my $self = shift ;
-# return *$self->{NewStream} ||
-# *$self->{EndStream} ;
-#}
-
-sub streamCount
-{
- my $self = shift ;
- return 1 if ! defined *$self->{InfoList};
- return scalar @{ *$self->{InfoList} } ;
-}
-
-sub read
-{
- # return codes
- # >0 - ok, number of bytes read
- # =0 - ok, eof
- # <0 - not ok
-
- my $self = shift ;
-
- return G_EOF if *$self->{Closed} ;
- return G_EOF if !length *$self->{Pending} && *$self->{EndStream} ;
-
- my $buffer ;
-
- #croak(*$self->{ClassName} . "::read: buffer parameter is read-only")
- # if Compress::Zlib::_readonly_ref($_[0]);
-
- if (ref $_[0] ) {
- croak(*$self->{ClassName} . "::read: buffer parameter is read-only")
- if readonly(${ $_[0] });
-
- croak *$self->{ClassName} . "::read: not a scalar reference $_[0]"
- unless ref $_[0] eq 'SCALAR' ;
- $buffer = $_[0] ;
- }
- else {
- croak(*$self->{ClassName} . "::read: buffer parameter is read-only")
- if readonly($_[0]);
-
- $buffer = \$_[0] ;
- }
-
- my $length = $_[1] ;
- my $offset = $_[2] || 0;
-
- # the core read will return 0 if asked for 0 bytes
- return 0 if defined $length && $length == 0 ;
-
- $length = $length || 0;
-
- croak(*$self->{ClassName} . "::read: length parameter is negative")
- if $length < 0 ;
-
- $$buffer = '' unless *$self->{AppendOutput} || $offset ;
-
- # Short-circuit if this is a simple read, with no length
- # or offset specified.
- unless ( $length || $offset) {
- if (length *$self->{Pending}) {
- $$buffer .= *$self->{Pending} ;
- my $len = length *$self->{Pending};
- *$self->{Pending} = '' ;
- return $len ;
- }
- else {
- my $len = 0;
- $len = $self->_raw_read($buffer)
- while ! *$self->{EndStream} && $len == 0 ;
- return $len ;
- }
- }
-
- # Need to jump through more hoops - either length or offset
- # or both are specified.
- #*$self->{Pending} = '' if ! length *$self->{Pending} ;
- my $out_buffer = \*$self->{Pending} ;
-
- while (! *$self->{EndStream} && length($$out_buffer) < $length)
- {
- my $buf_len = $self->_raw_read($out_buffer);
- return $buf_len
- if $buf_len < 0 ;
- }
-
- $length = length $$out_buffer
- if length($$out_buffer) < $length ;
-
- if ($offset) {
- $$buffer .= "\x00" x ($offset - length($$buffer))
- if $offset > length($$buffer) ;
- #substr($$buffer, $offset) = substr($$out_buffer, 0, $length, '') ;
- substr($$buffer, $offset) = substr($$out_buffer, 0, $length) ;
- substr($$out_buffer, 0, $length) = '' ;
- }
- else {
- #$$buffer .= substr($$out_buffer, 0, $length, '') ;
- $$buffer .= substr($$out_buffer, 0, $length) ;
- substr($$out_buffer, 0, $length) = '' ;
- }
-
- return $length ;
-}
-
-sub _getline
-{
- my $self = shift ;
-
- # Slurp Mode
- if ( ! defined $/ ) {
- my $data ;
- 1 while $self->read($data) > 0 ;
- return \$data ;
- }
-
- # Paragraph Mode
- if ( ! length $/ ) {
- my $paragraph ;
- while ($self->read($paragraph) > 0 ) {
- if ($paragraph =~ s/^(.*?\n\n+)//s) {
- *$self->{Pending} = $paragraph ;
- my $par = $1 ;
- return \$par ;
- }
- }
- return \$paragraph;
- }
-
- # Line Mode
- {
- my $line ;
- my $endl = quotemeta($/); # quote in case $/ contains RE meta chars
- while ($self->read($line) > 0 ) {
- if ($line =~ s/^(.*?$endl)//s) {
- *$self->{Pending} = $line ;
- $. = ++ *$self->{LineNo} ;
- my $l = $1 ;
- return \$l ;
- }
- }
- $. = ++ *$self->{LineNo} if defined($line);
- return \$line;
- }
-}
-
-sub getline
-{
- my $self = shift;
- my $current_append = *$self->{AppendOutput} ;
- *$self->{AppendOutput} = 1;
- my $lineref = $self->_getline();
- *$self->{AppendOutput} = $current_append;
- return $$lineref ;
-}
-
-sub getlines
-{
- my $self = shift;
- croak *$self->{ClassName} . "::getlines: called in scalar context\n" unless wantarray;
- my($line, @lines);
- push(@lines, $line) while defined($line = $self->getline);
- return @lines;
-}
-
-sub READLINE
-{
- goto &getlines if wantarray;
- goto &getline;
-}
-
-sub getc
-{
- my $self = shift;
- my $buf;
- return $buf if $self->read($buf, 1);
- return undef;
-}
-
-sub ungetc
-{
- my $self = shift;
- *$self->{Pending} = "" unless defined *$self->{Pending} ;
- *$self->{Pending} = $_[0] . *$self->{Pending} ;
-}
-
-sub trailingData
-{
- my $self = shift ;
- return \"" if ! defined *$self->{Trailing} ;
- return \*$self->{Trailing} ;
-}
-
-sub inflateSync
-{
- my $self = shift ;
-
- # inflateSync is a no-op in Plain mode
- return 1
- if *$self->{Plain} ;
-
- return 0 if *$self->{Closed} ;
- #return G_EOF if !length *$self->{Pending} && *$self->{EndStream} ;
- return 0 if ! length *$self->{Pending} && *$self->{EndStream} ;
-
- # Disable CRC check
- *$self->{Strict} = 0 ;
+1;
- my $status ;
- while (1)
- {
- my $temp_buf ;
-
- if (length *$self->{Pending} )
- {
- $temp_buf = *$self->{Pending} ;
- *$self->{Pending} = '';
- }
- else
- {
- $status = $self->smartRead(\$temp_buf, *$self->{BlockSize}) ;
- return $self->saveErrorString(0, "Error Reading Data")
- if $status < 0 ;
-
- if ($status == 0 ) {
- *$self->{EndStream} = 1 ;
- return $self->saveErrorString(0, "unexpected end of file", Z_DATA_ERROR);
- }
- }
-
- $status = *$self->{Inflate}->inflateSync($temp_buf) ;
-
- if ($status == Z_OK)
- {
- *$self->{Pending} .= $temp_buf ;
- return 1 ;
- }
-
- last unless $status = Z_DATA_ERROR ;
- }
-
- return 0;
-}
-
-sub eof
-{
- my $self = shift ;
-
- return (*$self->{Closed} ||
- (!length *$self->{Pending}
- && ( $self->smartEof() || *$self->{EndStream}))) ;
-}
-
-sub tell
-{
- my $self = shift ;
-
- my $in ;
- if (*$self->{Plain}) {
- $in = *$self->{PlainBytesRead} ;
- }
- else {
- $in = *$self->{TotalInflatedBytesRead} ;
- }
-
- my $pending = length *$self->{Pending} ;
-
- return 0 if $pending > $in ;
- return $in - $pending ;
-}
-
-sub close
-{
- # todo - what to do if close is called before the end of the gzip file
- # do we remember any trailing data?
- my $self = shift ;
-
- return 1 if *$self->{Closed} ;
-
- untie *$self
- if $] >= 5.008 ;
-
- my $status = 1 ;
-
- if (defined *$self->{FH}) {
- if ((! *$self->{Handle} || *$self->{AutoClose}) && ! *$self->{StdIO}) {
- #if ( *$self->{AutoClose}) {
- $! = 0 ;
- $status = *$self->{FH}->close();
- return $self->saveErrorString(0, $!, $!)
- if !*$self->{InNew} && $self->saveStatus($!) != 0 ;
- }
- delete *$self->{FH} ;
- $! = 0 ;
- }
- *$self->{Closed} = 1 ;
-
- return 1;
-}
-
-sub DESTROY
-{
- my $self = shift ;
- $self->close() ;
-}
-
-sub seek
-{
- my $self = shift ;
- my $position = shift;
- my $whence = shift ;
-
- my $here = $self->tell() ;
- my $target = 0 ;
-
-
- if ($whence == SEEK_SET) {
- $target = $position ;
- }
- elsif ($whence == SEEK_CUR) {
- $target = $here + $position ;
- }
- elsif ($whence == SEEK_END) {
- $target = $position ;
- croak *$self->{ClassName} . "::seek: SEEK_END not allowed" ;
- }
- else {
- croak *$self->{ClassName} ."::seek: unknown value, $whence, for whence parameter";
- }
-
- # short circuit if seeking to current offset
- return 1 if $target == $here ;
-
- # Outlaw any attempt to seek backwards
- croak *$self->{ClassName} ."::seek: cannot seek backwards"
- if $target < $here ;
-
- # Walk the file to the new offset
- my $offset = $target - $here ;
-
- my $buffer ;
- $self->read($buffer, $offset) == $offset
- or return 0 ;
-
- return 1 ;
-}
-
-sub fileno
-{
- my $self = shift ;
- return defined *$self->{FH}
- ? fileno *$self->{FH}
- : undef ;
-}
-
-sub binmode
-{
- 1;
-# my $self = shift ;
-# return defined *$self->{FH}
-# ? binmode *$self->{FH}
-# : 1 ;
-}
-
-*BINMODE = \&binmode;
-*SEEK = \&seek;
-*READ = \&read;
-*sysread = \&read;
-*TELL = \&tell;
-*EOF = \&eof;
-
-*FILENO = \&fileno;
-*CLOSE = \&close;
-
-sub _notAvailable
-{
- my $name = shift ;
- #return sub { croak "$name Not Available" ; } ;
- return sub { croak "$name Not Available: File opened only for intput" ; } ;
-}
-
-
-*print = _notAvailable('print');
-*PRINT = _notAvailable('print');
-*printf = _notAvailable('printf');
-*PRINTF = _notAvailable('printf');
-*write = _notAvailable('write');
-*WRITE = _notAvailable('write');
-
-#*sysread = \&read;
-#*syswrite = \&_notAvailable;
-
-#package IO::_infScan ;
-#
-#*_raw_read = \&IO::BaseInflate::_raw_read ;
-#*smartRead = \&IO::BaseInflate::smartRead ;
-#*smartWrite = \&IO::BaseInflate::smartWrite ;
-#*smartSeek = \&IO::BaseInflate::smartSeek ;
-
-sub scan
-{
- my $self = shift ;
-
- return 1 if *$self->{Closed} ;
- return 1 if !length *$self->{Pending} && *$self->{EndStream} ;
-
- my $buffer = '' ;
- my $len = 0;
-
- $len = $self->_raw_read(\$buffer, 1)
- while ! *$self->{EndStream} && $len >= 0 ;
-
- #return $len if $len < 0 ? $len : 0 ;
- return $len < 0 ? 0 : 1 ;
-}
-
-sub zap
-{
- my $self = shift ;
-
- my $headerLength = *$self->{Info}{HeaderLength};
- my $block_offset = $headerLength + *$self->{Inflate}->getLastBlockOffset();
- $_[0] = $headerLength + *$self->{Inflate}->getEndOffset();
- #printf "# End $_[0], headerlen $headerLength \n";;
-
- #printf "# block_offset $block_offset %x\n", $block_offset;
- my $byte ;
- ( $self->smartSeek($block_offset) &&
- $self->smartRead(\$byte, 1) )
- or return $self->saveErrorString(0, $!, $!);
-
- #printf "#byte is %x\n", unpack('C*',$byte);
- *$self->{Inflate}->resetLastBlockByte($byte);
- #printf "#to byte is %x\n", unpack('C*',$byte);
-
- ( $self->smartSeek($block_offset) &&
- $self->smartWrite($byte) )
- or return $self->saveErrorString(0, $!, $!);
-
- #$self->smartSeek($end_offset, 1);
-
- return 1 ;
-}
-
-sub createDeflate
-{
- my $self = shift ;
- my ($status, $def) = *$self->{Inflate}->createDeflateStream(
- -AppendOutput => 1,
- -WindowBits => - MAX_WBITS,
- -CRC32 => *$self->{Type} eq 'rfc1952'
- || *$self->{Type} eq 'zip',
- -ADLER32 => *$self->{Type} eq 'rfc1950',
- );
-
- return wantarray ? ($status, $def) : $def ;
-}
-
-
-package IO::Uncompress::Gunzip ;
-
-1 ;
__END__
@@ -1886,34 +360,34 @@ B<WARNING -- This is a Beta release>.
-This module provides a Perl interface that allows the reading of
+This module provides a Perl interface that allows the reading of
files/buffers that conform to RFC 1952.
-For writing RFC 1952 files/buffers, see the companion module
-IO::Compress::Gzip.
+For writing RFC 1952 files/buffers, see the companion module IO::Compress::Gzip.
=head1 Functional Interface
-A top-level function, C<gunzip>, is provided to carry out "one-shot"
-uncompression between buffers and/or files. For finer control over the uncompression process, see the L</"OO Interface"> section.
+A top-level function, C<gunzip>, is provided to carry out
+"one-shot" uncompression between buffers and/or files. For finer
+control over the uncompression process, see the L</"OO Interface">
+section.
use IO::Uncompress::Gunzip qw(gunzip $GunzipError) ;
gunzip $input => $output [,OPTS]
or die "gunzip failed: $GunzipError\n";
- gunzip \%hash [,OPTS]
- or die "gunzip failed: $GunzipError\n";
+
The functional interface needs Perl5.005 or better.
=head2 gunzip $input => $output [, OPTS]
-If the first parameter is not a hash reference C<gunzip> expects
-at least two parameters, C<$input> and C<$output>.
+
+C<gunzip> expects at least two parameters, C<$input> and C<$output>.
=head3 The C<$input> parameter
@@ -1943,13 +417,15 @@ from C<$$input>.
=item An array reference
-If C<$input> is an array reference, the input data will be read from each
-element of the array in turn. The action taken by C<gunzip> with
-each element of the array will depend on the type of data stored
-in it. You can mix and match any of the types defined in this list,
-excluding other array or hash references.
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
The complete array will be walked to ensure that it only
-contains valid data types before any data is uncompressed.
+contains valid filenames before any data is uncompressed.
+
+
=item An Input FileGlob string
@@ -1977,36 +453,28 @@ uncompressed data. This parameter can take one of these forms.
=item A filename
-If the C<$output> parameter is a simple scalar, it is assumed to be a filename.
-This file will be opened for writing and the uncompressed data will be
-written to it.
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the uncompressed
+data will be written to it.
=item A filehandle
-If the C<$output> parameter is a filehandle, the uncompressed data will
-be written to it.
+If the C<$output> parameter is a filehandle, the uncompressed data
+will be written to it.
The string '-' can be used as an alias for standard output.
=item A scalar reference
-If C<$output> is a scalar reference, the uncompressed data will be stored
-in C<$$output>.
+If C<$output> is a scalar reference, the uncompressed data will be
+stored in C<$$output>.
-=item A Hash Reference
-
-If C<$output> is a hash reference, the uncompressed data will be written
-to C<$output{$input}> as a scalar reference.
-
-When C<$output> is a hash reference, C<$input> must be either a filename or
-list of filenames. Anything else is an error.
-
=item An Array Reference
-If C<$output> is an array reference, the uncompressed data will be pushed
-onto the array.
+If C<$output> is an array reference, the uncompressed data will be
+pushed onto the array.
=item An Output FileGlob
@@ -2021,60 +489,13 @@ string. Anything else is an error.
If the C<$output> parameter is any other type, C<undef> will be returned.
-=head2 gunzip \%hash [, OPTS]
-
-If the first parameter is a hash reference, C<\%hash>, this will be used to
-define both the source of compressed data and to control where the
-uncompressed data is output. Each key/value pair in the hash defines a
-mapping between an input filename, stored in the key, and an output
-file/buffer, stored in the value. Although the input can only be a filename,
-there is more flexibility to control the destination of the uncompressed
-data. This is determined by the type of the value. Valid types are
-=over 5
-
-=item undef
-
-If the value is C<undef> the uncompressed data will be written to the
-value as a scalar reference.
-
-=item A filename
-
-If the value is a simple scalar, it is assumed to be a filename. This file will
-be opened for writing and the uncompressed data will be written to it.
-
-=item A filehandle
-
-If the value is a filehandle, the uncompressed data will be
-written to it.
-The string '-' can be used as an alias for standard output.
-
-
-=item A scalar reference
-
-If the value is a scalar reference, the uncompressed data will be stored
-in the buffer that is referenced by the scalar.
-
-
-=item A Hash Reference
-
-If the value is a hash reference, the uncompressed data will be written
-to C<$hash{$input}> as a scalar reference.
-
-=item An Array Reference
-
-If C<$output> is an array reference, the uncompressed data will be pushed
-onto the array.
-
-=back
-
-Any other type is a error.
=head2 Notes
When C<$input> maps to multiple files/buffers and C<$output> is a single
-file/buffer the uncompressed input files/buffers will all be stored in
-C<$output> as a single uncompressed stream.
+file/buffer the uncompressed input files/buffers will all be stored
+in C<$output> as a single uncompressed stream.
@@ -2088,8 +509,8 @@ L</"Constructor Options"> section below.
=item AutoClose =E<gt> 0|1
-This option applies to any input or output data streams to C<gunzip>
-that are filehandles.
+This option applies to any input or output data streams to
+C<gunzip> that are filehandles.
If C<AutoClose> is specified, and the value is true, it will result in all
input and/or output filehandles being closed once C<gunzip> has
@@ -2099,10 +520,27 @@ This parameter defaults to 0.
+=item BinModeOut =E<gt> 0|1
+
+When writing to a file or filehandle, set C<binmode> before writing to the
+file.
+
+Defaults to 0.
+
+
+
+
+
=item -Append =E<gt> 0|1
TODO
+=item -MultiStream =E<gt> 0|1
+
+Creates a new stream after each file.
+
+Defaults to 1.
+
=back
@@ -2175,11 +613,11 @@ The format of the constructor for IO::Uncompress::Gunzip is shown below
Returns an C<IO::Uncompress::Gunzip> object on success and undef on failure.
The variable C<$GunzipError> will contain an error message on failure.
-If you are running Perl 5.005 or better the object, C<$z>, returned from
-IO::Uncompress::Gunzip can be used exactly like an L<IO::File|IO::File> filehandle.
-This means that all normal input file operations can be carried out with C<$z>.
-For example, to read a line from a compressed file/buffer you can use either
-of these forms
+If you are running Perl 5.005 or better the object, C<$z>, returned from
+IO::Uncompress::Gunzip can be used exactly like an L<IO::File|IO::File> filehandle.
+This means that all normal input file operations can be carried out with
+C<$z>. For example, to read a line from a compressed file/buffer you can
+use either of these forms
$line = $z->getline();
$line = <$z>;
@@ -2253,8 +691,9 @@ input file/buffer.
This option can be useful when the compressed data is embedded in another
file/data structure and it is not possible to work out where the compressed
-data begins without having to read the first few bytes. If this is the case,
-the uncompression can be I<primed> with these bytes using this option.
+data begins without having to read the first few bytes. If this is the
+case, the uncompression can be I<primed> with these bytes using this
+option.
=item -Transparent =E<gt> 0|1
@@ -2265,20 +704,21 @@ This option defaults to 1.
=item -BlockSize =E<gt> $num
-When reading the compressed input data, IO::Uncompress::Gunzip will read it in blocks
-of C<$num> bytes.
+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<gt> $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 situation
-where there is useful data directly after the compressed data stream and you
-know beforehand the exact length of the compressed data stream.
+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
+situation where there is useful data directly after the compressed data
+stream and you know beforehand the exact length of the compressed data
+stream.
-This option is mostly used when reading from a filehandle, in which case the
-file pointer will be left pointing to the first byte directly after the
+This option is mostly used when reading from a filehandle, in which case
+the file pointer will be left pointing to the first byte directly after the
compressed data stream.
@@ -2289,11 +729,11 @@ This option defaults to off.
This option controls what the C<read> method does with uncompressed data.
-If set to 1, all uncompressed data will be appended to the output parameter of
-the C<read> method.
+If set to 1, all uncompressed data will be appended to the output parameter
+of the C<read> method.
-If set to 0, the contents of the output parameter of the C<read> method will be
-overwritten by the uncompressed data.
+If set to 0, the contents of the output parameter of the C<read> method
+will be overwritten by the uncompressed data.
Defaults to 0.
@@ -2302,8 +742,8 @@ Defaults to 0.
This option controls whether the extra checks defined below are used when
-carrying out the decompression. When Strict is on, the extra tests are carried
-out, when Strict is off they are not.
+carrying out the decompression. When Strict is on, the extra tests are
+carried out, when Strict is off they are not.
The default for this option is off.
@@ -2329,8 +769,8 @@ If the gzip header contains a name field (FNAME) it consists solely of ISO
=item 3
-If the gzip header contains a comment field (FCOMMENT) it consists solely of
-ISO 8859-1 characters plus line-feed.
+If the gzip header contains a comment field (FCOMMENT) it consists solely
+of ISO 8859-1 characters plus line-feed.
=item 4
@@ -2348,8 +788,8 @@ uncompressed data actually contained in the gzip file.
=item 7
-The value of the ISIZE fields read must match the length of the uncompressed
-data actually read from the file.
+The value of the ISIZE fields read must match the length of the
+uncompressed data actually read from the file.
=back
@@ -2386,12 +826,12 @@ Usage is
Reads a block of compressed data (the size the the compressed block is
determined by the C<Buffer> option in the constructor), uncompresses it and
-writes any uncompressed data into C<$buffer>. If the C<Append> parameter is set
-in the constructor, the uncompressed data will be appended to the C<$buffer>
-parameter. Otherwise C<$buffer> will be overwritten.
+writes any uncompressed data into C<$buffer>. If the C<Append> parameter is
+set in the constructor, the uncompressed data will be appended to the
+C<$buffer> parameter. Otherwise C<$buffer> will be overwritten.
-Returns the number of uncompressed bytes written to C<$buffer>, zero if eof or
-a negative number on error.
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
=head2 read
@@ -2405,13 +845,13 @@ Usage is
Attempt to read C<$length> bytes of uncompressed data into C<$buffer>.
-The main difference between this form of the C<read> method and the previous
-one, is that this one will attempt to return I<exactly> C<$length> bytes. The
-only circumstances that this function will not is if end-of-file or an IO error
-is encountered.
+The main difference between this form of the C<read> method and the
+previous one, is that this one will attempt to return I<exactly> C<$length>
+bytes. The only circumstances that this function will not is if end-of-file
+or an IO error is encountered.
-Returns the number of uncompressed bytes written to C<$buffer>, zero if eof or
-a negative number on error.
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
=head2 getline
@@ -2456,29 +896,28 @@ TODO
Usage is
- $hdr = $z->getHeaderInfo()
-
-TODO
-
-
-
-
-
-This method returns a hash reference that contains the contents of each of the
-header fields defined in RFC1952.
+ $hdr = $z->getHeaderInfo();
+ @hdrs = $z->getHeaderInfo();
+This method returns either a hash reference (in scalar context) or a list
+or hash references (in array context) that contains information about each
+of the header fields in the compressed data stream(s).
+=over 5
+=item Name
-=over 5
+The contents of the Name header field, if present. If no name is
+present, the value will be undef. Note this is different from a zero length
+name, which will return an empty string.
=item Comment
-The contents of the Comment header field, if present. If no comment is present,
-the value will be undef. Note this is different from a zero length comment,
-which will return an empty string.
+The contents of the Comment header field, if present. If no comment is
+present, the value will be undef. Note this is different from a zero length
+comment, which will return an empty string.
=back
@@ -2633,7 +1072,7 @@ See the Changes file.
=head1 COPYRIGHT AND LICENSE
-Copyright (c) 2005 Paul Marquess. All rights reserved.
+Copyright (c) 2005-2006 Paul Marquess. All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
diff --git a/ext/Compress/Zlib/lib/IO/Uncompress/Inflate.pm b/ext/Compress/Zlib/lib/IO/Uncompress/Inflate.pm
index 656b78a1b5..4193917288 100644
--- a/ext/Compress/Zlib/lib/IO/Uncompress/Inflate.pm
+++ b/ext/Compress/Zlib/lib/IO/Uncompress/Inflate.pm
@@ -3,33 +3,172 @@ package IO::Uncompress::Inflate ;
use strict ;
use warnings;
-use IO::Uncompress::Gunzip ;
+use Compress::Zlib::Common qw(createSelfTiedObject);
+use Compress::Zlib::FileConstants;
+
+use IO::Uncompress::RawInflate ;
require Exporter ;
our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $InflateError);
-$VERSION = '2.000_05';
+$VERSION = '2.000_07';
$InflateError = '';
-@ISA = qw( Exporter IO::BaseInflate );
+@ISA = qw( Exporter IO::Uncompress::RawInflate );
@EXPORT_OK = qw( $InflateError inflate ) ;
-%EXPORT_TAGS = %IO::BaseInflate::EXPORT_TAGS ;
+%EXPORT_TAGS = %IO::Uncompress::RawInflate::DEFLATE_CONSTANTS ;
push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
Exporter::export_ok_tags('all');
sub new
{
- my $pkg = shift ;
- return IO::BaseInflate::new($pkg, 'rfc1950', undef, \$InflateError, 0, @_);
+ my $class = shift ;
+ my $obj = createSelfTiedObject($class, \$InflateError);
+
+ $obj->_create(undef, 0, @_);
}
sub inflate
{
- return IO::BaseInflate::_inf(__PACKAGE__, 'rfc1950', \$InflateError, @_);
+ my $obj = createSelfTiedObject(undef, \$InflateError);
+ return $obj->_inf(@_);
+}
+
+sub getExtraParams
+{
+ return ();
+}
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ # gunzip always needs adler32
+ $got->value('ADLER32' => 1);
+
+ return 1;
+}
+
+sub ckMagic
+{
+ my $self = shift;
+
+ my $magic ;
+ $self->smartReadExact(\$magic, ZLIB_HEADER_SIZE);
+
+ *$self->{HeaderPending} = $magic ;
+
+ return $self->HeaderError("Header size is " .
+ ZLIB_HEADER_SIZE . " bytes")
+ if length $magic != ZLIB_HEADER_SIZE;
+
+ return $self->HeaderError("CRC mismatch.")
+ if ! isZlibMagic($magic) ;
+
+ *$self->{Type} = 'rfc1950';
+ return $magic;
+}
+
+sub readHeader
+{
+ my $self = shift;
+ my $magic = shift ;
+
+ return $self->_readDeflateHeader($magic) ;
+}
+
+sub chkTrailer
+{
+ my $self = shift;
+ my $trailer = shift;
+
+ my $ADLER32 = unpack("N", $trailer) ;
+ *$self->{Info}{ADLER32} = $ADLER32;
+ return $self->TrailerError("CRC mismatch")
+ if *$self->{Strict} && $ADLER32 != *$self->{Uncomp}->adler32() ;
+
+ return 1;
+}
+
+
+
+sub isZlibMagic
+{
+ my $buffer = shift ;
+ return 0 if length $buffer < ZLIB_HEADER_SIZE ;
+ my $hdr = unpack("n", $buffer) ;
+ return $hdr % 31 == 0 ;
}
+sub bits
+{
+ my $data = shift ;
+ my $offset = shift ;
+ my $mask = shift ;
+
+ ($data >> $offset ) & $mask & 0xFF ;
+}
+
+
+sub _readDeflateHeader
+{
+ my ($self, $buffer) = @_ ;
+
+# if (! $buffer) {
+# $self->smartReadExact(\$buffer, ZLIB_HEADER_SIZE);
+#
+# *$self->{HeaderPending} = $buffer ;
+#
+# return $self->HeaderError("Header size is " .
+# ZLIB_HEADER_SIZE . " bytes")
+# if length $buffer != ZLIB_HEADER_SIZE;
+#
+# return $self->HeaderError("CRC mismatch.")
+# if ! isZlibMagic($buffer) ;
+# }
+
+ my ($CMF, $FLG) = unpack "C C", $buffer;
+ my $FDICT = bits($FLG, ZLIB_FLG_FDICT_OFFSET, ZLIB_FLG_FDICT_BITS ),
+
+ my $cm = bits($CMF, ZLIB_CMF_CM_OFFSET, ZLIB_CMF_CM_BITS) ;
+ $cm == ZLIB_CMF_CM_DEFLATED
+ or return $self->HeaderError("Not Deflate (CM is $cm)") ;
+
+ my $DICTID;
+ if ($FDICT) {
+ $self->smartReadExact(\$buffer, ZLIB_FDICT_SIZE)
+ or return $self->TruncatedHeader("FDICT");
+
+ $DICTID = unpack("N", $buffer) ;
+ }
+
+ *$self->{Type} = 'rfc1950';
+
+ return {
+ 'Type' => 'rfc1950',
+ 'FingerprintLength' => ZLIB_HEADER_SIZE,
+ 'HeaderLength' => ZLIB_HEADER_SIZE,
+ 'TrailerLength' => ZLIB_TRAILER_SIZE,
+ 'Header' => $buffer,
+
+ CMF => $CMF ,
+ CM => bits($CMF, ZLIB_CMF_CM_OFFSET, ZLIB_CMF_CM_BITS ),
+ CINFO => bits($CMF, ZLIB_CMF_CINFO_OFFSET, ZLIB_CMF_CINFO_BITS ),
+ FLG => $FLG ,
+ FCHECK => bits($FLG, ZLIB_FLG_FCHECK_OFFSET, ZLIB_FLG_FCHECK_BITS),
+ FDICT => bits($FLG, ZLIB_FLG_FDICT_OFFSET, ZLIB_FLG_FDICT_BITS ),
+ FLEVEL => bits($FLG, ZLIB_FLG_LEVEL_OFFSET, ZLIB_FLG_LEVEL_BITS ),
+ DICTID => $DICTID ,
+
+ };
+}
+
+
+
+
1 ;
__END__
@@ -103,34 +242,34 @@ B<WARNING -- This is a Beta release>.
-This module provides a Perl interface that allows the reading of
+This module provides a Perl interface that allows the reading of
files/buffers that conform to RFC 1950.
-For writing RFC 1950 files/buffers, see the companion module
-IO::Compress::Deflate.
+For writing RFC 1950 files/buffers, see the companion module IO::Compress::Deflate.
=head1 Functional Interface
-A top-level function, C<inflate>, is provided to carry out "one-shot"
-uncompression between buffers and/or files. For finer control over the uncompression process, see the L</"OO Interface"> section.
+A top-level function, C<inflate>, is provided to carry out
+"one-shot" uncompression between buffers and/or files. For finer
+control over the uncompression process, see the L</"OO Interface">
+section.
use IO::Uncompress::Inflate qw(inflate $InflateError) ;
inflate $input => $output [,OPTS]
or die "inflate failed: $InflateError\n";
- inflate \%hash [,OPTS]
- or die "inflate failed: $InflateError\n";
+
The functional interface needs Perl5.005 or better.
=head2 inflate $input => $output [, OPTS]
-If the first parameter is not a hash reference C<inflate> expects
-at least two parameters, C<$input> and C<$output>.
+
+C<inflate> expects at least two parameters, C<$input> and C<$output>.
=head3 The C<$input> parameter
@@ -160,13 +299,15 @@ from C<$$input>.
=item An array reference
-If C<$input> is an array reference, the input data will be read from each
-element of the array in turn. The action taken by C<inflate> with
-each element of the array will depend on the type of data stored
-in it. You can mix and match any of the types defined in this list,
-excluding other array or hash references.
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
The complete array will be walked to ensure that it only
-contains valid data types before any data is uncompressed.
+contains valid filenames before any data is uncompressed.
+
+
=item An Input FileGlob string
@@ -194,36 +335,28 @@ uncompressed data. This parameter can take one of these forms.
=item A filename
-If the C<$output> parameter is a simple scalar, it is assumed to be a filename.
-This file will be opened for writing and the uncompressed data will be
-written to it.
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the uncompressed
+data will be written to it.
=item A filehandle
-If the C<$output> parameter is a filehandle, the uncompressed data will
-be written to it.
+If the C<$output> parameter is a filehandle, the uncompressed data
+will be written to it.
The string '-' can be used as an alias for standard output.
=item A scalar reference
-If C<$output> is a scalar reference, the uncompressed data will be stored
-in C<$$output>.
-
-
-=item A Hash Reference
-
-If C<$output> is a hash reference, the uncompressed data will be written
-to C<$output{$input}> as a scalar reference.
+If C<$output> is a scalar reference, the uncompressed data will be
+stored in C<$$output>.
-When C<$output> is a hash reference, C<$input> must be either a filename or
-list of filenames. Anything else is an error.
=item An Array Reference
-If C<$output> is an array reference, the uncompressed data will be pushed
-onto the array.
+If C<$output> is an array reference, the uncompressed data will be
+pushed onto the array.
=item An Output FileGlob
@@ -238,60 +371,13 @@ string. Anything else is an error.
If the C<$output> parameter is any other type, C<undef> will be returned.
-=head2 inflate \%hash [, OPTS]
-
-If the first parameter is a hash reference, C<\%hash>, this will be used to
-define both the source of compressed data and to control where the
-uncompressed data is output. Each key/value pair in the hash defines a
-mapping between an input filename, stored in the key, and an output
-file/buffer, stored in the value. Although the input can only be a filename,
-there is more flexibility to control the destination of the uncompressed
-data. This is determined by the type of the value. Valid types are
-
-=over 5
-
-=item undef
-
-If the value is C<undef> the uncompressed data will be written to the
-value as a scalar reference.
-
-=item A filename
-
-If the value is a simple scalar, it is assumed to be a filename. This file will
-be opened for writing and the uncompressed data will be written to it.
-
-=item A filehandle
-
-If the value is a filehandle, the uncompressed data will be
-written to it.
-The string '-' can be used as an alias for standard output.
-
-
-=item A scalar reference
-
-If the value is a scalar reference, the uncompressed data will be stored
-in the buffer that is referenced by the scalar.
-
-
-=item A Hash Reference
-
-If the value is a hash reference, the uncompressed data will be written
-to C<$hash{$input}> as a scalar reference.
-
-=item An Array Reference
-If C<$output> is an array reference, the uncompressed data will be pushed
-onto the array.
-
-=back
-
-Any other type is a error.
=head2 Notes
When C<$input> maps to multiple files/buffers and C<$output> is a single
-file/buffer the uncompressed input files/buffers will all be stored in
-C<$output> as a single uncompressed stream.
+file/buffer the uncompressed input files/buffers will all be stored
+in C<$output> as a single uncompressed stream.
@@ -305,8 +391,8 @@ L</"Constructor Options"> section below.
=item AutoClose =E<gt> 0|1
-This option applies to any input or output data streams to C<inflate>
-that are filehandles.
+This option applies to any input or output data streams to
+C<inflate> that are filehandles.
If C<AutoClose> is specified, and the value is true, it will result in all
input and/or output filehandles being closed once C<inflate> has
@@ -316,10 +402,27 @@ This parameter defaults to 0.
+=item BinModeOut =E<gt> 0|1
+
+When writing to a file or filehandle, set C<binmode> before writing to the
+file.
+
+Defaults to 0.
+
+
+
+
+
=item -Append =E<gt> 0|1
TODO
+=item -MultiStream =E<gt> 0|1
+
+Creates a new stream after each file.
+
+Defaults to 1.
+
=back
@@ -392,11 +495,11 @@ The format of the constructor for IO::Uncompress::Inflate is shown below
Returns an C<IO::Uncompress::Inflate> object on success and undef on failure.
The variable C<$InflateError> will contain an error message on failure.
-If you are running Perl 5.005 or better the object, C<$z>, returned from
-IO::Uncompress::Inflate can be used exactly like an L<IO::File|IO::File> filehandle.
-This means that all normal input file operations can be carried out with C<$z>.
-For example, to read a line from a compressed file/buffer you can use either
-of these forms
+If you are running Perl 5.005 or better the object, C<$z>, returned from
+IO::Uncompress::Inflate can be used exactly like an L<IO::File|IO::File> filehandle.
+This means that all normal input file operations can be carried out with
+C<$z>. For example, to read a line from a compressed file/buffer you can
+use either of these forms
$line = $z->getline();
$line = <$z>;
@@ -470,8 +573,9 @@ input file/buffer.
This option can be useful when the compressed data is embedded in another
file/data structure and it is not possible to work out where the compressed
-data begins without having to read the first few bytes. If this is the case,
-the uncompression can be I<primed> with these bytes using this option.
+data begins without having to read the first few bytes. If this is the
+case, the uncompression can be I<primed> with these bytes using this
+option.
=item -Transparent =E<gt> 0|1
@@ -482,20 +586,21 @@ This option defaults to 1.
=item -BlockSize =E<gt> $num
-When reading the compressed input data, IO::Uncompress::Inflate will read it in blocks
-of C<$num> bytes.
+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<gt> $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 situation
-where there is useful data directly after the compressed data stream and you
-know beforehand the exact length of the compressed data stream.
+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
+situation where there is useful data directly after the compressed data
+stream and you know beforehand the exact length of the compressed data
+stream.
-This option is mostly used when reading from a filehandle, in which case the
-file pointer will be left pointing to the first byte directly after the
+This option is mostly used when reading from a filehandle, in which case
+the file pointer will be left pointing to the first byte directly after the
compressed data stream.
@@ -506,11 +611,11 @@ This option defaults to off.
This option controls what the C<read> method does with uncompressed data.
-If set to 1, all uncompressed data will be appended to the output parameter of
-the C<read> method.
+If set to 1, all uncompressed data will be appended to the output parameter
+of the C<read> method.
-If set to 0, the contents of the output parameter of the C<read> method will be
-overwritten by the uncompressed data.
+If set to 0, the contents of the output parameter of the C<read> method
+will be overwritten by the uncompressed data.
Defaults to 0.
@@ -519,8 +624,8 @@ Defaults to 0.
This option controls whether the extra checks defined below are used when
-carrying out the decompression. When Strict is on, the extra tests are carried
-out, when Strict is off they are not.
+carrying out the decompression. When Strict is on, the extra tests are
+carried out, when Strict is off they are not.
The default for this option is off.
@@ -565,12 +670,12 @@ Usage is
Reads a block of compressed data (the size the the compressed block is
determined by the C<Buffer> option in the constructor), uncompresses it and
-writes any uncompressed data into C<$buffer>. If the C<Append> parameter is set
-in the constructor, the uncompressed data will be appended to the C<$buffer>
-parameter. Otherwise C<$buffer> will be overwritten.
+writes any uncompressed data into C<$buffer>. If the C<Append> parameter is
+set in the constructor, the uncompressed data will be appended to the
+C<$buffer> parameter. Otherwise C<$buffer> will be overwritten.
-Returns the number of uncompressed bytes written to C<$buffer>, zero if eof or
-a negative number on error.
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
=head2 read
@@ -584,13 +689,13 @@ Usage is
Attempt to read C<$length> bytes of uncompressed data into C<$buffer>.
-The main difference between this form of the C<read> method and the previous
-one, is that this one will attempt to return I<exactly> C<$length> bytes. The
-only circumstances that this function will not is if end-of-file or an IO error
-is encountered.
+The main difference between this form of the C<read> method and the
+previous one, is that this one will attempt to return I<exactly> C<$length>
+bytes. The only circumstances that this function will not is if end-of-file
+or an IO error is encountered.
-Returns the number of uncompressed bytes written to C<$buffer>, zero if eof or
-a negative number on error.
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
=head2 getline
@@ -635,19 +740,12 @@ TODO
Usage is
- $hdr = $z->getHeaderInfo()
-
-TODO
-
-
-
-
-
-This method returns a hash reference that contains the contents of each of the
-header fields defined in RFC1950.
-
-
+ $hdr = $z->getHeaderInfo();
+ @hdrs = $z->getHeaderInfo();
+This method returns either a hash reference (in scalar context) or a list
+or hash references (in array context) that contains information about each
+of the header fields in the compressed data stream(s).
@@ -800,7 +898,7 @@ See the Changes file.
=head1 COPYRIGHT AND LICENSE
-Copyright (c) 2005 Paul Marquess. All rights reserved.
+Copyright (c) 2005-2006 Paul Marquess. All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
diff --git a/ext/Compress/Zlib/lib/IO/Uncompress/RawInflate.pm b/ext/Compress/Zlib/lib/IO/Uncompress/RawInflate.pm
index 45cad1a5dc..756a10c163 100644
--- a/ext/Compress/Zlib/lib/IO/Uncompress/RawInflate.pm
+++ b/ext/Compress/Zlib/lib/IO/Uncompress/RawInflate.pm
@@ -3,34 +3,326 @@ package IO::Uncompress::RawInflate ;
use strict ;
use warnings;
-use IO::Uncompress::Gunzip;
+
+use Compress::Zlib 2 ;
+use Compress::Zlib::Common qw(:Status createSelfTiedObject);
+use Compress::Zlib::ParseParameters ;
+
+use IO::Uncompress::Base ;
+use UncompressPlugin::Inflate ;
+
+
+
require Exporter ;
-our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $RawInflateError);
+our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, %DEFLATE_CONSTANTS, $RawInflateError);
-$VERSION = '2.000_05';
+$VERSION = '2.000_07';
$RawInflateError = '';
-@ISA = qw(Exporter IO::BaseInflate);
+@ISA = qw( Exporter IO::Uncompress::Base );
@EXPORT_OK = qw( $RawInflateError rawinflate ) ;
-%EXPORT_TAGS = %IO::BaseInflate::EXPORT_TAGS ;
+%DEFLATE_CONSTANTS = ();
+%EXPORT_TAGS = %IO::Uncompress::Base::EXPORT_TAGS ;
push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
Exporter::export_ok_tags('all');
-
sub new
{
- my $pkg = shift ;
- return IO::BaseInflate::new($pkg, 'rfc1951', undef, \$RawInflateError, 0, @_);
+ my $class = shift ;
+ my $obj = createSelfTiedObject($class, \$RawInflateError);
+ $obj->_create(undef, 0, @_);
}
sub rawinflate
{
- return IO::BaseInflate::_inf(__PACKAGE__, 'rfc1951', \$RawInflateError, @_);
+ my $obj = createSelfTiedObject(undef, \$RawInflateError);
+ return $obj->_inf(@_);
+}
+
+sub getExtraParams
+{
+ return ();
+}
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ return 1;
+}
+
+sub mkUncomp
+{
+ my $self = shift ;
+ my $class = shift ;
+ my $got = shift ;
+
+ my ($obj, $errstr, $errno) = UncompressPlugin::Inflate::mkUncompObject(
+ $got->value('CRC32'),
+ $got->value('ADLER32'),
+ $got->value('Scan'),
+ );
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ *$self->{Uncomp} = $obj;
+
+ my $magic = $self->ckMagic()
+ or return 0;
+
+ *$self->{Info} = $self->readHeader($magic)
+ or return undef ;
+
+ return 1;
+
+}
+
+
+sub ckMagic
+{
+ my $self = shift;
+
+ return $self->_isRaw() ;
+}
+
+sub readHeader
+{
+ my $self = shift;
+ my $magic = shift ;
+
+ return {
+ 'Type' => 'rfc1951',
+ 'FingerprintLength' => 0,
+ 'HeaderLength' => 0,
+ 'TrailerLength' => 0,
+ 'Header' => ''
+ };
+}
+
+sub chkTrailer
+{
+ return 1 ;
+}
+
+sub _isRaw
+{
+ my $self = shift ;
+
+ my $got = $self->_isRawx(@_);
+
+ if ($got) {
+ *$self->{Pending} = *$self->{HeaderPending} ;
+ }
+ else {
+ $self->pushBack(*$self->{HeaderPending});
+ *$self->{Uncomp}->reset();
+ }
+ *$self->{HeaderPending} = '';
+
+ return $got ;
}
+sub _isRawx
+{
+ my $self = shift ;
+ my $magic = shift ;
+
+ $magic = '' unless defined $magic ;
+
+ my $buffer = '';
+
+ $self->smartRead(\$buffer, *$self->{BlockSize}) >= 0
+ or return $self->saveErrorString(undef, "No data to read");
+
+ my $temp_buf = $magic . $buffer ;
+ *$self->{HeaderPending} = $temp_buf ;
+ $buffer = '';
+ my $status = *$self->{Uncomp}->uncompr(\$temp_buf, \$buffer, $self->smartEof()) ;
+ return $self->saveErrorString(undef, *$self->{Uncomp}{Error}, STATUS_ERROR)
+ if $status == STATUS_ERROR;
+
+ my $buf_len = *$self->{Uncomp}->count();
+
+ if ($status == STATUS_ENDSTREAM) {
+ if (*$self->{MultiStream}
+ && (length $temp_buf || ! $self->smartEof())){
+ *$self->{NewStream} = 1 ;
+ *$self->{EndStream} = 0 ;
+ $self->pushBack($temp_buf);
+ }
+ else {
+ *$self->{EndStream} = 1 ;
+ $self->pushBack($temp_buf);
+ }
+ }
+ *$self->{HeaderPending} = $buffer ;
+ *$self->{InflatedBytesRead} = $buf_len ;
+ *$self->{TotalInflatedBytesRead} += $buf_len ;
+ *$self->{Type} = 'rfc1951';
+
+ $self->saveStatus(STATUS_OK);
+
+ return {
+ 'Type' => 'rfc1951',
+ 'HeaderLength' => 0,
+ 'TrailerLength' => 0,
+ 'Header' => ''
+ };
+}
+
+
+sub inflateSync
+{
+ my $self = shift ;
+
+ # inflateSync is a no-op in Plain mode
+ return 1
+ if *$self->{Plain} ;
+
+ return 0 if *$self->{Closed} ;
+ #return G_EOF if !length *$self->{Pending} && *$self->{EndStream} ;
+ return 0 if ! length *$self->{Pending} && *$self->{EndStream} ;
+
+ # Disable CRC check
+ *$self->{Strict} = 0 ;
+
+ my $status ;
+ while (1)
+ {
+ my $temp_buf ;
+
+ if (length *$self->{Pending} )
+ {
+ $temp_buf = *$self->{Pending} ;
+ *$self->{Pending} = '';
+ }
+ else
+ {
+ $status = $self->smartRead(\$temp_buf, *$self->{BlockSize}) ;
+ return $self->saveErrorString(0, "Error Reading Data")
+ if $status < 0 ;
+
+ if ($status == 0 ) {
+ *$self->{EndStream} = 1 ;
+ return $self->saveErrorString(0, "unexpected end of file", STATUS_ERROR);
+ }
+ }
+
+ $status = *$self->{Uncomp}->sync($temp_buf) ;
+
+ if ($status == STATUS_OK)
+ {
+ *$self->{Pending} .= $temp_buf ;
+ return 1 ;
+ }
+
+ last unless $status == STATUS_ERROR ;
+ }
+
+ return 0;
+}
+
+#sub performScan
+#{
+# my $self = shift ;
+#
+# my $status ;
+# my $end_offset = 0;
+#
+# $status = $self->scan()
+# #or return $self->saveErrorString(undef, "Error Scanning: $$error_ref", $self->errorNo) ;
+# or return $self->saveErrorString(G_ERR, "Error Scanning: $status")
+#
+# $status = $self->zap($end_offset)
+# or return $self->saveErrorString(G_ERR, "Error Zapping: $status");
+# #or return $self->saveErrorString(undef, "Error Zapping: $$error_ref", $self->errorNo) ;
+#
+# #(*$obj->{Deflate}, $status) = $inf->createDeflate();
+#
+## *$obj->{Header} = *$inf->{Info}{Header};
+## *$obj->{UnCompSize_32bit} =
+## *$obj->{BytesWritten} = *$inf->{UnCompSize_32bit} ;
+## *$obj->{CompSize_32bit} = *$inf->{CompSize_32bit} ;
+#
+#
+## if ( $outType eq 'buffer')
+## { substr( ${ *$self->{Buffer} }, $end_offset) = '' }
+## elsif ($outType eq 'handle' || $outType eq 'filename') {
+## *$self->{FH} = *$inf->{FH} ;
+## delete *$inf->{FH};
+## *$obj->{FH}->flush() ;
+## *$obj->{Handle} = 1 if $outType eq 'handle';
+##
+## #seek(*$obj->{FH}, $end_offset, SEEK_SET)
+## *$obj->{FH}->seek($end_offset, SEEK_SET)
+## or return $obj->saveErrorString(undef, $!, $!) ;
+## }
+#
+#}
+
+sub scan
+{
+ my $self = shift ;
+
+ return 1 if *$self->{Closed} ;
+ return 1 if !length *$self->{Pending} && *$self->{EndStream} ;
+
+ my $buffer = '' ;
+ my $len = 0;
+
+ $len = $self->_raw_read(\$buffer, 1)
+ while ! *$self->{EndStream} && $len >= 0 ;
+
+ #return $len if $len < 0 ? $len : 0 ;
+ return $len < 0 ? 0 : 1 ;
+}
+
+sub zap
+{
+ my $self = shift ;
+
+ my $headerLength = *$self->{Info}{HeaderLength};
+ my $block_offset = $headerLength + *$self->{Uncomp}->getLastBlockOffset();
+ $_[0] = $headerLength + *$self->{Uncomp}->getEndOffset();
+ #printf "# End $_[0], headerlen $headerLength \n";;
+ #printf "# block_offset $block_offset %x\n", $block_offset;
+ my $byte ;
+ ( $self->smartSeek($block_offset) &&
+ $self->smartRead(\$byte, 1) )
+ or return $self->saveErrorString(0, $!, $!);
+
+ #printf "#byte is %x\n", unpack('C*',$byte);
+ *$self->{Uncomp}->resetLastBlockByte($byte);
+ #printf "#to byte is %x\n", unpack('C*',$byte);
+
+ ( $self->smartSeek($block_offset) &&
+ $self->smartWrite($byte) )
+ or return $self->saveErrorString(0, $!, $!);
+
+ #$self->smartSeek($end_offset, 1);
+
+ return 1 ;
+}
+
+sub createDeflate
+{
+ my $self = shift ;
+ my ($def, $status) = *$self->{Uncomp}->createDeflateStream(
+ -AppendOutput => 1,
+ -WindowBits => - MAX_WBITS,
+ -CRC32 => *$self->{Params}->value('CRC32'),
+ -ADLER32 => *$self->{Params}->value('ADLER32'),
+ );
+
+ return wantarray ? ($status, $def) : $def ;
+}
+
+
1;
__END__
@@ -104,34 +396,34 @@ B<WARNING -- This is a Beta release>.
-This module provides a Perl interface that allows the reading of
+This module provides a Perl interface that allows the reading of
files/buffers that conform to RFC 1951.
-For writing RFC 1951 files/buffers, see the companion module
-IO::Compress::RawDeflate.
+For writing RFC 1951 files/buffers, see the companion module IO::Compress::RawDeflate.
=head1 Functional Interface
-A top-level function, C<rawinflate>, is provided to carry out "one-shot"
-uncompression between buffers and/or files. For finer control over the uncompression process, see the L</"OO Interface"> section.
+A top-level function, C<rawinflate>, is provided to carry out
+"one-shot" uncompression between buffers and/or files. For finer
+control over the uncompression process, see the L</"OO Interface">
+section.
use IO::Uncompress::RawInflate qw(rawinflate $RawInflateError) ;
rawinflate $input => $output [,OPTS]
or die "rawinflate failed: $RawInflateError\n";
- rawinflate \%hash [,OPTS]
- or die "rawinflate failed: $RawInflateError\n";
+
The functional interface needs Perl5.005 or better.
=head2 rawinflate $input => $output [, OPTS]
-If the first parameter is not a hash reference C<rawinflate> expects
-at least two parameters, C<$input> and C<$output>.
+
+C<rawinflate> expects at least two parameters, C<$input> and C<$output>.
=head3 The C<$input> parameter
@@ -161,13 +453,15 @@ from C<$$input>.
=item An array reference
-If C<$input> is an array reference, the input data will be read from each
-element of the array in turn. The action taken by C<rawinflate> with
-each element of the array will depend on the type of data stored
-in it. You can mix and match any of the types defined in this list,
-excluding other array or hash references.
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
The complete array will be walked to ensure that it only
-contains valid data types before any data is uncompressed.
+contains valid filenames before any data is uncompressed.
+
+
=item An Input FileGlob string
@@ -195,36 +489,28 @@ uncompressed data. This parameter can take one of these forms.
=item A filename
-If the C<$output> parameter is a simple scalar, it is assumed to be a filename.
-This file will be opened for writing and the uncompressed data will be
-written to it.
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the uncompressed
+data will be written to it.
=item A filehandle
-If the C<$output> parameter is a filehandle, the uncompressed data will
-be written to it.
+If the C<$output> parameter is a filehandle, the uncompressed data
+will be written to it.
The string '-' can be used as an alias for standard output.
=item A scalar reference
-If C<$output> is a scalar reference, the uncompressed data will be stored
-in C<$$output>.
+If C<$output> is a scalar reference, the uncompressed data will be
+stored in C<$$output>.
-=item A Hash Reference
-
-If C<$output> is a hash reference, the uncompressed data will be written
-to C<$output{$input}> as a scalar reference.
-
-When C<$output> is a hash reference, C<$input> must be either a filename or
-list of filenames. Anything else is an error.
-
=item An Array Reference
-If C<$output> is an array reference, the uncompressed data will be pushed
-onto the array.
+If C<$output> is an array reference, the uncompressed data will be
+pushed onto the array.
=item An Output FileGlob
@@ -239,60 +525,13 @@ string. Anything else is an error.
If the C<$output> parameter is any other type, C<undef> will be returned.
-=head2 rawinflate \%hash [, OPTS]
-
-If the first parameter is a hash reference, C<\%hash>, this will be used to
-define both the source of compressed data and to control where the
-uncompressed data is output. Each key/value pair in the hash defines a
-mapping between an input filename, stored in the key, and an output
-file/buffer, stored in the value. Although the input can only be a filename,
-there is more flexibility to control the destination of the uncompressed
-data. This is determined by the type of the value. Valid types are
-
-=over 5
-
-=item undef
-
-If the value is C<undef> the uncompressed data will be written to the
-value as a scalar reference.
-=item A filename
-
-If the value is a simple scalar, it is assumed to be a filename. This file will
-be opened for writing and the uncompressed data will be written to it.
-
-=item A filehandle
-
-If the value is a filehandle, the uncompressed data will be
-written to it.
-The string '-' can be used as an alias for standard output.
-
-
-=item A scalar reference
-
-If the value is a scalar reference, the uncompressed data will be stored
-in the buffer that is referenced by the scalar.
-
-
-=item A Hash Reference
-
-If the value is a hash reference, the uncompressed data will be written
-to C<$hash{$input}> as a scalar reference.
-
-=item An Array Reference
-
-If C<$output> is an array reference, the uncompressed data will be pushed
-onto the array.
-
-=back
-
-Any other type is a error.
=head2 Notes
When C<$input> maps to multiple files/buffers and C<$output> is a single
-file/buffer the uncompressed input files/buffers will all be stored in
-C<$output> as a single uncompressed stream.
+file/buffer the uncompressed input files/buffers will all be stored
+in C<$output> as a single uncompressed stream.
@@ -306,8 +545,8 @@ L</"Constructor Options"> section below.
=item AutoClose =E<gt> 0|1
-This option applies to any input or output data streams to C<rawinflate>
-that are filehandles.
+This option applies to any input or output data streams to
+C<rawinflate> that are filehandles.
If C<AutoClose> is specified, and the value is true, it will result in all
input and/or output filehandles being closed once C<rawinflate> has
@@ -317,10 +556,27 @@ This parameter defaults to 0.
+=item BinModeOut =E<gt> 0|1
+
+When writing to a file or filehandle, set C<binmode> before writing to the
+file.
+
+Defaults to 0.
+
+
+
+
+
=item -Append =E<gt> 0|1
TODO
+=item -MultiStream =E<gt> 0|1
+
+Creates a new stream after each file.
+
+Defaults to 1.
+
=back
@@ -393,11 +649,11 @@ The format of the constructor for IO::Uncompress::RawInflate is shown below
Returns an C<IO::Uncompress::RawInflate> object on success and undef on failure.
The variable C<$RawInflateError> will contain an error message on failure.
-If you are running Perl 5.005 or better the object, C<$z>, returned from
-IO::Uncompress::RawInflate can be used exactly like an L<IO::File|IO::File> filehandle.
-This means that all normal input file operations can be carried out with C<$z>.
-For example, to read a line from a compressed file/buffer you can use either
-of these forms
+If you are running Perl 5.005 or better the object, C<$z>, returned from
+IO::Uncompress::RawInflate can be used exactly like an L<IO::File|IO::File> filehandle.
+This means that all normal input file operations can be carried out with
+C<$z>. For example, to read a line from a compressed file/buffer you can
+use either of these forms
$line = $z->getline();
$line = <$z>;
@@ -465,8 +721,9 @@ input file/buffer.
This option can be useful when the compressed data is embedded in another
file/data structure and it is not possible to work out where the compressed
-data begins without having to read the first few bytes. If this is the case,
-the uncompression can be I<primed> with these bytes using this option.
+data begins without having to read the first few bytes. If this is the
+case, the uncompression can be I<primed> with these bytes using this
+option.
=item -Transparent =E<gt> 0|1
@@ -477,20 +734,21 @@ This option defaults to 1.
=item -BlockSize =E<gt> $num
-When reading the compressed input data, IO::Uncompress::RawInflate will read it in blocks
-of C<$num> bytes.
+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<gt> $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 situation
-where there is useful data directly after the compressed data stream and you
-know beforehand the exact length of the compressed data stream.
+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
+situation where there is useful data directly after the compressed data
+stream and you know beforehand the exact length of the compressed data
+stream.
-This option is mostly used when reading from a filehandle, in which case the
-file pointer will be left pointing to the first byte directly after the
+This option is mostly used when reading from a filehandle, in which case
+the file pointer will be left pointing to the first byte directly after the
compressed data stream.
@@ -501,11 +759,11 @@ This option defaults to off.
This option controls what the C<read> method does with uncompressed data.
-If set to 1, all uncompressed data will be appended to the output parameter of
-the C<read> method.
+If set to 1, all uncompressed data will be appended to the output parameter
+of the C<read> method.
-If set to 0, the contents of the output parameter of the C<read> method will be
-overwritten by the uncompressed data.
+If set to 0, the contents of the output parameter of the C<read> method
+will be overwritten by the uncompressed data.
Defaults to 0.
@@ -535,12 +793,12 @@ Usage is
Reads a block of compressed data (the size the the compressed block is
determined by the C<Buffer> option in the constructor), uncompresses it and
-writes any uncompressed data into C<$buffer>. If the C<Append> parameter is set
-in the constructor, the uncompressed data will be appended to the C<$buffer>
-parameter. Otherwise C<$buffer> will be overwritten.
+writes any uncompressed data into C<$buffer>. If the C<Append> parameter is
+set in the constructor, the uncompressed data will be appended to the
+C<$buffer> parameter. Otherwise C<$buffer> will be overwritten.
-Returns the number of uncompressed bytes written to C<$buffer>, zero if eof or
-a negative number on error.
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
=head2 read
@@ -554,13 +812,13 @@ Usage is
Attempt to read C<$length> bytes of uncompressed data into C<$buffer>.
-The main difference between this form of the C<read> method and the previous
-one, is that this one will attempt to return I<exactly> C<$length> bytes. The
-only circumstances that this function will not is if end-of-file or an IO error
-is encountered.
+The main difference between this form of the C<read> method and the
+previous one, is that this one will attempt to return I<exactly> C<$length>
+bytes. The only circumstances that this function will not is if end-of-file
+or an IO error is encountered.
-Returns the number of uncompressed bytes written to C<$buffer>, zero if eof or
-a negative number on error.
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
=head2 getline
@@ -605,17 +863,12 @@ TODO
Usage is
- $hdr = $z->getHeaderInfo()
-
-TODO
-
-
-
-
-
-
-
+ $hdr = $z->getHeaderInfo();
+ @hdrs = $z->getHeaderInfo();
+This method returns either a hash reference (in scalar context) or a list
+or hash references (in array context) that contains information about each
+of the header fields in the compressed data stream(s).
@@ -768,7 +1021,7 @@ See the Changes file.
=head1 COPYRIGHT AND LICENSE
-Copyright (c) 2005 Paul Marquess. All rights reserved.
+Copyright (c) 2005-2006 Paul Marquess. All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
diff --git a/ext/Compress/Zlib/lib/IO/Uncompress/Unzip.pm b/ext/Compress/Zlib/lib/IO/Uncompress/Unzip.pm
new file mode 100644
index 0000000000..df108a569e
--- /dev/null
+++ b/ext/Compress/Zlib/lib/IO/Uncompress/Unzip.pm
@@ -0,0 +1,459 @@
+package IO::Uncompress::Unzip;
+
+require 5.004 ;
+
+# for RFC1952
+
+use strict ;
+use warnings;
+
+use IO::Uncompress::RawInflate ;
+use Compress::Zlib::Common qw(createSelfTiedObject);
+use UncompressPlugin::Identity;
+
+require Exporter ;
+
+our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $UnzipError);
+
+$VERSION = '2.000_05';
+$UnzipError = '';
+
+@ISA = qw(Exporter IO::Uncompress::RawInflate);
+@EXPORT_OK = qw( $UnzipError unzip );
+%EXPORT_TAGS = %IO::Uncompress::RawInflate::EXPORT_TAGS ;
+push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
+Exporter::export_ok_tags('all');
+
+
+sub new
+{
+ my $class = shift ;
+ my $obj = createSelfTiedObject($class, \$UnzipError);
+ $obj->_create(undef, 0, @_);
+}
+
+sub unzip
+{
+ my $obj = createSelfTiedObject(undef, \$UnzipError);
+ return $obj->_inf(@_) ;
+}
+
+sub getExtraParams
+{
+ use Compress::Zlib::ParseParameters;
+
+
+ return (
+# # Zip header fields
+ 'Name' => [1, 1, Parse_any, undef],
+
+# 'Streaming' => [1, 1, Parse_boolean, 1],
+ );
+}
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ # unzip always needs crc32
+ $got->value('CRC32' => 1);
+
+ *$self->{UnzipData}{Name} = $got->value('Name');
+
+ return 1;
+}
+
+
+sub ckMagic
+{
+ my $self = shift;
+
+ my $magic ;
+ $self->smartReadExact(\$magic, 4);
+
+ *$self->{HeaderPending} = $magic ;
+
+ return $self->HeaderError("Minimum header size is " .
+ 4 . " bytes")
+ if length $magic != 4 ;
+
+ return $self->HeaderError("Bad Magic")
+ if ! _isZipMagic($magic) ;
+
+ *$self->{Type} = 'zip';
+
+ return $magic ;
+}
+
+
+
+sub readHeader
+{
+ my $self = shift;
+ my $magic = shift ;
+
+ my $name = *$self->{UnzipData}{Name} ;
+ my $status = $self->_readZipHeader($magic) ;
+
+ while (defined $status)
+ {
+ if (! defined $name || $status->{Name} eq $name)
+ {
+ return $status ;
+ }
+
+ # skip the data
+ my $c = $status->{CompressedLength};
+ my $buffer;
+ $self->smartReadExact(\$buffer, $c)
+ or return $self->saveErrorString(undef, "Truncated file");
+
+ # skip the trailer
+ $c = $status->{TrailerLength};
+ $self->smartReadExact(\$buffer, $c)
+ or return $self->saveErrorString(undef, "Truncated file");
+
+ $self->chkTrailer($buffer)
+ or return $self->saveErrorString(undef, "Truncated file");
+
+ $status = $self->_readFullZipHeader();
+
+ return $self->saveErrorString(undef, "Cannot find '$name'")
+ if $self->smartEof();
+ }
+
+ return undef;
+}
+
+sub chkTrailer
+{
+ my $self = shift;
+ my $trailer = shift;
+
+ my ($sig, $CRC32, $cSize, $uSize) ;
+ if (*$self->{ZipData}{Streaming}) {
+ ($sig, $CRC32, $cSize, $uSize) = unpack("V V V V", $trailer) ;
+ return $self->TrailerError("Data Descriptor signature")
+ if $sig != 0x08074b50;
+ }
+ else {
+ ($CRC32, $cSize, $uSize) =
+ (*$self->{ZipData}{Crc32},
+ *$self->{ZipData}{CompressedLen},
+ *$self->{ZipData}{UnCompressedLen});
+ }
+
+ if (*$self->{Strict}) {
+ #return $self->TrailerError("CRC mismatch")
+ # if $CRC32 != *$self->{Uncomp}->crc32() ;
+
+ my $exp_isize = *$self->{Uncomp}->compressedBytes();
+ return $self->TrailerError("CSIZE mismatch. Got $cSize"
+ . ", expected $exp_isize")
+ if $cSize != $exp_isize ;
+
+ $exp_isize = *$self->{Uncomp}->uncompressedBytes();
+ return $self->TrailerError("USIZE mismatch. Got $uSize"
+ . ", expected $exp_isize")
+ if $uSize != $exp_isize ;
+ }
+
+ # check for central directory or end of central directory
+ while (1)
+ {
+ my $magic ;
+ $self->smartReadExact(\$magic, 4);
+ my $sig = unpack("V", $magic) ;
+
+ if ($sig == 0x02014b50)
+ {
+ $self->skipCentralDirectory($magic);
+ }
+ elsif ($sig == 0x06054b50)
+ {
+ $self->skipEndCentralDirectory($magic);
+ last;
+ }
+ else
+ {
+ # put the data back
+ $self->pushBack($magic) ;
+ last;
+ }
+ }
+
+ return 1 ;
+}
+
+sub skipCentralDirectory
+{
+ my $self = shift;
+ my $magic = shift ;
+
+ my $buffer;
+ $self->smartReadExact(\$buffer, 46 - 4)
+ or return $self->HeaderError("Minimum header size is " .
+ 46 . " bytes") ;
+
+ my $keep = $magic . $buffer ;
+ *$self->{HeaderPending} = $keep ;
+
+ #my $versionMadeBy = unpack ("v", substr($buffer, 4-4, 2));
+ #my $extractVersion = unpack ("v", substr($buffer, 6-4, 2));
+ #my $gpFlag = unpack ("v", substr($buffer, 8-4, 2));
+ #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 $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));
+ #my $disk_start = unpack ("v", substr($buffer, 34-4, 2));
+ #my $int_file_attrib = unpack ("v", substr($buffer, 36-4, 2));
+ #my $ext_file_attrib = unpack ("V", substr($buffer, 38-4, 2));
+ #my $lcl_hdr_offset = unpack ("V", substr($buffer, 42-4, 2));
+
+
+ my $filename;
+ my $extraField;
+ my $comment ;
+ if ($filename_length)
+ {
+ $self->smartReadExact(\$filename, $filename_length)
+ or return $self->HeaderError("xxx");
+ $keep .= $filename ;
+ }
+
+ if ($extra_length)
+ {
+ $self->smartReadExact(\$extraField, $extra_length)
+ or return $self->HeaderError("xxx");
+ $keep .= $extraField ;
+ }
+
+ if ($comment_length)
+ {
+ $self->smartReadExact(\$comment, $comment_length)
+ or return $self->HeaderError("xxx");
+ $keep .= $comment ;
+ }
+
+ return 1 ;
+}
+
+sub skipEndCentralDirectory
+{
+ my $self = shift;
+ my $magic = shift ;
+
+ my $buffer;
+ $self->smartReadExact(\$buffer, 22 - 4)
+ or return $self->HeaderError("Minimum header size is " .
+ 22 . " bytes") ;
+
+ my $keep = $magic . $buffer ;
+ *$self->{HeaderPending} = $keep ;
+
+ #my $diskNumber = unpack ("v", substr($buffer, 4-4, 2));
+ #my $cntrlDirDiskNo = unpack ("v", substr($buffer, 6-4, 2));
+ #my $entriesInThisCD = unpack ("v", substr($buffer, 8-4, 2));
+ #my $entriesInCD = unpack ("v", substr($buffer, 10-4, 2));
+ #my $sizeOfCD = unpack ("V", substr($buffer, 12-4, 2));
+ #my $offsetToCD = unpack ("V", substr($buffer, 16-4, 2));
+ my $comment_length = unpack ("v", substr($buffer, 20-4, 2));
+
+
+ my $comment ;
+ if ($comment_length)
+ {
+ $self->smartReadExact(\$comment, $comment_length)
+ or return $self->HeaderError("xxx");
+ $keep .= $comment ;
+ }
+
+ return 1 ;
+}
+
+
+
+
+sub _isZipMagic
+{
+ my $buffer = shift ;
+ return 0 if length $buffer < 4 ;
+ my $sig = unpack("V", $buffer) ;
+ return $sig == 0x04034b50 ;
+}
+
+
+sub _readFullZipHeader($)
+{
+ my ($self) = @_ ;
+ my $magic = '' ;
+
+ $self->smartReadExact(\$magic, 4);
+
+ *$self->{HeaderPending} = $magic ;
+
+ return $self->HeaderError("Minimum header size is " .
+ 30 . " bytes")
+ if length $magic != 4 ;
+
+
+ return $self->HeaderError("Bad Magic")
+ if ! _isZipMagic($magic) ;
+
+ my $status = $self->_readZipHeader($magic);
+ delete *$self->{Transparent} if ! defined $status ;
+ return $status ;
+}
+
+sub _readZipHeader($)
+{
+ my ($self, $magic) = @_ ;
+ my ($HeaderCRC) ;
+ my ($buffer) = '' ;
+
+ $self->smartReadExact(\$buffer, 30 - 4)
+ or return $self->HeaderError("Minimum header size is " .
+ 30 . " bytes") ;
+
+ my $keep = $magic . $buffer ;
+ *$self->{HeaderPending} = $keep ;
+
+ my $extractVersion = unpack ("v", substr($buffer, 4-4, 2));
+ my $gpFlag = unpack ("v", substr($buffer, 6-4, 2));
+ 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 $filename_length = unpack ("v", substr($buffer, 26-4, 2));
+ my $extra_length = unpack ("v", substr($buffer, 28-4, 2));
+
+ my $filename;
+ my $extraField;
+ my $streamingMode = ($gpFlag & 0x08) ? 1 : 0 ;
+
+ return $self->HeaderError("Streamed Stored content not supported")
+ if $streamingMode && $compressedMethod == 0 ;
+
+ *$self->{ZipData}{Streaming} = $streamingMode;
+
+ if (! $streamingMode) {
+ *$self->{ZipData}{Streaming} = 0;
+ *$self->{ZipData}{Crc32} = $crc32;
+ *$self->{ZipData}{CompressedLen} = $compressedLength;
+ *$self->{ZipData}{UnCompressedLen} = $uncompressedLength;
+ }
+
+ if ($filename_length)
+ {
+ $self->smartReadExact(\$filename, $filename_length)
+ or return $self->HeaderError("xxx");
+ $keep .= $filename ;
+ }
+
+ if ($extra_length)
+ {
+ $self->smartReadExact(\$extraField, $extra_length)
+ or return $self->HeaderError("xxx");
+ $keep .= $extraField ;
+ }
+
+ *$self->{CompressedInputLengthRemaining} =
+ *$self->{CompressedInputLength} = $compressedLength;
+
+ if ($compressedMethod == 8)
+ {
+ *$self->{Type} = 'zip';
+ }
+ elsif ($compressedMethod == 0)
+ {
+ # TODO -- add support for reading uncompressed
+
+ *$self->{Type} = 'zipStored';
+
+ my $obj = UncompressPlugin::Identity::mkUncompObject(# $got->value('CRC32'),
+ # $got->value('ADLER32'),
+ );
+
+ *$self->{Uncomp} = $obj;
+
+ }
+ else
+ {
+ return $self->HeaderError("Unsupported Compression format $compressedMethod");
+ }
+
+ return {
+ 'Type' => 'zip',
+ 'FingerprintLength' => 2,
+ #'HeaderLength' => $compressedMethod == 8 ? length $keep : 0,
+ 'HeaderLength' => length $keep,
+ 'TrailerLength' => $streamingMode ? 16 : 0,
+ 'Header' => $keep,
+ 'CompressedLength' => $compressedLength ,
+ 'UncompressedLength' => $uncompressedLength ,
+ 'CRC32' => $crc32 ,
+ 'Name' => $filename,
+ 'Time' => _dosToUnixTime($lastModTime),
+ 'Stream' => $streamingMode,
+
+ 'MethodID' => $compressedMethod,
+ 'MethodName' => $compressedMethod == 8
+ ? "Deflated"
+ : $compressedMethod == 0
+ ? "Stored"
+ : "Unknown" ,
+
+# 'TextFlag' => $flag & GZIP_FLG_FTEXT ? 1 : 0,
+# 'HeaderCRCFlag' => $flag & GZIP_FLG_FHCRC ? 1 : 0,
+# 'NameFlag' => $flag & GZIP_FLG_FNAME ? 1 : 0,
+# 'CommentFlag' => $flag & GZIP_FLG_FCOMMENT ? 1 : 0,
+# 'ExtraFlag' => $flag & GZIP_FLG_FEXTRA ? 1 : 0,
+# 'Comment' => $comment,
+# 'OsID' => $os,
+# 'OsName' => defined $GZIP_OS_Names{$os}
+# ? $GZIP_OS_Names{$os} : "Unknown",
+# 'HeaderCRC' => $HeaderCRC,
+# 'Flags' => $flag,
+# 'ExtraFlags' => $xfl,
+# 'ExtraFieldRaw' => $EXTRA,
+# 'ExtraField' => [ @EXTRA ],
+
+
+ }
+}
+
+# from Archive::Zip
+sub _dosToUnixTime
+{
+ #use Time::Local 'timelocal_nocheck';
+ use Time::Local 'timelocal';
+
+ my $dt = shift;
+
+ my $year = ( ( $dt >> 25 ) & 0x7f ) + 80;
+ my $mon = ( ( $dt >> 21 ) & 0x0f ) - 1;
+ my $mday = ( ( $dt >> 16 ) & 0x1f );
+
+ my $hour = ( ( $dt >> 11 ) & 0x1f );
+ my $min = ( ( $dt >> 5 ) & 0x3f );
+ my $sec = ( ( $dt << 1 ) & 0x3e );
+
+ # catch errors
+ my $time_t =
+ eval { timelocal( $sec, $min, $hour, $mday, $mon, $year ); };
+ return 0
+ if $@;
+ return $time_t;
+}
+
+
+1;
+
+__END__
+
diff --git a/ext/Compress/Zlib/lib/UncompressPlugin/Identity.pm b/ext/Compress/Zlib/lib/UncompressPlugin/Identity.pm
new file mode 100644
index 0000000000..3041a9f5a2
--- /dev/null
+++ b/ext/Compress/Zlib/lib/UncompressPlugin/Identity.pm
@@ -0,0 +1,93 @@
+package UncompressPlugin::Identity;
+
+use warnings;
+use strict;
+
+use Compress::Zlib::Common qw(:Status);
+
+our ($VERSION);
+
+$VERSION = '2.000_05';
+
+use Compress::Zlib ();
+
+sub mkUncompObject
+{
+ my $crc32 = 1; #shift ;
+ my $adler32 = shift;
+
+ bless { 'CompSize' => 0,
+ 'UnCompSize' => 0,
+ 'wantCRC32' => $crc32,
+ 'CRC32' => Compress::Zlib::crc32(''),
+ 'wantADLER32'=> $adler32,
+ 'ADLER32' => Compress::Zlib::adler32(''),
+ } ;
+}
+
+sub uncompr
+{
+ my $self = shift;
+ my $eof = $_[2];
+
+ if (defined ${ $_[0] } && length ${ $_[0] }) {
+ $self->{CompSize} += length ${ $_[0] } ;
+ $self->{UnCompSize} = $self->{CompSize} ;
+
+ $self->{CRC32} = Compress::Zlib::crc32($_[0], $self->{CRC32})
+ if $self->{wantCRC32};
+
+ $self->{ADLER32} = Compress::Zlib::adler32($_[0], $self->{ADLER32})
+ if $self->{wantADLER32};
+
+ ${ $_[1] } .= ${ $_[0] };
+ }
+
+ return STATUS_ENDSTREAM if $eof;
+ return STATUS_OK ;
+}
+
+sub reset
+{
+ return STATUS_OK ;
+}
+
+
+sub count
+{
+ my $self = shift ;
+ return $self->{UnCompSize} ;
+}
+
+sub compressedBytes
+{
+ my $self = shift ;
+ return $self->{UnCompSize} ;
+}
+
+sub uncompressedBytes
+{
+ my $self = shift ;
+ return $self->{UnCompSize} ;
+}
+
+sub sync
+{
+ return STATUS_OK ;
+}
+
+sub crc32
+{
+ my $self = shift ;
+ return $self->{CRC32};
+}
+
+sub adler32
+{
+ my $self = shift ;
+ return $self->{ADLER32};
+}
+
+1;
+
+__END__
diff --git a/ext/Compress/Zlib/lib/UncompressPlugin/Inflate.pm b/ext/Compress/Zlib/lib/UncompressPlugin/Inflate.pm
new file mode 100644
index 0000000000..ec3a148258
--- /dev/null
+++ b/ext/Compress/Zlib/lib/UncompressPlugin/Inflate.pm
@@ -0,0 +1,160 @@
+package UncompressPlugin::Inflate;
+
+use strict;
+use warnings;
+
+use Compress::Zlib::Common qw(:Status);
+use Compress::Zlib qw(Z_OK Z_DATA_ERROR Z_STREAM_END Z_FINISH MAX_WBITS);
+
+our ($VERSION);
+$VERSION = '2.000_05';
+
+
+
+sub mkUncompObject
+{
+ my $crc32 = shift || 1;
+ my $adler32 = shift || 1;
+ my $scan = shift || 0;
+
+ my $inflate ;
+ my $status ;
+
+ if ($scan)
+ {
+ ($inflate, $status) = new Compress::Zlib::InflateScan
+ CRC32 => $crc32,
+ ADLER32 => $adler32,
+ WindowBits => - MAX_WBITS ;
+ }
+ else
+ {
+ ($inflate, $status) = new Compress::Zlib::Inflate
+ AppendOutput => 1,
+ CRC32 => $crc32,
+ ADLER32 => $adler32,
+ WindowBits => - MAX_WBITS ;
+ }
+
+ return (undef, "Could not create Inflation object: $status", $status)
+ if $status != Z_OK ;
+
+ return bless {'Inf' => $inflate,
+ 'CompSize' => 0,
+ 'UnCompSize' => 0,
+ 'Error' => '',
+ } ;
+
+}
+
+sub uncompr
+{
+ my $self = shift ;
+ my $from = shift ;
+ my $to = shift ;
+ my $eof = shift ;
+
+ my $inf = $self->{Inf};
+
+ my $status = $inf->inflate($from, $to, $eof);
+ $self->{ErrorNo} = $status;
+
+ if ($status != Z_STREAM_END && $eof)
+ {
+ $self->{Error} = "unexpected end of file";
+ return STATUS_ERROR;
+ }
+
+ if ($status != Z_OK && $status != Z_STREAM_END )
+ {
+ $self->{Error} = "Inflation Error: $status";
+ return STATUS_ERROR;
+ }
+
+
+ return STATUS_OK if $status == Z_OK ;
+ return STATUS_ENDSTREAM if $status == Z_STREAM_END ;
+ return STATUS_ERROR ;
+}
+
+sub reset
+{
+ my $self = shift ;
+ $self->{Inf}->inflateReset();
+
+ return STATUS_OK ;
+}
+
+sub count
+{
+ my $self = shift ;
+ $self->{Inf}->inflateCount();
+}
+
+sub crc32
+{
+ my $self = shift ;
+ $self->{Inf}->crc32();
+}
+
+sub compressedBytes
+{
+ my $self = shift ;
+ $self->{Inf}->compressedBytes();
+}
+
+sub uncompressedBytes
+{
+ my $self = shift ;
+ $self->{Inf}->uncompressedBytes();
+}
+
+sub adler32
+{
+ my $self = shift ;
+ $self->{Inf}->adler32();
+}
+
+sub sync
+{
+ my $self = shift ;
+ ( $self->{Inf}->inflateSync(@_) == Z_OK)
+ ? STATUS_OK
+ : STATUS_ERROR ;
+}
+
+
+sub getLastBlockOffset
+{
+ my $self = shift ;
+ $self->{Inf}->getLastBlockOffset();
+}
+
+sub getEndOffset
+{
+ my $self = shift ;
+ $self->{Inf}->getEndOffset();
+}
+
+sub resetLastBlockByte
+{
+ my $self = shift ;
+ $self->{Inf}->resetLastBlockByte(@_);
+}
+
+sub createDeflateStream
+{
+ my $self = shift ;
+ my $deflate = $self->{Inf}->createDeflateStream(@_);
+ return bless {'Def' => $deflate,
+ 'CompSize' => 0,
+ 'UnCompSize' => 0,
+ 'Error' => '',
+ }, 'CompressPlugin::Deflate';
+}
+
+1;
+
+
+__END__
+