X-Git-Url: http://git.maemo.org/git/?p=dh-make-perl;a=blobdiff_plain;f=dev%2Fi386%2Flibio-compress-zlib-perl%2Flibio-compress-zlib-perl-2.012%2Flib%2FIO%2FCompress%2FZip.pm;fp=dev%2Fi386%2Flibio-compress-zlib-perl%2Flibio-compress-zlib-perl-2.012%2Flib%2FIO%2FCompress%2FZip.pm;h=6220d98c839eb9f6feab0e564a7173a472df7dd1;hp=0000000000000000000000000000000000000000;hb=8977e561d8a9eae6959218b0306c9df2056a38a9;hpb=df794b845212301ea0d267c919232538bfef356a diff --git a/dev/i386/libio-compress-zlib-perl/libio-compress-zlib-perl-2.012/lib/IO/Compress/Zip.pm b/dev/i386/libio-compress-zlib-perl/libio-compress-zlib-perl-2.012/lib/IO/Compress/Zip.pm new file mode 100644 index 0000000..6220d98 --- /dev/null +++ b/dev/i386/libio-compress-zlib-perl/libio-compress-zlib-perl-2.012/lib/IO/Compress/Zip.pm @@ -0,0 +1,1512 @@ +package IO::Compress::Zip ; + +use strict ; +use warnings; +use bytes; + +use IO::Compress::Base::Common 2.012 qw(:Status createSelfTiedObject); +use IO::Compress::RawDeflate 2.012 ; +use IO::Compress::Adapter::Deflate 2.012 ; +use IO::Compress::Adapter::Identity 2.012 ; +use IO::Compress::Zlib::Extra 2.012 ; +use IO::Compress::Zip::Constants 2.012 ; + + +use Compress::Raw::Zlib 2.012 qw(crc32) ; +BEGIN +{ + eval { require IO::Compress::Adapter::Bzip2 ; + import IO::Compress::Adapter::Bzip2 2.012 ; + require IO::Compress::Bzip2 ; + import IO::Compress::Bzip2 2.012 ; + } ; +} + + +require Exporter ; + +our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $ZipError); + +$VERSION = '2.012'; +$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 ; + +$EXPORT_TAGS{zip_method} = [qw( ZIP_CM_STORE ZIP_CM_DEFLATE ZIP_CM_BZIP2 )]; +push @{ $EXPORT_TAGS{all} }, @{ $EXPORT_TAGS{zip_method} }; + +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 $got = shift ; + + my ($obj, $errstr, $errno) ; + + if (*$self->{ZipData}{Method} == ZIP_CM_STORE) { + ($obj, $errstr, $errno) = IO::Compress::Adapter::Identity::mkCompObject( + $got->value('Level'), + $got->value('Strategy') + ); + } + elsif (*$self->{ZipData}{Method} == ZIP_CM_DEFLATE) { + ($obj, $errstr, $errno) = IO::Compress::Adapter::Deflate::mkCompObject( + $got->value('CRC32'), + $got->value('Adler32'), + $got->value('Level'), + $got->value('Strategy') + ); + } + elsif (*$self->{ZipData}{Method} == ZIP_CM_BZIP2) { + ($obj, $errstr, $errno) = IO::Compress::Adapter::Bzip2::mkCompObject( + $got->value('BlockSize100K'), + $got->value('WorkFactor'), + $got->value('Verbosity') + ); + *$self->{ZipData}{CRC32} = crc32(undef); + } + + return $self->saveErrorString(undef, $errstr, $errno) + if ! defined $obj; + + if (! defined *$self->{ZipData}{StartOffset}) { + *$self->{ZipData}{StartOffset} = 0; + *$self->{ZipData}{Offset} = new U64 ; + } + + return $obj; +} + +sub reset +{ + my $self = shift ; + + *$self->{Compress}->reset(); + *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32(''); + + return STATUS_OK; +} + +sub filterUncompressed +{ + my $self = shift ; + + if (*$self->{ZipData}{Method} == ZIP_CM_DEFLATE) { + *$self->{ZipData}{CRC32} = *$self->{Compress}->crc32(); + } + else { + *$self->{ZipData}{CRC32} = crc32(${$_[0]}, *$self->{ZipData}{CRC32}); + + } +} + +sub mkHeader +{ + my $self = shift; + my $param = shift ; + + *$self->{ZipData}{StartOffset} = *$self->{ZipData}{Offset}->get32bit() ; + + my $filename = ''; + $filename = $param->value('Name') || ''; + + my $comment = ''; + $comment = $param->value('Comment') || ''; + + my $hdr = ''; + + my $time = _unixToDosTime($param->value('Time')); + + my $extra = ''; + my $ctlExtra = ''; + my $empty = 0; + my $osCode = $param->value('OS_Code') ; + my $extFileAttr = 0 ; + + # This code assumes Unix. + $extFileAttr = 0666 << 16 + if $osCode == ZIP_OS_CODE_UNIX ; + + if (*$self->{ZipData}{Zip64}) { + $empty = 0xFFFF; + + my $x = ''; + $x .= pack "V V", 0, 0 ; # uncompressedLength + $x .= pack "V V", 0, 0 ; # compressedLength + $x .= *$self->{ZipData}{Offset}->getPacked_V64() ; # offset to local hdr + #$x .= pack "V ", 0 ; # disk no + + $x = IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_ZIP64, $x); + $extra .= $x; + $ctlExtra .= $x; + } + + if (! $param->value('Minimal')) { + if (defined $param->value('exTime')) + { + $extra .= mkExtendedTime($param->value('MTime'), + $param->value('ATime'), + $param->value('CTime')); + + $ctlExtra .= mkExtendedTime($param->value('MTime')); + } + + if ( $param->value('UID') && $osCode == ZIP_OS_CODE_UNIX) + { + $extra .= mkUnix2Extra( $param->value('UID'), $param->value('GID')); + $ctlExtra .= mkUnix2Extra(); + } + + $extFileAttr = $param->value('ExtAttr') + if defined $param->value('ExtAttr') ; + + $extra .= $param->value('ExtraFieldLocal') + if defined $param->value('ExtraFieldLocal'); + + $ctlExtra .= $param->value('ExtraFieldCentral') + if defined $param->value('ExtraFieldCentral'); + } + + my $gpFlag = 0 ; + $gpFlag |= ZIP_GP_FLAG_STREAMING_MASK + if *$self->{ZipData}{Stream} ; + + my $method = *$self->{ZipData}{Method} ; + + my $version = $ZIP_CM_MIN_VERSIONS{$method}; + $version = ZIP64_MIN_VERSION + if ZIP64_MIN_VERSION > $version && *$self->{ZipData}{Zip64}; + my $madeBy = ($param->value('OS_Code') << 8) + $version; + my $extract = $version; + + *$self->{ZipData}{Version} = $version; + *$self->{ZipData}{MadeBy} = $madeBy; + + my $ifa = 0; + $ifa |= ZIP_IFA_TEXT_MASK + if $param->value('TextFlag'); + + $hdr .= pack "V", ZIP_LOCAL_HDR_SIG ; # signature + $hdr .= pack 'v', $extract ; # extract Version & OS + $hdr .= pack 'v', $gpFlag ; # general purpose flag (set streaming mode) + $hdr .= pack 'v', $method ; # compression method (deflate) + $hdr .= pack 'V', $time ; # last mod date/time + $hdr .= pack 'V', 0 ; # crc32 - 0 when streaming + $hdr .= pack 'V', $empty ; # compressed length - 0 when streaming + $hdr .= pack 'V', $empty ; # uncompressed length - 0 when streaming + $hdr .= pack 'v', length $filename ; # filename length + $hdr .= pack 'v', length $extra ; # extra length + + $hdr .= $filename ; + $hdr .= $extra ; + + + my $ctl = ''; + + $ctl .= pack "V", ZIP_CENTRAL_HDR_SIG ; # signature + $ctl .= pack 'v', $madeBy ; # version made by + $ctl .= pack 'v', $extract ; # extract Version + $ctl .= pack 'v', $gpFlag ; # general purpose flag (streaming mode) + $ctl .= pack 'v', $method ; # compression method (deflate) + $ctl .= pack 'V', $time ; # last mod date/time + $ctl .= pack 'V', 0 ; # crc32 + $ctl .= pack 'V', $empty ; # compressed length + $ctl .= pack 'V', $empty ; # uncompressed length + $ctl .= pack 'v', length $filename ; # filename length + $ctl .= pack 'v', length $ctlExtra ; # extra length + $ctl .= pack 'v', length $comment ; # file comment length + $ctl .= pack 'v', 0 ; # disk number start + $ctl .= pack 'v', $ifa ; # internal file attributes + $ctl .= pack 'V', $extFileAttr ; # external file attributes + if (! *$self->{ZipData}{Zip64}) { + $ctl .= pack 'V', *$self->{ZipData}{Offset}->get32bit() ; # offset to local header + } + else { + $ctl .= pack 'V', $empty ; # offset to local header + } + + $ctl .= $filename ; + *$self->{ZipData}{StartOffset64} = 4 + length $ctl; + $ctl .= $ctlExtra ; + $ctl .= $comment ; + + *$self->{ZipData}{Offset}->add(length $hdr) ; + + *$self->{ZipData}{CentralHeader} = $ctl; + + return $hdr; +} + +sub mkTrailer +{ + my $self = shift ; + + my $crc32 ; + if (*$self->{ZipData}{Method} == ZIP_CM_DEFLATE) { + $crc32 = pack "V", *$self->{Compress}->crc32(); + } + else { + $crc32 = pack "V", *$self->{ZipData}{CRC32}; + } + + my $ctl = *$self->{ZipData}{CentralHeader} ; + + my $sizes ; + if (! *$self->{ZipData}{Zip64}) { + $sizes .= *$self->{CompSize}->getPacked_V32() ; # Compressed size + $sizes .= *$self->{UnCompSize}->getPacked_V32() ; # Uncompressed size + } + else { + $sizes .= *$self->{CompSize}->getPacked_V64() ; # Compressed size + $sizes .= *$self->{UnCompSize}->getPacked_V64() ; # Uncompressed size + } + + my $data = $crc32 . $sizes ; + + + my $hdr = ''; + + if (*$self->{ZipData}{Stream}) { + $hdr = pack "V", ZIP_DATA_HDR_SIG ; # signature + $hdr .= $data ; + } + else { + $self->writeAt(*$self->{ZipData}{StartOffset} + 14, $data) + or return undef; + } + + if (! *$self->{ZipData}{Zip64}) + { substr($ctl, 16, length $data) = $data } + else { + substr($ctl, 16, length $crc32) = $crc32 ; + my $s = *$self->{UnCompSize}->getPacked_V64() ; # Uncompressed size + $s .= *$self->{CompSize}->getPacked_V64() ; # Compressed size + substr($ctl, *$self->{ZipData}{StartOffset64}, length $s) = $s ; + } + + *$self->{ZipData}{Offset}->add(length($hdr)); + *$self->{ZipData}{Offset}->add( *$self->{CompSize} ); + push @{ *$self->{ZipData}{CentralDir} }, $ctl ; + + return $hdr; +} + +sub mkFinalTrailer +{ + my $self = shift ; + + my $comment = ''; + $comment = *$self->{ZipData}{ZipComment} ; + + my $cd_offset = *$self->{ZipData}{Offset}->get32bit() ; # offset to start central dir + + my $entries = @{ *$self->{ZipData}{CentralDir} }; + my $cd = join '', @{ *$self->{ZipData}{CentralDir} }; + my $cd_len = length $cd ; + + my $z64e = ''; + + if ( *$self->{ZipData}{Zip64} ) { + + my $v = *$self->{ZipData}{Version} ; + my $mb = *$self->{ZipData}{MadeBy} ; + $z64e .= pack 'v', $v ; # Version made by + $z64e .= pack 'v', $mb ; # Version to extract + $z64e .= pack 'V', 0 ; # number of disk + $z64e .= pack 'V', 0 ; # number of disk with central dir + $z64e .= U64::pack_V64 $entries ; # entries in central dir on this disk + $z64e .= U64::pack_V64 $entries ; # entries in central dir + $z64e .= U64::pack_V64 $cd_len ; # size of central dir + $z64e .= *$self->{ZipData}{Offset}->getPacked_V64() ; # offset to start central dir + + $z64e = pack("V", ZIP64_END_CENTRAL_REC_HDR_SIG) # signature + . U64::pack_V64(length $z64e) + . $z64e ; + + *$self->{ZipData}{Offset}->add(length $cd) ; + + $z64e .= pack "V", ZIP64_END_CENTRAL_LOC_HDR_SIG; # signature + $z64e .= pack 'V', 0 ; # number of disk with central dir + $z64e .= *$self->{ZipData}{Offset}->getPacked_V64() ; # offset to end zip64 central dir + $z64e .= pack 'V', 1 ; # Total number of disks + + # TODO - fix these when info-zip 3 is fixed. + #$cd_len = + #$cd_offset = + $entries = 0xFFFF ; + } + + my $ecd = ''; + $ecd .= pack "V", ZIP_END_CENTRAL_HDR_SIG ; # signature + $ecd .= pack 'v', 0 ; # number of disk + $ecd .= pack 'v', 0 ; # number of disk with central dir + $ecd .= pack 'v', $entries ; # entries in central dir on this disk + $ecd .= pack 'v', $entries ; # entries in central dir + $ecd .= pack 'V', $cd_len ; # size of central dir + $ecd .= pack 'V', $cd_offset ; # offset to start central dir + $ecd .= pack 'v', length $comment ; # zipfile comment length + $ecd .= $comment; + + return $cd . $z64e . $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) ; + } + + if (! $got->parsed('exTime') ) { + my $timeRef = $got->value('exTime'); + if ( defined $timeRef) { + return $self->saveErrorString(undef, "exTime not a 3-element array ref") + if ref $timeRef ne 'ARRAY' || @$timeRef != 3; + } + + $got->value("MTime", $timeRef->[1]); + $got->value("ATime", $timeRef->[0]); + $got->value("CTime", $timeRef->[2]); + } + + # Unix2 Extended Attribute + if (! $got->parsed('exUnix2') ) { + my $timeRef = $got->value('exUnix2'); + if ( defined $timeRef) { + return $self->saveErrorString(undef, "exUnix2 not a 2-element array ref") + if ref $timeRef ne 'ARRAY' || @$timeRef != 2; + } + + $got->value("UID", $timeRef->[0]); + $got->value("GID", $timeRef->[1]); + } + + *$self->{ZipData}{Zip64} = $got->value('Zip64'); + *$self->{ZipData}{Stream} = $got->value('Stream'); + + return $self->saveErrorString(undef, "Zip64 only supported if Stream enabled") + if *$self->{ZipData}{Zip64} && ! *$self->{ZipData}{Stream} ; + + my $method = $got->value('Method'); + return $self->saveErrorString(undef, "Unknown Method '$method'") + if ! defined $ZIP_CM_MIN_VERSIONS{$method}; + + return $self->saveErrorString(undef, "Bzip2 not available") + if $method == ZIP_CM_BZIP2 and + ! defined $IO::Compress::Adapter::Bzip2::VERSION; + + *$self->{ZipData}{Method} = $method; + + *$self->{ZipData}{ZipComment} = $got->value('ZipComment') ; + + for my $name (qw( ExtraFieldLocal ExtraFieldCentral )) + { + my $data = $got->value($name) ; + if (defined $data) { + my $bad = IO::Compress::Zlib::Extra::parseExtraField($data, 1, 0) ; + return $self->saveErrorString(undef, "Error with $name Parameter: $bad") + if $bad ; + + $got->value($name, $data) ; + } + } + + return undef + if defined $IO::Compress::Bzip2::VERSION + and ! IO::Compress::Bzip2::ckParams($self, $got); + + return 1 ; +} + +#sub newHeader +#{ +# my $self = shift ; +# +# return $self->mkHeader(*$self->{Got}); +#} + +sub getExtraParams +{ + my $self = shift ; + + use IO::Compress::Base::Common 2.012 qw(:Parse); + use Compress::Raw::Zlib 2.012 qw(Z_DEFLATED Z_DEFAULT_COMPRESSION Z_DEFAULT_STRATEGY); + + my @Bzip2 = (); + + @Bzip2 = IO::Compress::Bzip2::getExtraParams($self) + if defined $IO::Compress::Bzip2::VERSION; + + return ( + # zlib behaviour + $self->getZlibParams(), + + 'Stream' => [1, 1, Parse_boolean, 1], + #'Store' => [0, 1, Parse_boolean, 0], + 'Method' => [0, 1, Parse_unsigned, ZIP_CM_DEFLATE], + +# # Zip header fields + 'Minimal' => [0, 1, Parse_boolean, 0], + 'Zip64' => [0, 1, Parse_boolean, 0], + 'Comment' => [0, 1, Parse_any, ''], + 'ZipComment'=> [0, 1, Parse_any, ''], + 'Name' => [0, 1, Parse_any, ''], + 'Time' => [0, 1, Parse_any, undef], + 'exTime' => [0, 1, Parse_any, undef], + 'exUnix2' => [0, 1, Parse_any, undef], + 'ExtAttr' => [0, 1, Parse_any, 0], + 'OS_Code' => [0, 1, Parse_unsigned, $Compress::Raw::Zlib::gzip_os_code], + + 'TextFlag' => [0, 1, Parse_boolean, 0], + 'ExtraFieldLocal' => [0, 1, Parse_any, undef], + 'ExtraFieldCentral'=> [0, 1, Parse_any, undef], + + @Bzip2, + ); +} + +sub getInverseClass +{ + return ('IO::Uncompress::Unzip', + \$IO::Uncompress::Unzip::UnzipError); +} + +sub getFileInfo +{ + my $self = shift ; + my $params = shift; + my $filename = shift ; + + my ($mode, $uid, $gid, $atime, $mtime, $ctime) + = (stat($filename))[2, 4,5, 8,9,10] ; + + $params->value('Name' => $filename) + if ! $params->parsed('Name') ; + + $params->value('Time' => $mtime) + if ! $params->parsed('Time') ; + + if ( ! $params->parsed('exTime')) + { + $params->value('MTime' => $mtime) ; + $params->value('ATime' => $atime) ; + $params->value('CTime' => undef) ; # No Creation time + } + + # NOTE - Unix specific code alert + $params->value('ExtAttr' => $mode << 16) + if ! $params->parsed('ExtAttr'); + + $params->value('UID' => $uid) ; + $params->value('GID' => $gid) ; + +} + +sub mkExtendedTime +{ + # order expected is m, a, c + + my $times = ''; + my $bit = 1 ; + my $flags = 0; + + for my $time (@_) + { + if (defined $time) + { + $flags |= $bit; + $times .= pack("V", $time); + } + + $bit <<= 1 ; + } + + return IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_EXT_TIMESTAMP, + pack("C", $flags) . $times); +} + +sub mkUnix2Extra +{ + my $ids = ''; + for my $id (@_) + { + $ids .= pack("v", $id); + } + + return IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_INFO_ZIP_UNIX2, + $ids); +} + + +# 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__ + +=head1 NAME + +IO::Compress::Zip - Write zip files/buffers + + + +=head1 SYNOPSIS + + use IO::Compress::Zip qw(zip $ZipError) ; + + my $status = zip $input => $output [,OPTS] + or die "zip failed: $ZipError\n"; + + my $z = new IO::Compress::Zip $output [,OPTS] + or die "zip failed: $ZipError\n"; + + $z->print($string); + $z->printf($format, $string); + $z->write($string); + $z->syswrite($string [, $length, $offset]); + $z->flush(); + $z->tell(); + $z->eof(); + $z->seek($position, $whence); + $z->binmode(); + $z->fileno(); + $z->opened(); + $z->autoflush(); + $z->input_line_number(); + $z->newStream( [OPTS] ); + + $z->deflateParams(); + + $z->close() ; + + $ZipError ; + + # IO::File mode + + print $z $string; + printf $z $format, $string; + tell $z + eof $z + seek $z, $position, $whence + binmode $z + fileno $z + close $z ; + + +=head1 DESCRIPTION + +This module provides a Perl interface that allows writing zip +compressed data to files or buffer. + +The primary purpose of this module is to provide streaming write access to +zip files and buffers. It is not a general-purpose file archiver. If that +is what you want, check out C. + +At present three compression methods are supported by IO::Compress::Zip, +namely Store (no compression at all), Deflate and Bzip2. + +Note that to create Bzip2 content, the module C must +be installed. + +For reading zip files/buffers, see the companion module +L. + +=head1 Functional Interface + +A top-level function, C, is provided to carry out +"one-shot" compression between buffers and/or files. For finer +control over the compression process, see the L +section. + + use IO::Compress::Zip qw(zip $ZipError) ; + + zip $input => $output [,OPTS] + or die "zip failed: $ZipError\n"; + +The functional interface needs Perl5.005 or better. + +=head2 zip $input => $output [, OPTS] + +C expects at least two parameters, C<$input> and C<$output>. + +=head3 The C<$input> parameter + +The parameter, C<$input>, is used to define the source of +the uncompressed data. + +It can take one of the following forms: + +=over 5 + +=item A filename + +If the C<$input> parameter is a simple scalar, it is assumed to be a +filename. This file will be opened for reading and the input data +will be read from it. + +=item A filehandle + +If the C<$input> parameter is a filehandle, the input data will be +read from it. +The string '-' can be used as an alias for standard input. + +=item A scalar reference + +If C<$input> is a scalar reference, the input data will be read +from C<$$input>. + +=item An array reference + +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 filenames before any data is compressed. + +=item An Input FileGlob string + +If C<$input> is a string that is delimited by the characters "<" and ">" +C will assume that it is an I. The +input is the list of files that match the fileglob. + +If the fileglob does not match any files ... + +See L for more details. + +=back + +If the C<$input> parameter is any other type, C will be returned. + +In addition, if C<$input> is a simple filename, the default values for +the C, C