xref: /openbsd-src/gnu/usr.bin/perl/cpan/IO-Compress/lib/IO/Compress/Zip.pm (revision aa1fa3d4849d8c6172fb7a884e8fa612b2ab7385)
1package IO::Compress::Zip ;
2
3use strict ;
4use warnings;
5use bytes;
6
7use IO::Compress::Base::Common  2.084 qw(:Status );
8use IO::Compress::RawDeflate 2.084 ();
9use IO::Compress::Adapter::Deflate 2.084 ;
10use IO::Compress::Adapter::Identity 2.084 ;
11use IO::Compress::Zlib::Extra 2.084 ;
12use IO::Compress::Zip::Constants 2.084 ;
13
14use File::Spec();
15use Config;
16
17use Compress::Raw::Zlib  2.084 ();
18
19BEGIN
20{
21    eval { require IO::Compress::Adapter::Bzip2 ;
22           import  IO::Compress::Adapter::Bzip2 2.084 ;
23           require IO::Compress::Bzip2 ;
24           import  IO::Compress::Bzip2 2.084 ;
25         } ;
26
27    eval { require IO::Compress::Adapter::Lzma ;
28           import  IO::Compress::Adapter::Lzma 2.084 ;
29           require IO::Compress::Lzma ;
30           import  IO::Compress::Lzma 2.084 ;
31         } ;
32}
33
34
35require Exporter ;
36
37our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, %DEFLATE_CONSTANTS, $ZipError);
38
39$VERSION = '2.084';
40$ZipError = '';
41
42@ISA = qw(IO::Compress::RawDeflate Exporter);
43@EXPORT_OK = qw( $ZipError zip ) ;
44%EXPORT_TAGS = %IO::Compress::RawDeflate::DEFLATE_CONSTANTS ;
45
46push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
47
48$EXPORT_TAGS{zip_method} = [qw( ZIP_CM_STORE ZIP_CM_DEFLATE ZIP_CM_BZIP2 ZIP_CM_LZMA)];
49push @{ $EXPORT_TAGS{all} }, @{ $EXPORT_TAGS{zip_method} };
50
51Exporter::export_ok_tags('all');
52
53sub new
54{
55    my $class = shift ;
56
57    my $obj = IO::Compress::Base::Common::createSelfTiedObject($class, \$ZipError);
58    $obj->_create(undef, @_);
59
60}
61
62sub zip
63{
64    my $obj = IO::Compress::Base::Common::createSelfTiedObject(undef, \$ZipError);
65    return $obj->_def(@_);
66}
67
68sub isMethodAvailable
69{
70    my $method = shift;
71
72    # Store & Deflate are always available
73    return 1
74        if $method == ZIP_CM_STORE || $method == ZIP_CM_DEFLATE ;
75
76    return 1
77        if $method == ZIP_CM_BZIP2 and
78           defined $IO::Compress::Adapter::Bzip2::VERSION;
79
80    return 1
81        if $method == ZIP_CM_LZMA and
82           defined $IO::Compress::Adapter::Lzma::VERSION;
83
84    return 0;
85}
86
87sub beforePayload
88{
89    my $self = shift ;
90
91    if (*$self->{ZipData}{Sparse} ) {
92        my $inc = 1024 * 100 ;
93        my $NULLS = ("\x00" x $inc) ;
94        my $sparse = *$self->{ZipData}{Sparse} ;
95        *$self->{CompSize}->add( $sparse );
96        *$self->{UnCompSize}->add( $sparse );
97
98        *$self->{FH}->seek($sparse, IO::Handle::SEEK_CUR);
99
100        *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32($NULLS, *$self->{ZipData}{CRC32})
101            for 1 .. int $sparse / $inc;
102        *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32(substr($NULLS, 0,  $sparse % $inc),
103                                         *$self->{ZipData}{CRC32})
104            if $sparse % $inc;
105    }
106}
107
108sub mkComp
109{
110    my $self = shift ;
111    my $got = shift ;
112
113    my ($obj, $errstr, $errno) ;
114
115    if (*$self->{ZipData}{Method} == ZIP_CM_STORE) {
116        ($obj, $errstr, $errno) = IO::Compress::Adapter::Identity::mkCompObject(
117                                                 $got->getValue('level'),
118                                                 $got->getValue('strategy')
119                                                 );
120        *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32(undef);
121    }
122    elsif (*$self->{ZipData}{Method} == ZIP_CM_DEFLATE) {
123        ($obj, $errstr, $errno) = IO::Compress::Adapter::Deflate::mkCompObject(
124                                                 $got->getValue('crc32'),
125                                                 $got->getValue('adler32'),
126                                                 $got->getValue('level'),
127                                                 $got->getValue('strategy')
128                                                 );
129    }
130    elsif (*$self->{ZipData}{Method} == ZIP_CM_BZIP2) {
131        ($obj, $errstr, $errno) = IO::Compress::Adapter::Bzip2::mkCompObject(
132                                                $got->getValue('blocksize100k'),
133                                                $got->getValue('workfactor'),
134                                                $got->getValue('verbosity')
135                                               );
136        *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32(undef);
137    }
138    elsif (*$self->{ZipData}{Method} == ZIP_CM_LZMA) {
139        ($obj, $errstr, $errno) = IO::Compress::Adapter::Lzma::mkRawZipCompObject($got->getValue('preset'),
140                                                                                 $got->getValue('extreme'),
141                                                                                 );
142        *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32(undef);
143    }
144
145    return $self->saveErrorString(undef, $errstr, $errno)
146       if ! defined $obj;
147
148    if (! defined *$self->{ZipData}{SizesOffset}) {
149        *$self->{ZipData}{SizesOffset} = 0;
150        *$self->{ZipData}{Offset} = new U64 ;
151    }
152
153    *$self->{ZipData}{AnyZip64} = 0
154        if ! defined  *$self->{ZipData}{AnyZip64} ;
155
156    return $obj;
157}
158
159sub reset
160{
161    my $self = shift ;
162
163    *$self->{Compress}->reset();
164    *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32('');
165
166    return STATUS_OK;
167}
168
169sub filterUncompressed
170{
171    my $self = shift ;
172
173    if (*$self->{ZipData}{Method} == ZIP_CM_DEFLATE) {
174        *$self->{ZipData}{CRC32} = *$self->{Compress}->crc32();
175    }
176    else {
177        *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32(${$_[0]}, *$self->{ZipData}{CRC32});
178
179    }
180}
181
182sub canonicalName
183{
184    # This sub is derived from Archive::Zip::_asZipDirName
185
186    # Return the normalized name as used in a zip file (path
187    # separators become slashes, etc.).
188    # Will translate internal slashes in path components (i.e. on Macs) to
189    # underscores.  Discards volume names.
190    # When $forceDir is set, returns paths with trailing slashes
191    #
192    # input         output
193    # .             '.'
194    # ./a           a
195    # ./a/b         a/b
196    # ./a/b/        a/b
197    # a/b/          a/b
198    # /a/b/         a/b
199    # c:\a\b\c.doc  a/b/c.doc      # on Windows
200    # "i/o maps:whatever"   i_o maps/whatever   # on Macs
201
202    my $name      = shift;
203    my $forceDir  = shift ;
204
205    my ( $volume, $directories, $file ) =
206      File::Spec->splitpath( File::Spec->canonpath($name), $forceDir );
207
208    my @dirs = map { $_ =~ s{/}{_}g; $_ }
209               File::Spec->splitdir($directories);
210
211    if ( @dirs > 0 ) { pop (@dirs) if $dirs[-1] eq '' }   # remove empty component
212    push @dirs, defined($file) ? $file : '' ;
213
214    my $normalised_path = join '/', @dirs;
215
216    # Leading directory separators should not be stored in zip archives.
217    # Example:
218    #   C:\a\b\c\      a/b/c
219    #   C:\a\b\c.txt   a/b/c.txt
220    #   /a/b/c/        a/b/c
221    #   /a/b/c.txt     a/b/c.txt
222    $normalised_path =~ s{^/}{};  # remove leading separator
223
224    return $normalised_path;
225}
226
227
228sub mkHeader
229{
230    my $self  = shift;
231    my $param = shift ;
232
233    *$self->{ZipData}{LocalHdrOffset} = U64::clone(*$self->{ZipData}{Offset});
234
235    my $comment = '';
236    $comment = $param->valueOrDefault('comment') ;
237
238    my $filename = '';
239    $filename = $param->valueOrDefault('name') ;
240
241    $filename = canonicalName($filename)
242        if length $filename && $param->getValue('canonicalname') ;
243
244    if (defined *$self->{ZipData}{FilterName} ) {
245        local *_ = \$filename ;
246        &{ *$self->{ZipData}{FilterName} }() ;
247    }
248
249#    if ( $param->getValue('utf8') ) {
250#        require Encode ;
251#        $filename = Encode::encode_utf8($filename)
252#            if length $filename ;
253#        $comment = Encode::encode_utf8($comment)
254#            if length $comment ;
255#    }
256
257    my $hdr = '';
258
259    my $time = _unixToDosTime($param->getValue('time'));
260
261    my $extra = '';
262    my $ctlExtra = '';
263    my $empty = 0;
264    my $osCode = $param->getValue('os_code') ;
265    my $extFileAttr = 0 ;
266
267    # This code assumes Unix.
268    # TODO - revisit this
269    $extFileAttr = 0100644 << 16
270        if $osCode == ZIP_OS_CODE_UNIX ;
271
272    if (*$self->{ZipData}{Zip64}) {
273        $empty = IO::Compress::Base::Common::MAX32;
274
275        my $x = '';
276        $x .= pack "V V", 0, 0 ; # uncompressedLength
277        $x .= pack "V V", 0, 0 ; # compressedLength
278
279        # Zip64 needs to be first in extra field to workaround a Windows Explorer Bug
280        # See http://www.info-zip.org/phpBB3/viewtopic.php?f=3&t=440 for details
281        $extra .= IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_ZIP64, $x);
282    }
283
284    if (! $param->getValue('minimal')) {
285        if ($param->parsed('mtime'))
286        {
287            $extra .= mkExtendedTime($param->getValue('mtime'),
288                                    $param->getValue('atime'),
289                                    $param->getValue('ctime'));
290
291            $ctlExtra .= mkExtendedTime($param->getValue('mtime'));
292        }
293
294        if ( $osCode == ZIP_OS_CODE_UNIX )
295        {
296            if ( $param->getValue('want_exunixn') )
297            {
298                    my $ux3 = mkUnixNExtra( @{ $param->getValue('want_exunixn') });
299                    $extra    .= $ux3;
300                    $ctlExtra .= $ux3;
301            }
302
303            if ( $param->getValue('exunix2') )
304            {
305                    $extra    .= mkUnix2Extra( @{ $param->getValue('exunix2') });
306                    $ctlExtra .= mkUnix2Extra();
307            }
308        }
309
310        $extFileAttr = $param->getValue('extattr')
311            if defined $param->getValue('extattr') ;
312
313        $extra .= $param->getValue('extrafieldlocal')
314            if defined $param->getValue('extrafieldlocal');
315
316        $ctlExtra .= $param->getValue('extrafieldcentral')
317            if defined $param->getValue('extrafieldcentral');
318    }
319
320    my $method = *$self->{ZipData}{Method} ;
321    my $gpFlag = 0 ;
322    $gpFlag |= ZIP_GP_FLAG_STREAMING_MASK
323        if *$self->{ZipData}{Stream} ;
324
325    $gpFlag |= ZIP_GP_FLAG_LZMA_EOS_PRESENT
326        if $method == ZIP_CM_LZMA ;
327
328#    $gpFlag |= ZIP_GP_FLAG_LANGUAGE_ENCODING
329#        if  $param->getValue('utf8') && (length($filename) || length($comment));
330
331    my $version = $ZIP_CM_MIN_VERSIONS{$method};
332    $version = ZIP64_MIN_VERSION
333        if ZIP64_MIN_VERSION > $version && *$self->{ZipData}{Zip64};
334
335    my $madeBy = ($param->getValue('os_code') << 8) + $version;
336    my $extract = $version;
337
338    *$self->{ZipData}{Version} = $version;
339    *$self->{ZipData}{MadeBy} = $madeBy;
340
341    my $ifa = 0;
342    $ifa |= ZIP_IFA_TEXT_MASK
343        if $param->getValue('textflag');
344
345    $hdr .= pack "V", ZIP_LOCAL_HDR_SIG ; # signature
346    $hdr .= pack 'v', $extract   ; # extract Version & OS
347    $hdr .= pack 'v', $gpFlag    ; # general purpose flag (set streaming mode)
348    $hdr .= pack 'v', $method    ; # compression method (deflate)
349    $hdr .= pack 'V', $time      ; # last mod date/time
350    $hdr .= pack 'V', 0          ; # crc32               - 0 when streaming
351    $hdr .= pack 'V', $empty     ; # compressed length   - 0 when streaming
352    $hdr .= pack 'V', $empty     ; # uncompressed length - 0 when streaming
353    $hdr .= pack 'v', length $filename ; # filename length
354    $hdr .= pack 'v', length $extra ; # extra length
355
356    $hdr .= $filename ;
357
358    # Remember the offset for the compressed & uncompressed lengths in the
359    # local header.
360    if (*$self->{ZipData}{Zip64}) {
361        *$self->{ZipData}{SizesOffset} = *$self->{ZipData}{Offset}->get64bit()
362            + length($hdr) + 4 ;
363    }
364    else {
365        *$self->{ZipData}{SizesOffset} = *$self->{ZipData}{Offset}->get64bit()
366                                            + 18;
367    }
368
369    $hdr .= $extra ;
370
371
372    my $ctl = '';
373
374    $ctl .= pack "V", ZIP_CENTRAL_HDR_SIG ; # signature
375    $ctl .= pack 'v', $madeBy    ; # version made by
376    $ctl .= pack 'v', $extract   ; # extract Version
377    $ctl .= pack 'v', $gpFlag    ; # general purpose flag (streaming mode)
378    $ctl .= pack 'v', $method    ; # compression method (deflate)
379    $ctl .= pack 'V', $time      ; # last mod date/time
380    $ctl .= pack 'V', 0          ; # crc32
381    $ctl .= pack 'V', $empty     ; # compressed length
382    $ctl .= pack 'V', $empty     ; # uncompressed length
383    $ctl .= pack 'v', length $filename ; # filename length
384
385    *$self->{ZipData}{ExtraOffset} = length $ctl;
386    *$self->{ZipData}{ExtraSize} = length $ctlExtra ;
387
388    $ctl .= pack 'v', length $ctlExtra ; # extra length
389    $ctl .= pack 'v', length $comment ;  # file comment length
390    $ctl .= pack 'v', 0          ; # disk number start
391    $ctl .= pack 'v', $ifa       ; # internal file attributes
392    $ctl .= pack 'V', $extFileAttr   ; # external file attributes
393
394    # offset to local hdr
395    if (*$self->{ZipData}{LocalHdrOffset}->is64bit() ) {
396        $ctl .= pack 'V', IO::Compress::Base::Common::MAX32 ;
397    }
398    else {
399        $ctl .= *$self->{ZipData}{LocalHdrOffset}->getPacked_V32() ;
400    }
401
402    $ctl .= $filename ;
403
404    *$self->{ZipData}{Offset}->add32(length $hdr) ;
405
406    *$self->{ZipData}{CentralHeader} = [ $ctl, $ctlExtra, $comment];
407
408    return $hdr;
409}
410
411sub mkTrailer
412{
413    my $self = shift ;
414
415    my $crc32 ;
416    if (*$self->{ZipData}{Method} == ZIP_CM_DEFLATE) {
417        $crc32 = pack "V", *$self->{Compress}->crc32();
418    }
419    else {
420        $crc32 = pack "V", *$self->{ZipData}{CRC32};
421    }
422
423    my ($ctl, $ctlExtra, $comment) = @{ *$self->{ZipData}{CentralHeader} };
424
425    my $sizes ;
426    if (! *$self->{ZipData}{Zip64}) {
427        $sizes .= *$self->{CompSize}->getPacked_V32() ;   # Compressed size
428        $sizes .= *$self->{UnCompSize}->getPacked_V32() ; # Uncompressed size
429    }
430    else {
431        $sizes .= *$self->{CompSize}->getPacked_V64() ;   # Compressed size
432        $sizes .= *$self->{UnCompSize}->getPacked_V64() ; # Uncompressed size
433    }
434
435    my $data = $crc32 . $sizes ;
436
437    my $xtrasize  = *$self->{UnCompSize}->getPacked_V64() ; # Uncompressed size
438       $xtrasize .= *$self->{CompSize}->getPacked_V64() ;   # Compressed size
439
440    my $hdr = '';
441
442    if (*$self->{ZipData}{Stream}) {
443        $hdr  = pack "V", ZIP_DATA_HDR_SIG ;                       # signature
444        $hdr .= $data ;
445    }
446    else {
447        $self->writeAt(*$self->{ZipData}{LocalHdrOffset}->get64bit() + 14,  $crc32)
448            or return undef;
449        $self->writeAt(*$self->{ZipData}{SizesOffset},
450                *$self->{ZipData}{Zip64} ? $xtrasize : $sizes)
451            or return undef;
452    }
453
454    # Central Header Record/Zip64 extended field
455
456    substr($ctl, 16, length $crc32) = $crc32 ;
457
458    my $zip64Payload = '';
459
460    # uncompressed length - only set zip64 if needed
461    if (*$self->{UnCompSize}->isAlmost64bit()) { #  || *$self->{ZipData}{Zip64}) {
462        $zip64Payload .= *$self->{UnCompSize}->getPacked_V64() ;
463    } else {
464        substr($ctl, 24, 4) = *$self->{UnCompSize}->getPacked_V32() ;
465    }
466
467    # compressed length - only set zip64 if needed
468    if (*$self->{CompSize}->isAlmost64bit()) { # || *$self->{ZipData}{Zip64}) {
469        $zip64Payload .= *$self->{CompSize}->getPacked_V64() ;
470    } else {
471        substr($ctl, 20, 4) = *$self->{CompSize}->getPacked_V32() ;
472    }
473
474    # Local Header offset
475    $zip64Payload .= *$self->{ZipData}{LocalHdrOffset}->getPacked_V64()
476        if *$self->{ZipData}{LocalHdrOffset}->is64bit() ;
477
478    # disk no - always zero, so don't need to include it.
479    #$zip64Payload .= pack "V", 0    ;
480
481    my $zip64Xtra = '';
482
483    if (length $zip64Payload) {
484        $zip64Xtra = IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_ZIP64, $zip64Payload);
485
486        substr($ctl, *$self->{ZipData}{ExtraOffset}, 2) =
487             pack 'v', *$self->{ZipData}{ExtraSize} + length $zip64Xtra;
488
489        *$self->{ZipData}{AnyZip64} = 1;
490    }
491
492    # Zip64 needs to be first in extra field to workaround a Windows Explorer Bug
493    # See http://www.info-zip.org/phpBB3/viewtopic.php?f=3&t=440 for details
494    $ctl .= $zip64Xtra . $ctlExtra . $comment;
495
496    *$self->{ZipData}{Offset}->add32(length($hdr));
497    *$self->{ZipData}{Offset}->add( *$self->{CompSize} );
498    push @{ *$self->{ZipData}{CentralDir} }, $ctl ;
499
500    return $hdr;
501}
502
503sub mkFinalTrailer
504{
505    my $self = shift ;
506
507    my $comment = '';
508    $comment = *$self->{ZipData}{ZipComment} ;
509
510    my $cd_offset = *$self->{ZipData}{Offset}->get32bit() ; # offset to start central dir
511
512    my $entries = @{ *$self->{ZipData}{CentralDir} };
513
514    *$self->{ZipData}{AnyZip64} = 1
515        if *$self->{ZipData}{Offset}->is64bit || $entries >= 0xFFFF ;
516
517    my $cd = join '', @{ *$self->{ZipData}{CentralDir} };
518    my $cd_len = length $cd ;
519
520    my $z64e = '';
521
522    if ( *$self->{ZipData}{AnyZip64} ) {
523
524        my $v  = *$self->{ZipData}{Version} ;
525        my $mb = *$self->{ZipData}{MadeBy} ;
526        $z64e .= pack 'v', $mb            ; # Version made by
527        $z64e .= pack 'v', $v             ; # Version to extract
528        $z64e .= pack 'V', 0              ; # number of disk
529        $z64e .= pack 'V', 0              ; # number of disk with central dir
530        $z64e .= U64::pack_V64 $entries   ; # entries in central dir on this disk
531        $z64e .= U64::pack_V64 $entries   ; # entries in central dir
532        $z64e .= U64::pack_V64 $cd_len    ; # size of central dir
533        $z64e .= *$self->{ZipData}{Offset}->getPacked_V64() ; # offset to start central dir
534
535        $z64e  = pack("V", ZIP64_END_CENTRAL_REC_HDR_SIG) # signature
536              .  U64::pack_V64(length $z64e)
537              .  $z64e ;
538
539        *$self->{ZipData}{Offset}->add32(length $cd) ;
540
541        $z64e .= pack "V", ZIP64_END_CENTRAL_LOC_HDR_SIG; # signature
542        $z64e .= pack 'V', 0              ; # number of disk with central dir
543        $z64e .= *$self->{ZipData}{Offset}->getPacked_V64() ; # offset to end zip64 central dir
544        $z64e .= pack 'V', 1              ; # Total number of disks
545
546        $cd_offset = IO::Compress::Base::Common::MAX32 ;
547        $cd_len = IO::Compress::Base::Common::MAX32 if IO::Compress::Base::Common::isGeMax32 $cd_len ;
548        $entries = 0xFFFF if $entries >= 0xFFFF ;
549    }
550
551    my $ecd = '';
552    $ecd .= pack "V", ZIP_END_CENTRAL_HDR_SIG ; # signature
553    $ecd .= pack 'v', 0          ; # number of disk
554    $ecd .= pack 'v', 0          ; # number of disk with central dir
555    $ecd .= pack 'v', $entries   ; # entries in central dir on this disk
556    $ecd .= pack 'v', $entries   ; # entries in central dir
557    $ecd .= pack 'V', $cd_len    ; # size of central dir
558    $ecd .= pack 'V', $cd_offset ; # offset to start central dir
559    $ecd .= pack 'v', length $comment ; # zipfile comment length
560    $ecd .= $comment;
561
562    return $cd . $z64e . $ecd ;
563}
564
565sub ckParams
566{
567    my $self = shift ;
568    my $got = shift;
569
570    $got->setValue('crc32' => 1);
571
572    if (! $got->parsed('time') ) {
573        # Modification time defaults to now.
574        $got->setValue('time' => time) ;
575    }
576
577    if ($got->parsed('extime') ) {
578        my $timeRef = $got->getValue('extime');
579        if ( defined $timeRef) {
580            return $self->saveErrorString(undef, "exTime not a 3-element array ref")
581                if ref $timeRef ne 'ARRAY' || @$timeRef != 3;
582        }
583
584        $got->setValue("mtime", $timeRef->[1]);
585        $got->setValue("atime", $timeRef->[0]);
586        $got->setValue("ctime", $timeRef->[2]);
587    }
588
589    # Unix2/3 Extended Attribute
590    for my $name (qw(exunix2 exunixn))
591    {
592        if ($got->parsed($name) ) {
593            my $idRef = $got->getValue($name);
594            if ( defined $idRef) {
595                return $self->saveErrorString(undef, "$name not a 2-element array ref")
596                    if ref $idRef ne 'ARRAY' || @$idRef != 2;
597            }
598
599            $got->setValue("uid", $idRef->[0]);
600            $got->setValue("gid", $idRef->[1]);
601            $got->setValue("want_$name", $idRef);
602        }
603    }
604
605    *$self->{ZipData}{AnyZip64} = 1
606        if $got->getValue('zip64');
607    *$self->{ZipData}{Zip64} = $got->getValue('zip64');
608    *$self->{ZipData}{Stream} = $got->getValue('stream');
609
610    my $method = $got->getValue('method');
611    return $self->saveErrorString(undef, "Unknown Method '$method'")
612        if ! defined $ZIP_CM_MIN_VERSIONS{$method};
613
614    return $self->saveErrorString(undef, "Bzip2 not available")
615        if $method == ZIP_CM_BZIP2 and
616           ! defined $IO::Compress::Adapter::Bzip2::VERSION;
617
618    return $self->saveErrorString(undef, "Lzma not available")
619        if $method == ZIP_CM_LZMA
620        and ! defined $IO::Compress::Adapter::Lzma::VERSION;
621
622    *$self->{ZipData}{Method} = $method;
623
624    *$self->{ZipData}{ZipComment} = $got->getValue('zipcomment') ;
625
626    for my $name (qw( extrafieldlocal extrafieldcentral ))
627    {
628        my $data = $got->getValue($name) ;
629        if (defined $data) {
630            my $bad = IO::Compress::Zlib::Extra::parseExtraField($data, 1, 0) ;
631            return $self->saveErrorString(undef, "Error with $name Parameter: $bad")
632                if $bad ;
633
634            $got->setValue($name, $data) ;
635        }
636    }
637
638    return undef
639        if defined $IO::Compress::Bzip2::VERSION
640            and ! IO::Compress::Bzip2::ckParams($self, $got);
641
642    if ($got->parsed('sparse') ) {
643        *$self->{ZipData}{Sparse} = $got->getValue('sparse') ;
644        *$self->{ZipData}{Method} = ZIP_CM_STORE;
645    }
646
647    if ($got->parsed('filtername')) {
648        my $v = $got->getValue('filtername') ;
649        *$self->{ZipData}{FilterName} = $v
650            if ref $v eq 'CODE' ;
651    }
652
653    return 1 ;
654}
655
656sub outputPayload
657{
658    my $self = shift ;
659    return 1 if *$self->{ZipData}{Sparse} ;
660    return $self->output(@_);
661}
662
663
664#sub newHeader
665#{
666#    my $self = shift ;
667#
668#    return $self->mkHeader(*$self->{Got});
669#}
670
671
672our %PARAMS = (
673            'stream'    => [IO::Compress::Base::Common::Parse_boolean,   1],
674           #'store'     => [IO::Compress::Base::Common::Parse_boolean,   0],
675            'method'    => [IO::Compress::Base::Common::Parse_unsigned,  ZIP_CM_DEFLATE],
676
677#            # Zip header fields
678            'minimal'   => [IO::Compress::Base::Common::Parse_boolean,   0],
679            'zip64'     => [IO::Compress::Base::Common::Parse_boolean,   0],
680            'comment'   => [IO::Compress::Base::Common::Parse_any,       ''],
681            'zipcomment'=> [IO::Compress::Base::Common::Parse_any,       ''],
682            'name'      => [IO::Compress::Base::Common::Parse_any,       ''],
683            'filtername'=> [IO::Compress::Base::Common::Parse_code,      undef],
684            'canonicalname'=> [IO::Compress::Base::Common::Parse_boolean,   0],
685#            'utf8'      => [IO::Compress::Base::Common::Parse_boolean,   0],
686            'time'      => [IO::Compress::Base::Common::Parse_any,       undef],
687            'extime'    => [IO::Compress::Base::Common::Parse_any,       undef],
688            'exunix2'   => [IO::Compress::Base::Common::Parse_any,       undef],
689            'exunixn'   => [IO::Compress::Base::Common::Parse_any,       undef],
690            'extattr'   => [IO::Compress::Base::Common::Parse_any,
691                    $Compress::Raw::Zlib::gzip_os_code == 3
692                        ? 0100644 << 16
693                        : 0],
694            'os_code'   => [IO::Compress::Base::Common::Parse_unsigned,  $Compress::Raw::Zlib::gzip_os_code],
695
696            'textflag'  => [IO::Compress::Base::Common::Parse_boolean,   0],
697            'extrafieldlocal'  => [IO::Compress::Base::Common::Parse_any,    undef],
698            'extrafieldcentral'=> [IO::Compress::Base::Common::Parse_any,    undef],
699
700            # Lzma
701            'preset'   => [IO::Compress::Base::Common::Parse_unsigned, 6],
702            'extreme'  => [IO::Compress::Base::Common::Parse_boolean,  0],
703
704            # For internal use only
705            'sparse'    => [IO::Compress::Base::Common::Parse_unsigned,  0],
706
707            IO::Compress::RawDeflate::getZlibParams(),
708            defined $IO::Compress::Bzip2::VERSION
709                ? IO::Compress::Bzip2::getExtraParams()
710                : ()
711
712
713                );
714
715sub getExtraParams
716{
717    return %PARAMS ;
718}
719
720sub getInverseClass
721{
722    return ('IO::Uncompress::Unzip',
723                \$IO::Uncompress::Unzip::UnzipError);
724}
725
726sub getFileInfo
727{
728    my $self = shift ;
729    my $params = shift;
730    my $filename = shift ;
731
732    if (IO::Compress::Base::Common::isaScalar($filename))
733    {
734        $params->setValue(zip64 => 1)
735            if IO::Compress::Base::Common::isGeMax32 length (${ $filename }) ;
736
737        return ;
738    }
739
740    my ($mode, $uid, $gid, $size, $atime, $mtime, $ctime) ;
741    if ( $params->parsed('storelinks') )
742    {
743        ($mode, $uid, $gid, $size, $atime, $mtime, $ctime)
744                = (lstat($filename))[2, 4,5,7, 8,9,10] ;
745    }
746    else
747    {
748        ($mode, $uid, $gid, $size, $atime, $mtime, $ctime)
749                = (stat($filename))[2, 4,5,7, 8,9,10] ;
750    }
751
752    $params->setValue(textflag => -T $filename )
753        if ! $params->parsed('textflag');
754
755    $params->setValue(zip64 => 1)
756        if IO::Compress::Base::Common::isGeMax32 $size ;
757
758    $params->setValue('name' => $filename)
759        if ! $params->parsed('name') ;
760
761    $params->setValue('time' => $mtime)
762        if ! $params->parsed('time') ;
763
764    if ( ! $params->parsed('extime'))
765    {
766        $params->setValue('mtime' => $mtime) ;
767        $params->setValue('atime' => $atime) ;
768        $params->setValue('ctime' => undef) ; # No Creation time
769        # TODO - see if can fillout creation time on non-Unix
770    }
771
772    # NOTE - Unix specific code alert
773    if (! $params->parsed('extattr'))
774    {
775        use Fcntl qw(:mode) ;
776        my $attr = $mode << 16;
777        $attr |= ZIP_A_RONLY if ($mode & S_IWRITE) == 0 ;
778        $attr |= ZIP_A_DIR   if ($mode & S_IFMT  ) == S_IFDIR ;
779
780        $params->setValue('extattr' => $attr);
781    }
782
783    $params->setValue('want_exunixn', [$uid, $gid]);
784    $params->setValue('uid' => $uid) ;
785    $params->setValue('gid' => $gid) ;
786
787}
788
789sub mkExtendedTime
790{
791    # order expected is m, a, c
792
793    my $times = '';
794    my $bit = 1 ;
795    my $flags = 0;
796
797    for my $time (@_)
798    {
799        if (defined $time)
800        {
801            $flags |= $bit;
802            $times .= pack("V", $time);
803        }
804
805        $bit <<= 1 ;
806    }
807
808    return IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_EXT_TIMESTAMP,
809                                                 pack("C", $flags) .  $times);
810}
811
812sub mkUnix2Extra
813{
814    my $ids = '';
815    for my $id (@_)
816    {
817        $ids .= pack("v", $id);
818    }
819
820    return IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_INFO_ZIP_UNIX2,
821                                                 $ids);
822}
823
824sub mkUnixNExtra
825{
826    my $uid = shift;
827    my $gid = shift;
828
829    # Assumes UID/GID are 32-bit
830    my $ids ;
831    $ids .= pack "C", 1; # version
832    $ids .= pack "C", $Config{uidsize};
833    $ids .= pack "V", $uid;
834    $ids .= pack "C", $Config{gidsize};
835    $ids .= pack "V", $gid;
836
837    return IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_INFO_ZIP_UNIXN,
838                                                 $ids);
839}
840
841
842# from Archive::Zip
843sub _unixToDosTime    # Archive::Zip::Member
844{
845	my $time_t = shift;
846
847    # TODO - add something to cope with unix time < 1980
848	my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime($time_t);
849	my $dt = 0;
850	$dt += ( $sec >> 1 );
851	$dt += ( $min << 5 );
852	$dt += ( $hour << 11 );
853	$dt += ( $mday << 16 );
854	$dt += ( ( $mon + 1 ) << 21 );
855	$dt += ( ( $year - 80 ) << 25 );
856	return $dt;
857}
858
8591;
860
861__END__
862
863=head1 NAME
864
865IO::Compress::Zip - Write zip files/buffers
866
867=head1 SYNOPSIS
868
869    use IO::Compress::Zip qw(zip $ZipError) ;
870
871    my $status = zip $input => $output [,OPTS]
872        or die "zip failed: $ZipError\n";
873
874    my $z = new IO::Compress::Zip $output [,OPTS]
875        or die "zip failed: $ZipError\n";
876
877    $z->print($string);
878    $z->printf($format, $string);
879    $z->write($string);
880    $z->syswrite($string [, $length, $offset]);
881    $z->flush();
882    $z->tell();
883    $z->eof();
884    $z->seek($position, $whence);
885    $z->binmode();
886    $z->fileno();
887    $z->opened();
888    $z->autoflush();
889    $z->input_line_number();
890    $z->newStream( [OPTS] );
891
892    $z->deflateParams();
893
894    $z->close() ;
895
896    $ZipError ;
897
898    # IO::File mode
899
900    print $z $string;
901    printf $z $format, $string;
902    tell $z
903    eof $z
904    seek $z, $position, $whence
905    binmode $z
906    fileno $z
907    close $z ;
908
909
910=head1 DESCRIPTION
911
912This module provides a Perl interface that allows writing zip
913compressed data to files or buffer.
914
915The primary purpose of this module is to provide streaming write access to
916zip files and buffers. It is not a general-purpose file archiver. If that
917is what you want, check out C<Archive::Zip> or C<Archive::Zip::SimpleZip>.
918
919At present three compression methods are supported by IO::Compress::Zip,
920namely Store (no compression at all), Deflate, Bzip2 and LZMA.
921
922Note that to create Bzip2 content, the module C<IO::Compress::Bzip2> must
923be installed.
924
925Note that to create LZMA content, the module C<IO::Compress::Lzma> must
926be installed.
927
928For reading zip files/buffers, see the companion module
929L<IO::Uncompress::Unzip|IO::Uncompress::Unzip>.
930
931=head1 Functional Interface
932
933A top-level function, C<zip>, is provided to carry out
934"one-shot" compression between buffers and/or files. For finer
935control over the compression process, see the L</"OO Interface">
936section.
937
938    use IO::Compress::Zip qw(zip $ZipError) ;
939
940    zip $input_filename_or_reference => $output_filename_or_reference [,OPTS]
941        or die "zip failed: $ZipError\n";
942
943The functional interface needs Perl5.005 or better.
944
945=head2 zip $input_filename_or_reference => $output_filename_or_reference [, OPTS]
946
947C<zip> expects at least two parameters,
948C<$input_filename_or_reference> and C<$output_filename_or_reference>.
949
950=head3 The C<$input_filename_or_reference> parameter
951
952The parameter, C<$input_filename_or_reference>, is used to define the
953source of the uncompressed data.
954
955It can take one of the following forms:
956
957=over 5
958
959=item A filename
960
961If the <$input_filename_or_reference> parameter is a simple scalar, it is
962assumed to be a filename. This file will be opened for reading and the
963input data will be read from it.
964
965=item A filehandle
966
967If the C<$input_filename_or_reference> parameter is a filehandle, the input
968data will be read from it.  The string '-' can be used as an alias for
969standard input.
970
971=item A scalar reference
972
973If C<$input_filename_or_reference> is a scalar reference, the input data
974will be read from C<$$input_filename_or_reference>.
975
976=item An array reference
977
978If C<$input_filename_or_reference> is an array reference, each element in
979the array must be a filename.
980
981The input data will be read from each file in turn.
982
983The complete array will be walked to ensure that it only
984contains valid filenames before any data is compressed.
985
986=item An Input FileGlob string
987
988If C<$input_filename_or_reference> is a string that is delimited by the
989characters "<" and ">" C<zip> will assume that it is an
990I<input fileglob string>. The input is the list of files that match the
991fileglob.
992
993See L<File::GlobMapper|File::GlobMapper> for more details.
994
995=back
996
997If the C<$input_filename_or_reference> parameter is any other type,
998C<undef> will be returned.
999
1000In addition, if C<$input_filename_or_reference> is a simple filename,
1001the default values for
1002the C<Name>, C<Time>, C<TextFlag>, C<ExtAttr>, C<exUnixN> and C<exTime> options will be sourced from that file.
1003
1004If you do not want to use these defaults they can be overridden by
1005explicitly setting the C<Name>, C<Time>, C<TextFlag>, C<ExtAttr>, C<exUnixN> and C<exTime> options or by setting the
1006C<Minimal> parameter.
1007
1008=head3 The C<$output_filename_or_reference> parameter
1009
1010The parameter C<$output_filename_or_reference> is used to control the
1011destination of the compressed data. This parameter can take one of
1012these forms.
1013
1014=over 5
1015
1016=item A filename
1017
1018If the C<$output_filename_or_reference> parameter is a simple scalar, it is
1019assumed to be a filename.  This file will be opened for writing and the
1020compressed data will be written to it.
1021
1022=item A filehandle
1023
1024If the C<$output_filename_or_reference> parameter is a filehandle, the
1025compressed data will be written to it.  The string '-' can be used as
1026an alias for standard output.
1027
1028=item A scalar reference
1029
1030If C<$output_filename_or_reference> is a scalar reference, the
1031compressed data will be stored in C<$$output_filename_or_reference>.
1032
1033=item An Array Reference
1034
1035If C<$output_filename_or_reference> is an array reference,
1036the compressed data will be pushed onto the array.
1037
1038=item An Output FileGlob
1039
1040If C<$output_filename_or_reference> is a string that is delimited by the
1041characters "<" and ">" C<zip> will assume that it is an
1042I<output fileglob string>. The output is the list of files that match the
1043fileglob.
1044
1045When C<$output_filename_or_reference> is an fileglob string,
1046C<$input_filename_or_reference> must also be a fileglob string. Anything
1047else is an error.
1048
1049See L<File::GlobMapper|File::GlobMapper> for more details.
1050
1051=back
1052
1053If the C<$output_filename_or_reference> parameter is any other type,
1054C<undef> will be returned.
1055
1056=head2 Notes
1057
1058When C<$input_filename_or_reference> maps to multiple files/buffers and
1059C<$output_filename_or_reference> is a single
1060file/buffer the input files/buffers will each be stored
1061in C<$output_filename_or_reference> as a distinct entry.
1062
1063=head2 Optional Parameters
1064
1065Unless specified below, the optional parameters for C<zip>,
1066C<OPTS>, are the same as those used with the OO interface defined in the
1067L</"Constructor Options"> section below.
1068
1069=over 5
1070
1071=item C<< AutoClose => 0|1 >>
1072
1073This option applies to any input or output data streams to
1074C<zip> that are filehandles.
1075
1076If C<AutoClose> is specified, and the value is true, it will result in all
1077input and/or output filehandles being closed once C<zip> has
1078completed.
1079
1080This parameter defaults to 0.
1081
1082=item C<< BinModeIn => 0|1 >>
1083
1084This option is now a no-op. All files will be read in binmode.
1085
1086=item C<< Append => 0|1 >>
1087
1088The behaviour of this option is dependent on the type of output data
1089stream.
1090
1091=over 5
1092
1093=item * A Buffer
1094
1095If C<Append> is enabled, all compressed data will be append to the end of
1096the output buffer. Otherwise the output buffer will be cleared before any
1097compressed data is written to it.
1098
1099=item * A Filename
1100
1101If C<Append> is enabled, the file will be opened in append mode. Otherwise
1102the contents of the file, if any, will be truncated before any compressed
1103data is written to it.
1104
1105=item * A Filehandle
1106
1107If C<Append> is enabled, the filehandle will be positioned to the end of
1108the file via a call to C<seek> before any compressed data is
1109written to it.  Otherwise the file pointer will not be moved.
1110
1111=back
1112
1113When C<Append> is specified, and set to true, it will I<append> all compressed
1114data to the output data stream.
1115
1116So when the output is a filehandle it will carry out a seek to the eof
1117before writing any compressed data. If the output is a filename, it will be opened for
1118appending. If the output is a buffer, all compressed data will be
1119appended to the existing buffer.
1120
1121Conversely when C<Append> is not specified, or it is present and is set to
1122false, it will operate as follows.
1123
1124When the output is a filename, it will truncate the contents of the file
1125before writing any compressed data. If the output is a filehandle
1126its position will not be changed. If the output is a buffer, it will be
1127wiped before any compressed data is output.
1128
1129Defaults to 0.
1130
1131=back
1132
1133=head2 Examples
1134
1135To read the contents of the file C<file1.txt> and write the compressed
1136data to the file C<file1.txt.zip>.
1137
1138    use strict ;
1139    use warnings ;
1140    use IO::Compress::Zip qw(zip $ZipError) ;
1141
1142    my $input = "file1.txt";
1143    zip $input => "$input.zip"
1144        or die "zip failed: $ZipError\n";
1145
1146To read from an existing Perl filehandle, C<$input>, and write the
1147compressed data to a buffer, C<$buffer>.
1148
1149    use strict ;
1150    use warnings ;
1151    use IO::Compress::Zip qw(zip $ZipError) ;
1152    use IO::File ;
1153
1154    my $input = new IO::File "<file1.txt"
1155        or die "Cannot open 'file1.txt': $!\n" ;
1156    my $buffer ;
1157    zip $input => \$buffer
1158        or die "zip failed: $ZipError\n";
1159
1160To create a zip file, C<output.zip>, that contains the compressed contents
1161of the files C<alpha.txt> and C<beta.txt>
1162
1163    use strict ;
1164    use warnings ;
1165    use IO::Compress::Zip qw(zip $ZipError) ;
1166
1167    zip [ 'alpha.txt', 'beta.txt' ] => 'output.zip'
1168        or die "zip failed: $ZipError\n";
1169
1170Alternatively, rather than having to explicitly name each of the files that
1171you want to compress, you could use a fileglob to select all the C<txt>
1172files in the current directory, as follows
1173
1174    use strict ;
1175    use warnings ;
1176    use IO::Compress::Zip qw(zip $ZipError) ;
1177
1178    my @files = <*.txt>;
1179    zip \@files => 'output.zip'
1180        or die "zip failed: $ZipError\n";
1181
1182or more succinctly
1183
1184    zip [ <*.txt> ] => 'output.zip'
1185        or die "zip failed: $ZipError\n";
1186
1187=head1 OO Interface
1188
1189=head2 Constructor
1190
1191The format of the constructor for C<IO::Compress::Zip> is shown below
1192
1193    my $z = new IO::Compress::Zip $output [,OPTS]
1194        or die "IO::Compress::Zip failed: $ZipError\n";
1195
1196It returns an C<IO::Compress::Zip> object on success and undef on failure.
1197The variable C<$ZipError> will contain an error message on failure.
1198
1199If you are running Perl 5.005 or better the object, C<$z>, returned from
1200IO::Compress::Zip can be used exactly like an L<IO::File|IO::File> filehandle.
1201This means that all normal output file operations can be carried out
1202with C<$z>.
1203For example, to write to a compressed file/buffer you can use either of
1204these forms
1205
1206    $z->print("hello world\n");
1207    print $z "hello world\n";
1208
1209The mandatory parameter C<$output> is used to control the destination
1210of the compressed data. This parameter can take one of these forms.
1211
1212=over 5
1213
1214=item A filename
1215
1216If the C<$output> parameter is a simple scalar, it is assumed to be a
1217filename. This file will be opened for writing and the compressed data
1218will be written to it.
1219
1220=item A filehandle
1221
1222If the C<$output> parameter is a filehandle, the compressed data will be
1223written to it.
1224The string '-' can be used as an alias for standard output.
1225
1226=item A scalar reference
1227
1228If C<$output> is a scalar reference, the compressed data will be stored
1229in C<$$output>.
1230
1231=back
1232
1233If the C<$output> parameter is any other type, C<IO::Compress::Zip>::new will
1234return undef.
1235
1236=head2 Constructor Options
1237
1238C<OPTS> is any combination of the following options:
1239
1240=over 5
1241
1242=item C<< AutoClose => 0|1 >>
1243
1244This option is only valid when the C<$output> parameter is a filehandle. If
1245specified, and the value is true, it will result in the C<$output> being
1246closed once either the C<close> method is called or the C<IO::Compress::Zip>
1247object is destroyed.
1248
1249This parameter defaults to 0.
1250
1251=item C<< Append => 0|1 >>
1252
1253Opens C<$output> in append mode.
1254
1255The behaviour of this option is dependent on the type of C<$output>.
1256
1257=over 5
1258
1259=item * A Buffer
1260
1261If C<$output> is a buffer and C<Append> is enabled, all compressed data
1262will be append to the end of C<$output>. Otherwise C<$output> will be
1263cleared before any data is written to it.
1264
1265=item * A Filename
1266
1267If C<$output> is a filename and C<Append> is enabled, the file will be
1268opened in append mode. Otherwise the contents of the file, if any, will be
1269truncated before any compressed data is written to it.
1270
1271=item * A Filehandle
1272
1273If C<$output> is a filehandle, the file pointer will be positioned to the
1274end of the file via a call to C<seek> before any compressed data is written
1275to it.  Otherwise the file pointer will not be moved.
1276
1277=back
1278
1279This parameter defaults to 0.
1280
1281=item C<< Name => $string >>
1282
1283Stores the contents of C<$string> in the zip filename header field.
1284
1285If C<Name> is not specified and the C<$input> parameter is a filename, the
1286value of C<$input> will be used for the zip filename header field.
1287
1288If C<Name> is not specified and the C<$input> parameter is not a filename,
1289no zip filename field will be created.
1290
1291Note that both the C<CanonicalName> and C<FilterName> options
1292can modify the value used for the zip filename header field.
1293
1294=item C<< CanonicalName => 0|1 >>
1295
1296This option controls whether the filename field in the zip header is
1297I<normalized> into Unix format before being written to the zip file.
1298
1299It is recommended that you enable this option unless you really need
1300to create a non-standard Zip file.
1301
1302This is what APPNOTE.TXT has to say on what should be stored in the zip
1303filename header field.
1304
1305    The name of the file, with optional relative path.
1306    The path stored should not contain a drive or
1307    device letter, or a leading slash.  All slashes
1308    should be forward slashes '/' as opposed to
1309    backwards slashes '\' for compatibility with Amiga
1310    and UNIX file systems etc.
1311
1312This option defaults to B<false>.
1313
1314=item C<< FilterName => sub { ... }  >>
1315
1316This option allow the filename field in the zip header to be modified
1317before it is written to the zip file.
1318
1319This option takes a parameter that must be a reference to a sub.  On entry
1320to the sub the C<$_> variable will contain the name to be filtered. If no
1321filename is available C<$_> will contain an empty string.
1322
1323The value of C<$_> when the sub returns will be  stored in the filename
1324header field.
1325
1326Note that if C<CanonicalName> is enabled, a
1327normalized filename will be passed to the sub.
1328
1329If you use C<FilterName> to modify the filename, it is your responsibility
1330to keep the filename in Unix format.
1331
1332Although this option can be used with the OO interface, it is of most use
1333with the one-shot interface. For example, the code below shows how
1334C<FilterName> can be used to remove the path component from a series of
1335filenames before they are stored in C<$zipfile>.
1336
1337    sub compressTxtFiles
1338    {
1339        my $zipfile = shift ;
1340        my $dir     = shift ;
1341
1342        zip [ <$dir/*.txt> ] => $zipfile,
1343            FilterName => sub { s[^$dir/][] } ;
1344    }
1345
1346=item C<< Time => $number >>
1347
1348Sets the last modified time field in the zip header to $number.
1349
1350This field defaults to the time the C<IO::Compress::Zip> object was created
1351if this option is not specified and the C<$input> parameter is not a
1352filename.
1353
1354=item C<< ExtAttr => $attr >>
1355
1356This option controls the "external file attributes" field in the central
1357header of the zip file. This is a 4 byte field.
1358
1359If you are running a Unix derivative this value defaults to
1360
1361    0100644 << 16
1362
1363This should allow read/write access to any files that are extracted from
1364the zip file/buffer`.
1365
1366For all other systems it defaults to 0.
1367
1368=item C<< exTime => [$atime, $mtime, $ctime] >>
1369
1370This option expects an array reference with exactly three elements:
1371C<$atime>, C<mtime> and C<$ctime>. These correspond to the last access
1372time, last modification time and creation time respectively.
1373
1374It uses these values to set the extended timestamp field (ID is "UT") in
1375the local zip header using the three values, $atime, $mtime, $ctime. In
1376addition it sets the extended timestamp field in the central zip header
1377using C<$mtime>.
1378
1379If any of the three values is C<undef> that time value will not be used.
1380So, for example, to set only the C<$mtime> you would use this
1381
1382    exTime => [undef, $mtime, undef]
1383
1384If the C<Minimal> option is set to true, this option will be ignored.
1385
1386By default no extended time field is created.
1387
1388=item C<< exUnix2 => [$uid, $gid] >>
1389
1390This option expects an array reference with exactly two elements: C<$uid>
1391and C<$gid>. These values correspond to the numeric User ID (UID) and Group ID
1392(GID) of the owner of the files respectively.
1393
1394When the C<exUnix2> option is present it will trigger the creation of a
1395Unix2 extra field (ID is "Ux") in the local zip header. This will be populated
1396with C<$uid> and C<$gid>. An empty Unix2 extra field will also
1397be created in the central zip header.
1398
1399Note - The UID & GID are stored as 16-bit
1400integers in the "Ux" field. Use C<< exUnixN >> if your UID or GID are
140132-bit.
1402
1403If the C<Minimal> option is set to true, this option will be ignored.
1404
1405By default no Unix2 extra field is created.
1406
1407=item C<< exUnixN => [$uid, $gid] >>
1408
1409This option expects an array reference with exactly two elements: C<$uid>
1410and C<$gid>. These values correspond to the numeric User ID (UID) and Group ID
1411(GID) of the owner of the files respectively.
1412
1413When the C<exUnixN> option is present it will trigger the creation of a
1414UnixN extra field (ID is "ux") in both the local and central zip headers.
1415This will be populated with C<$uid> and C<$gid>.
1416The UID & GID are stored as 32-bit integers.
1417
1418If the C<Minimal> option is set to true, this option will be ignored.
1419
1420By default no UnixN extra field is created.
1421
1422=item C<< Comment => $comment >>
1423
1424Stores the contents of C<$comment> in the Central File Header of
1425the zip file.
1426
1427By default, no comment field is written to the zip file.
1428
1429=item C<< ZipComment => $comment >>
1430
1431Stores the contents of C<$comment> in the End of Central Directory record
1432of the zip file.
1433
1434By default, no comment field is written to the zip file.
1435
1436=item C<< Method => $method >>
1437
1438Controls which compression method is used. At present four compression
1439methods are supported, namely Store (no compression at all), Deflate,
1440Bzip2 and Lzma.
1441
1442The symbols, ZIP_CM_STORE, ZIP_CM_DEFLATE, ZIP_CM_BZIP2 and ZIP_CM_LZMA
1443are used to select the compression method.
1444
1445These constants are not imported by C<IO::Compress::Zip> by default.
1446
1447    use IO::Compress::Zip qw(:zip_method);
1448    use IO::Compress::Zip qw(:constants);
1449    use IO::Compress::Zip qw(:all);
1450
1451Note that to create Bzip2 content, the module C<IO::Compress::Bzip2> must
1452be installed. A fatal error will be thrown if you attempt to create Bzip2
1453content when C<IO::Compress::Bzip2> is not available.
1454
1455Note that to create Lzma content, the module C<IO::Compress::Lzma> must
1456be installed. A fatal error will be thrown if you attempt to create Lzma
1457content when C<IO::Compress::Lzma> is not available.
1458
1459The default method is ZIP_CM_DEFLATE.
1460
1461=item C<< Stream => 0|1 >>
1462
1463This option controls whether the zip file/buffer output is created in
1464streaming mode.
1465
1466Note that when outputting to a file with streaming mode disabled (C<Stream>
1467is 0), the output file must be seekable.
1468
1469The default is 1.
1470
1471=item C<< Zip64 => 0|1 >>
1472
1473Create a Zip64 zip file/buffer. This option is used if you want
1474to store files larger than 4 Gig or store more than 64K files in a single
1475zip archive.
1476
1477C<Zip64> will be automatically set, as needed, if working with the one-shot
1478interface when the input is either a filename or a scalar reference.
1479
1480If you intend to manipulate the Zip64 zip files created with this module
1481using an external zip/unzip, make sure that it supports Zip64.
1482
1483In particular, if you are using Info-Zip you need to have zip version 3.x
1484or better to update a Zip64 archive and unzip version 6.x to read a zip64
1485archive.
1486
1487The default is 0.
1488
1489=item C<< TextFlag => 0|1 >>
1490
1491This parameter controls the setting of a bit in the zip central header. It
1492is used to signal that the data stored in the zip file/buffer is probably
1493text.
1494
1495In one-shot mode this flag will be set to true if the Perl C<-T> operator thinks
1496the file contains text.
1497
1498The default is 0.
1499
1500=item C<< ExtraFieldLocal => $data >>
1501
1502=item C<< ExtraFieldCentral => $data >>
1503
1504The C<ExtraFieldLocal> option is used to store additional metadata in the
1505local header for the zip file/buffer. The C<ExtraFieldCentral> does the
1506same for the matching central header.
1507
1508An extra field consists of zero or more subfields. Each subfield consists
1509of a two byte header followed by the subfield data.
1510
1511The list of subfields can be supplied in any of the following formats
1512
1513    ExtraFieldLocal => [$id1, $data1,
1514                        $id2, $data2,
1515                         ...
1516                       ]
1517
1518    ExtraFieldLocal => [ [$id1 => $data1],
1519                         [$id2 => $data2],
1520                         ...
1521                       ]
1522
1523    ExtraFieldLocal => { $id1 => $data1,
1524                         $id2 => $data2,
1525                         ...
1526                       }
1527
1528Where C<$id1>, C<$id2> are two byte subfield ID's.
1529
1530If you use the hash syntax, you have no control over the order in which
1531the ExtraSubFields are stored, plus you cannot have SubFields with
1532duplicate ID.
1533
1534Alternatively the list of subfields can by supplied as a scalar, thus
1535
1536    ExtraField => $rawdata
1537
1538In this case C<IO::Compress::Zip> will check that C<$rawdata> consists of
1539zero or more conformant sub-fields.
1540
1541The Extended Time field (ID "UT"), set using the C<exTime> option, and the
1542Unix2 extra field (ID "Ux), set using the C<exUnix2> option, are examples
1543of extra fields.
1544
1545If the C<Minimal> option is set to true, this option will be ignored.
1546
1547The maximum size of an extra field 65535 bytes.
1548
1549=item C<< Minimal => 1|0 >>
1550
1551If specified, this option will disable the creation of all extra fields
1552in the zip local and central headers. So the C<exTime>, C<exUnix2>,
1553C<exUnixN>, C<ExtraFieldLocal> and C<ExtraFieldCentral> options will
1554be ignored.
1555
1556This parameter defaults to 0.
1557
1558=item C<< BlockSize100K => number >>
1559
1560Specify the number of 100K blocks bzip2 uses during compression.
1561
1562Valid values are from 1 to 9, where 9 is best compression.
1563
1564This option is only valid if the C<Method> is ZIP_CM_BZIP2. It is ignored
1565otherwise.
1566
1567The default is 1.
1568
1569=item C<< WorkFactor => number >>
1570
1571Specifies how much effort bzip2 should take before resorting to a slower
1572fallback compression algorithm.
1573
1574Valid values range from 0 to 250, where 0 means use the default value 30.
1575
1576This option is only valid if the C<Method> is ZIP_CM_BZIP2. It is ignored
1577otherwise.
1578
1579The default is 0.
1580
1581=item C<< Preset => number >>
1582
1583Used to choose the LZMA compression preset.
1584
1585Valid values are 0-9 and C<LZMA_PRESET_DEFAULT>.
1586
15870 is the fastest compression with the lowest memory usage and the lowest
1588compression.
1589
15909 is the slowest compression with the highest memory usage but with the best
1591compression.
1592
1593This option is only valid if the C<Method> is ZIP_CM_LZMA. It is ignored
1594otherwise.
1595
1596Defaults to C<LZMA_PRESET_DEFAULT> (6).
1597
1598=item C<< Extreme => 0|1 >>
1599
1600Makes LZMA compression a lot slower, but a small compression gain.
1601
1602This option is only valid if the C<Method> is ZIP_CM_LZMA. It is ignored
1603otherwise.
1604
1605Defaults to 0.
1606
1607=item -Level
1608
1609Defines the compression level used by zlib. The value should either be
1610a number between 0 and 9 (0 means no compression and 9 is maximum
1611compression), or one of the symbolic constants defined below.
1612
1613   Z_NO_COMPRESSION
1614   Z_BEST_SPEED
1615   Z_BEST_COMPRESSION
1616   Z_DEFAULT_COMPRESSION
1617
1618The default is Z_DEFAULT_COMPRESSION.
1619
1620Note, these constants are not imported by C<IO::Compress::Zip> by default.
1621
1622    use IO::Compress::Zip qw(:strategy);
1623    use IO::Compress::Zip qw(:constants);
1624    use IO::Compress::Zip qw(:all);
1625
1626=item -Strategy
1627
1628Defines the strategy used to tune the compression. Use one of the symbolic
1629constants defined below.
1630
1631   Z_FILTERED
1632   Z_HUFFMAN_ONLY
1633   Z_RLE
1634   Z_FIXED
1635   Z_DEFAULT_STRATEGY
1636
1637The default is Z_DEFAULT_STRATEGY.
1638
1639=item C<< Strict => 0|1 >>
1640
1641This is a placeholder option.
1642
1643=back
1644
1645=head2 Examples
1646
1647TODO
1648
1649=head1 Methods
1650
1651=head2 print
1652
1653Usage is
1654
1655    $z->print($data)
1656    print $z $data
1657
1658Compresses and outputs the contents of the C<$data> parameter. This
1659has the same behaviour as the C<print> built-in.
1660
1661Returns true if successful.
1662
1663=head2 printf
1664
1665Usage is
1666
1667    $z->printf($format, $data)
1668    printf $z $format, $data
1669
1670Compresses and outputs the contents of the C<$data> parameter.
1671
1672Returns true if successful.
1673
1674=head2 syswrite
1675
1676Usage is
1677
1678    $z->syswrite $data
1679    $z->syswrite $data, $length
1680    $z->syswrite $data, $length, $offset
1681
1682Compresses and outputs the contents of the C<$data> parameter.
1683
1684Returns the number of uncompressed bytes written, or C<undef> if
1685unsuccessful.
1686
1687=head2 write
1688
1689Usage is
1690
1691    $z->write $data
1692    $z->write $data, $length
1693    $z->write $data, $length, $offset
1694
1695Compresses and outputs the contents of the C<$data> parameter.
1696
1697Returns the number of uncompressed bytes written, or C<undef> if
1698unsuccessful.
1699
1700=head2 flush
1701
1702Usage is
1703
1704    $z->flush;
1705    $z->flush($flush_type);
1706
1707Flushes any pending compressed data to the output file/buffer.
1708
1709This method takes an optional parameter, C<$flush_type>, that controls
1710how the flushing will be carried out. By default the C<$flush_type>
1711used is C<Z_FINISH>. Other valid values for C<$flush_type> are
1712C<Z_NO_FLUSH>, C<Z_SYNC_FLUSH>, C<Z_FULL_FLUSH> and C<Z_BLOCK>. It is
1713strongly recommended that you only set the C<flush_type> parameter if
1714you fully understand the implications of what it does - overuse of C<flush>
1715can seriously degrade the level of compression achieved. See the C<zlib>
1716documentation for details.
1717
1718Returns true on success.
1719
1720=head2 tell
1721
1722Usage is
1723
1724    $z->tell()
1725    tell $z
1726
1727Returns the uncompressed file offset.
1728
1729=head2 eof
1730
1731Usage is
1732
1733    $z->eof();
1734    eof($z);
1735
1736Returns true if the C<close> method has been called.
1737
1738=head2 seek
1739
1740    $z->seek($position, $whence);
1741    seek($z, $position, $whence);
1742
1743Provides a sub-set of the C<seek> functionality, with the restriction
1744that it is only legal to seek forward in the output file/buffer.
1745It is a fatal error to attempt to seek backward.
1746
1747Empty parts of the file/buffer will have NULL (0x00) bytes written to them.
1748
1749The C<$whence> parameter takes one the usual values, namely SEEK_SET,
1750SEEK_CUR or SEEK_END.
1751
1752Returns 1 on success, 0 on failure.
1753
1754=head2 binmode
1755
1756Usage is
1757
1758    $z->binmode
1759    binmode $z ;
1760
1761This is a noop provided for completeness.
1762
1763=head2 opened
1764
1765    $z->opened()
1766
1767Returns true if the object currently refers to a opened file/buffer.
1768
1769=head2 autoflush
1770
1771    my $prev = $z->autoflush()
1772    my $prev = $z->autoflush(EXPR)
1773
1774If the C<$z> object is associated with a file or a filehandle, this method
1775returns the current autoflush setting for the underlying filehandle. If
1776C<EXPR> is present, and is non-zero, it will enable flushing after every
1777write/print operation.
1778
1779If C<$z> is associated with a buffer, this method has no effect and always
1780returns C<undef>.
1781
1782B<Note> that the special variable C<$|> B<cannot> be used to set or
1783retrieve the autoflush setting.
1784
1785=head2 input_line_number
1786
1787    $z->input_line_number()
1788    $z->input_line_number(EXPR)
1789
1790This method always returns C<undef> when compressing.
1791
1792=head2 fileno
1793
1794    $z->fileno()
1795    fileno($z)
1796
1797If the C<$z> object is associated with a file or a filehandle, C<fileno>
1798will return the underlying file descriptor. Once the C<close> method is
1799called C<fileno> will return C<undef>.
1800
1801If the C<$z> object is associated with a buffer, this method will return
1802C<undef>.
1803
1804=head2 close
1805
1806    $z->close() ;
1807    close $z ;
1808
1809Flushes any pending compressed data and then closes the output file/buffer.
1810
1811For most versions of Perl this method will be automatically invoked if
1812the IO::Compress::Zip object is destroyed (either explicitly or by the
1813variable with the reference to the object going out of scope). The
1814exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
1815these cases, the C<close> method will be called automatically, but
1816not until global destruction of all live objects when the program is
1817terminating.
1818
1819Therefore, if you want your scripts to be able to run on all versions
1820of Perl, you should call C<close> explicitly and not rely on automatic
1821closing.
1822
1823Returns true on success, otherwise 0.
1824
1825If the C<AutoClose> option has been enabled when the IO::Compress::Zip
1826object was created, and the object is associated with a file, the
1827underlying file will also be closed.
1828
1829=head2 newStream([OPTS])
1830
1831Usage is
1832
1833    $z->newStream( [OPTS] )
1834
1835Closes the current compressed data stream and starts a new one.
1836
1837OPTS consists of any of the options that are available when creating
1838the C<$z> object.
1839
1840See the L</"Constructor Options"> section for more details.
1841
1842=head2 deflateParams
1843
1844Usage is
1845
1846    $z->deflateParams
1847
1848TODO
1849
1850=head1 Importing
1851
1852A number of symbolic constants are required by some methods in
1853C<IO::Compress::Zip>. None are imported by default.
1854
1855=over 5
1856
1857=item :all
1858
1859Imports C<zip>, C<$ZipError> and all symbolic
1860constants that can be used by C<IO::Compress::Zip>. Same as doing this
1861
1862    use IO::Compress::Zip qw(zip $ZipError :constants) ;
1863
1864=item :constants
1865
1866Import all symbolic constants. Same as doing this
1867
1868    use IO::Compress::Zip qw(:flush :level :strategy :zip_method) ;
1869
1870=item :flush
1871
1872These symbolic constants are used by the C<flush> method.
1873
1874    Z_NO_FLUSH
1875    Z_PARTIAL_FLUSH
1876    Z_SYNC_FLUSH
1877    Z_FULL_FLUSH
1878    Z_FINISH
1879    Z_BLOCK
1880
1881=item :level
1882
1883These symbolic constants are used by the C<Level> option in the constructor.
1884
1885    Z_NO_COMPRESSION
1886    Z_BEST_SPEED
1887    Z_BEST_COMPRESSION
1888    Z_DEFAULT_COMPRESSION
1889
1890=item :strategy
1891
1892These symbolic constants are used by the C<Strategy> option in the constructor.
1893
1894    Z_FILTERED
1895    Z_HUFFMAN_ONLY
1896    Z_RLE
1897    Z_FIXED
1898    Z_DEFAULT_STRATEGY
1899
1900=item :zip_method
1901
1902These symbolic constants are used by the C<Method> option in the
1903constructor.
1904
1905    ZIP_CM_STORE
1906    ZIP_CM_DEFLATE
1907    ZIP_CM_BZIP2
1908
1909=back
1910
1911=head1 EXAMPLES
1912
1913=head2 Apache::GZip Revisited
1914
1915See L<IO::Compress::FAQ|IO::Compress::FAQ/"Apache::GZip Revisited">
1916
1917=head2 Working with Net::FTP
1918
1919See L<IO::Compress::FAQ|IO::Compress::FAQ/"Compressed files and Net::FTP">
1920
1921=head1 SEE ALSO
1922
1923L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzip>, L<IO::Uncompress::UnLzip>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Compress::Zstd>, L<IO::Uncompress::UnZstd>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
1924
1925L<IO::Compress::FAQ|IO::Compress::FAQ>
1926
1927L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
1928L<Archive::Tar|Archive::Tar>,
1929L<IO::Zlib|IO::Zlib>
1930
1931For RFC 1950, 1951 and 1952 see
1932L<http://www.faqs.org/rfcs/rfc1950.html>,
1933L<http://www.faqs.org/rfcs/rfc1951.html> and
1934L<http://www.faqs.org/rfcs/rfc1952.html>
1935
1936The I<zlib> compression library was written by Jean-loup Gailly
1937C<gzip@prep.ai.mit.edu> and Mark Adler C<madler@alumni.caltech.edu>.
1938
1939The primary site for the I<zlib> compression library is
1940L<http://www.zlib.org>.
1941
1942The primary site for gzip is L<http://www.gzip.org>.
1943
1944=head1 AUTHOR
1945
1946This module was written by Paul Marquess, C<pmqs@cpan.org>.
1947
1948=head1 MODIFICATION HISTORY
1949
1950See the Changes file.
1951
1952=head1 COPYRIGHT AND LICENSE
1953
1954Copyright (c) 2005-2019 Paul Marquess. All rights reserved.
1955
1956This program is free software; you can redistribute it and/or
1957modify it under the same terms as Perl itself.
1958
1959