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