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