1package IO::Compress::Zip ;
2
3use strict ;
4use warnings;
5use bytes;
6
7use IO::Compress::Base::Common  2.212 qw(:Status );
8use IO::Compress::RawDeflate 2.212 ();
9use IO::Compress::Adapter::Deflate 2.212 ;
10use IO::Compress::Adapter::Identity 2.212 ;
11use IO::Compress::Zlib::Extra 2.212 ;
12use IO::Compress::Zip::Constants 2.212 ;
13
14use File::Spec();
15use Config;
16
17use Compress::Raw::Zlib  2.212 ();
18
19BEGIN
20{
21    eval { require IO::Compress::Adapter::Bzip2 ;
22           IO::Compress::Adapter::Bzip2->VERSION( 2.212 );
23           require IO::Compress::Bzip2 ;
24           IO::Compress::Bzip2->VERSION( 2.212 );
25         } ;
26
27    eval { require IO::Compress::Adapter::Lzma ;
28           IO::Compress::Adapter::Lzma->VERSION( 2.212 );
29           require IO::Compress::Lzma ;
30           IO::Compress::Lzma->VERSION( 2.212 );
31         } ;
32
33    eval { require IO::Compress::Adapter::Xz ;
34           IO::Compress::Adapter::Xz->VERSION( 2.212 );
35           require IO::Compress::Xz ;
36           IO::Compress::Xz->VERSION( 2.212 );
37         } ;
38    eval { require IO::Compress::Adapter::Zstd ;
39           IO::Compress::Adapter::Zstd->VERSION( 2.212 );
40           require IO::Compress::Zstd ;
41           IO::Compress::Zstd->VERSION( 2.212 );
42         } ;
43}
44
45
46require Exporter ;
47
48our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, %DEFLATE_CONSTANTS, $ZipError);
49
50$VERSION = '2.212';
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 &&
89           defined $IO::Compress::Adapter::Bzip2::VERSION &&
90           defined &{ "IO::Compress::Adapter::Bzip2::mkRawZipCompObject" };
91
92    return 1
93        if $method == ZIP_CM_LZMA &&
94           defined $IO::Compress::Adapter::Lzma::VERSION &&
95           defined &{ "IO::Compress::Adapter::Lzma::mkRawZipCompObject" };
96
97    return 1
98        if $method == ZIP_CM_XZ &&
99           defined $IO::Compress::Adapter::Xz::VERSION &&
100           defined &{ "IO::Compress::Adapter::Xz::mkRawZipCompObject" };
101
102    return 1
103        if $method == ZIP_CM_ZSTD &&
104           defined $IO::Compress::Adapter::ZSTD::VERSION &&
105           defined &{ "IO::Compress::Adapter::ZSTD::mkRawZipCompObject" };
106
107    return 0;
108}
109
110sub beforePayload
111{
112    my $self = shift ;
113
114    if (*$self->{ZipData}{Sparse} ) {
115        my $inc = 1024 * 100 ;
116        my $NULLS = ("\x00" x $inc) ;
117        my $sparse = *$self->{ZipData}{Sparse} ;
118        *$self->{CompSize}->add( $sparse );
119        *$self->{UnCompSize}->add( $sparse );
120
121        *$self->{FH}->seek($sparse, IO::Handle::SEEK_CUR);
122
123        *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32($NULLS, *$self->{ZipData}{CRC32})
124            for 1 .. int $sparse / $inc;
125        *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32(substr($NULLS, 0,  $sparse % $inc),
126                                         *$self->{ZipData}{CRC32})
127            if $sparse % $inc;
128    }
129}
130
131sub mkComp
132{
133    my $self = shift ;
134    my $got = shift ;
135
136    my ($obj, $errstr, $errno) ;
137
138    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 Oneshot 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
1320The constructor takes one mandatory parameter, C<$output>, defined below and
1321zero or more C<OPTS>, defined in L<Constructor Options>.
1322
1323It returns an C<IO::Compress::Zip> object on success and C<undef> on failure.
1324The variable C<$ZipError> will contain an error message on failure.
1325
1326If you are running Perl 5.005 or better the object, C<$z>, returned from
1327IO::Compress::Zip can be used exactly like an L<IO::File|IO::File> filehandle.
1328This means that all normal output file operations can be carried out
1329with C<$z>.
1330For example, to write to a compressed file/buffer you can use either of
1331these forms
1332
1333    $z->print("hello world\n");
1334    print $z "hello world\n";
1335
1336Below is a simple exaple of using the OO interface to create an output file
1337C<myfile.zip> and write some data to it.
1338
1339    my $filename = "myfile.zip";
1340    my $z = IO::Compress::Zip->new($filename)
1341        or die "IO::Compress::Zip failed: $ZipError\n";
1342
1343    $z->print("abcde");
1344    $z->close();
1345
1346See the L</Examples> for more.
1347
1348The mandatory parameter C<$output> is used to control the destination
1349of the compressed data. This parameter can take one of these forms.
1350
1351=over 5
1352
1353=item A filename
1354
1355If the C<$output> parameter is a simple scalar, it is assumed to be a
1356filename. This file will be opened for writing and the compressed data
1357will be written to it.
1358
1359=item A filehandle
1360
1361If the C<$output> parameter is a filehandle, the compressed data will be
1362written to it.
1363The string '-' can be used as an alias for standard output.
1364
1365=item A scalar reference
1366
1367If C<$output> is a scalar reference, the compressed data will be stored
1368in C<$$output>.
1369
1370=back
1371
1372If the C<$output> parameter is any other type, C<IO::Compress::Zip>::new will
1373return undef.
1374
1375=head2 Constructor Options
1376
1377C<OPTS> is any combination of zero or more the following options:
1378
1379=over 5
1380
1381=item C<< AutoClose => 0|1 >>
1382
1383This option is only valid when the C<$output> parameter is a filehandle. If
1384specified, and the value is true, it will result in the C<$output> being
1385closed once either the C<close> method is called or the C<IO::Compress::Zip>
1386object is destroyed.
1387
1388This parameter defaults to 0.
1389
1390=item C<< Append => 0|1 >>
1391
1392Opens C<$output> in append mode.
1393
1394The behaviour of this option is dependent on the type of C<$output>.
1395
1396=over 5
1397
1398=item * A Buffer
1399
1400If C<$output> is a buffer and C<Append> is enabled, all compressed data
1401will be append to the end of C<$output>. Otherwise C<$output> will be
1402cleared before any data is written to it.
1403
1404=item * A Filename
1405
1406If C<$output> is a filename and C<Append> is enabled, the file will be
1407opened in append mode. Otherwise the contents of the file, if any, will be
1408truncated before any compressed data is written to it.
1409
1410=item * A Filehandle
1411
1412If C<$output> is a filehandle, the file pointer will be positioned to the
1413end of the file via a call to C<seek> before any compressed data is written
1414to it.  Otherwise the file pointer will not be moved.
1415
1416=back
1417
1418This parameter defaults to 0.
1419
1420=back
1421
1422=head3 File Naming Options
1423
1424A quick bit of zip file terminology -- A zip archive consists of one or more I<archive members>, where each member has an associated
1425filename, known as the I<archive member name>.
1426
1427The options listed in this section control how the I<archive member name> (or filename) is stored the zip archive.
1428
1429=over 5
1430
1431=item C<< Name => $string >>
1432
1433This option is used to explicitly set the I<archive member name> in
1434the zip archive to C<$string>.
1435Most of the time you don't need to make use of this option.
1436By default when adding a filename to the zip archive, the I<archive member name> will match the filename.
1437
1438You should only need to use this option if you want the I<archive member name>
1439to be different from the uncompressed filename or when the input is a filehandle or a buffer.
1440
1441The default behaviour for what I<archive member name> is used when the C<Name> option
1442is I<not> specified depends on the form of the C<$input> parameter:
1443
1444=over 5
1445
1446=item *
1447
1448If the C<$input> parameter is a filename, the
1449value of C<$input> will be used for the I<archive member name> .
1450
1451=item *
1452If the C<$input> parameter is not a filename,
1453the I<archive member name> will be an empty string.
1454
1455=back
1456
1457Note that both the C<CanonicalName> and C<FilterName> options
1458can modify the value used for the I<archive member name>.
1459
1460Also note that you should set the C<Efs> option to true if you are working
1461with UTF8 filenames.
1462
1463=item C<< CanonicalName => 0|1 >>
1464
1465This option controls whether the I<archive member name> is
1466I<normalized> into Unix format before being written to the zip file.
1467
1468It is recommended that you enable this option unless you really need
1469to create a non-standard Zip file.
1470
1471This is what APPNOTE.TXT has to say on what should be stored in the zip
1472filename header field.
1473
1474    The name of the file, with optional relative path.
1475    The path stored should not contain a drive or
1476    device letter, or a leading slash.  All slashes
1477    should be forward slashes '/' as opposed to
1478    backwards slashes '\' for compatibility with Amiga
1479    and UNIX file systems etc.
1480
1481This option defaults to B<false>.
1482
1483=item C<< FilterName => sub { ... }  >>
1484
1485This option allow the I<archive member> name to be modified
1486before it is written to the zip file.
1487
1488This option takes a parameter that must be a reference to a sub.  On entry
1489to the sub the C<$_> variable will contain the name to be filtered. If no
1490filename is available C<$_> will contain an empty string.
1491
1492The value of C<$_> when the sub returns will be  used as the I<archive member name>.
1493
1494Note that if C<CanonicalName> is enabled, a
1495normalized filename will be passed to the sub.
1496
1497If you use C<FilterName> to modify the filename, it is your responsibility
1498to keep the filename in Unix format.
1499
1500Although this option can be used with the OO interface, it is of most use
1501with the one-shot interface. For example, the code below shows how
1502C<FilterName> can be used to remove the path component from a series of
1503filenames before they are stored in C<$zipfile>.
1504
1505    sub compressTxtFiles
1506    {
1507        my $zipfile = shift ;
1508        my $dir     = shift ;
1509
1510        zip [ <$dir/*.txt> ] => $zipfile,
1511            FilterName => sub { s[^$dir/][] } ;
1512    }
1513
1514=item C<< Efs => 0|1 >>
1515
1516This option controls setting of the "Language Encoding Flag" (EFS) in the zip
1517archive. When set, the filename and comment fields for the zip archive MUST
1518be valid UTF-8.
1519
1520If the string used for the filename and/or comment is not valid UTF-8 when this option
1521is true, the script will die with a "wide character" error.
1522
1523Note that this option only works with Perl 5.8.4 or better.
1524
1525This option defaults to B<false>.
1526
1527=back
1528
1529=head3 Overall Zip Archive Structure
1530
1531=over 5
1532
1533=item C<< Minimal => 1|0 >>
1534
1535If specified, this option will disable the creation of all extra fields
1536in the zip local and central headers. So the C<exTime>, C<exUnix2>,
1537C<exUnixN>, C<ExtraFieldLocal> and C<ExtraFieldCentral> options will
1538be ignored.
1539
1540This parameter defaults to 0.
1541
1542=item C<< Stream => 0|1 >>
1543
1544This option controls whether the zip file/buffer output is created in
1545streaming mode.
1546
1547Note that when outputting to a file with streaming mode disabled (C<Stream>
1548is 0), the output file must be seekable.
1549
1550The default is 1.
1551
1552=item C<< Zip64 => 0|1 >>
1553
1554Create a Zip64 zip file/buffer. This option is used if you want
1555to store files larger than 4 Gig or store more than 64K files in a single
1556zip archive.
1557
1558C<Zip64> will be automatically set, as needed, if working with the one-shot
1559interface when the input is either a filename or a scalar reference.
1560
1561If you intend to manipulate the Zip64 zip files created with this module
1562using an external zip/unzip, make sure that it supports Zip64.
1563
1564In particular, if you are using Info-Zip you need to have zip version 3.x
1565or better to update a Zip64 archive and unzip version 6.x to read a zip64
1566archive.
1567
1568The default is 0.
1569
1570=back
1571
1572=head3 Deflate Compression Options
1573
1574=over 5
1575
1576=item -Level
1577
1578Defines the compression level used by zlib. The value should either be
1579a number between 0 and 9 (0 means no compression and 9 is maximum
1580compression), or one of the symbolic constants defined below.
1581
1582   Z_NO_COMPRESSION
1583   Z_BEST_SPEED
1584   Z_BEST_COMPRESSION
1585   Z_DEFAULT_COMPRESSION
1586
1587The default is Z_DEFAULT_COMPRESSION.
1588
1589Note, these constants are not imported by C<IO::Compress::Zip> by default.
1590
1591    use IO::Compress::Zip qw(:strategy);
1592    use IO::Compress::Zip qw(:constants);
1593    use IO::Compress::Zip qw(:all);
1594
1595=item -Strategy
1596
1597Defines the strategy used to tune the compression. Use one of the symbolic
1598constants defined below.
1599
1600   Z_FILTERED
1601   Z_HUFFMAN_ONLY
1602   Z_RLE
1603   Z_FIXED
1604   Z_DEFAULT_STRATEGY
1605
1606The default is Z_DEFAULT_STRATEGY.
1607
1608=back
1609
1610=head3 Bzip2 Compression Options
1611
1612=over 5
1613
1614=item C<< BlockSize100K => number >>
1615
1616Specify the number of 100K blocks bzip2 uses during compression.
1617
1618Valid values are from 1 to 9, where 9 is best compression.
1619
1620This option is only valid if the C<Method> is ZIP_CM_BZIP2. It is ignored
1621otherwise.
1622
1623The default is 1.
1624
1625=item C<< WorkFactor => number >>
1626
1627Specifies how much effort bzip2 should take before resorting to a slower
1628fallback compression algorithm.
1629
1630Valid values range from 0 to 250, where 0 means use the default value 30.
1631
1632This option is only valid if the C<Method> is ZIP_CM_BZIP2. It is ignored
1633otherwise.
1634
1635The default is 0.
1636
1637=back
1638
1639=head3 Lzma and Xz Compression Options
1640
1641=over 5
1642
1643=item C<< Preset => number >>
1644
1645Used to choose the LZMA compression preset.
1646
1647Valid values are 0-9 and C<LZMA_PRESET_DEFAULT>.
1648
16490 is the fastest compression with the lowest memory usage and the lowest
1650compression.
1651
16529 is the slowest compression with the highest memory usage but with the best
1653compression.
1654
1655This option is only valid if the C<Method> is ZIP_CM_LZMA. It is ignored
1656otherwise.
1657
1658Defaults to C<LZMA_PRESET_DEFAULT> (6).
1659
1660=item C<< Extreme => 0|1 >>
1661
1662Makes LZMA compression a lot slower, but a small compression gain.
1663
1664This option is only valid if the C<Method> is ZIP_CM_LZMA. It is ignored
1665otherwise.
1666
1667Defaults to 0.
1668
1669=back
1670
1671=head3 Other Options
1672
1673=over 5
1674
1675=item C<< Time => $number >>
1676
1677Sets the last modified time field in the zip header to $number.
1678
1679This field defaults to the time the C<IO::Compress::Zip> object was created
1680if this option is not specified and the C<$input> parameter is not a
1681filename.
1682
1683=item C<< ExtAttr => $attr >>
1684
1685This option controls the "external file attributes" field in the central
1686header of the zip file. This is a 4 byte field.
1687
1688If you are running a Unix derivative this value defaults to
1689
1690    0100644 << 16
1691
1692This should allow read/write access to any files that are extracted from
1693the zip file/buffer`.
1694
1695For all other systems it defaults to 0.
1696
1697=item C<< exTime => [$atime, $mtime, $ctime] >>
1698
1699This option expects an array reference with exactly three elements:
1700C<$atime>, C<mtime> and C<$ctime>. These correspond to the last access
1701time, last modification time and creation time respectively.
1702
1703It uses these values to set the extended timestamp field (ID is "UT") in
1704the local zip header using the three values, $atime, $mtime, $ctime. In
1705addition it sets the extended timestamp field in the central zip header
1706using C<$mtime>.
1707
1708If any of the three values is C<undef> that time value will not be used.
1709So, for example, to set only the C<$mtime> you would use this
1710
1711    exTime => [undef, $mtime, undef]
1712
1713If the C<Minimal> option is set to true, this option will be ignored.
1714
1715By default no extended time field is created.
1716
1717=item C<< exUnix2 => [$uid, $gid] >>
1718
1719This option expects an array reference with exactly two elements: C<$uid>
1720and C<$gid>. These values correspond to the numeric User ID (UID) and Group ID
1721(GID) of the owner of the files respectively.
1722
1723When the C<exUnix2> option is present it will trigger the creation of a
1724Unix2 extra field (ID is "Ux") in the local zip header. This will be populated
1725with C<$uid> and C<$gid>. An empty Unix2 extra field will also
1726be created in the central zip header.
1727
1728Note - The UID & GID are stored as 16-bit
1729integers in the "Ux" field. Use C<< exUnixN >> if your UID or GID are
173032-bit.
1731
1732If the C<Minimal> option is set to true, this option will be ignored.
1733
1734By default no Unix2 extra field is created.
1735
1736=item C<< exUnixN => [$uid, $gid] >>
1737
1738This option expects an array reference with exactly two elements: C<$uid>
1739and C<$gid>. These values correspond to the numeric User ID (UID) and Group ID
1740(GID) of the owner of the files respectively.
1741
1742When the C<exUnixN> option is present it will trigger the creation of a
1743UnixN extra field (ID is "ux") in both the local and central zip headers.
1744This will be populated with C<$uid> and C<$gid>.
1745The UID & GID are stored as 32-bit integers.
1746
1747If the C<Minimal> option is set to true, this option will be ignored.
1748
1749By default no UnixN extra field is created.
1750
1751=item C<< Comment => $comment >>
1752
1753Stores the contents of C<$comment> in the Central File Header of
1754the zip file.
1755
1756Set the C<Efs> option to true if you want to store a UTF8 comment.
1757
1758By default, no comment field is written to the zip file.
1759
1760=item C<< ZipComment => $comment >>
1761
1762Stores the contents of C<$comment> in the End of Central Directory record
1763of the zip file.
1764
1765By default, no comment field is written to the zip file.
1766
1767=item C<< Method => $method >>
1768
1769Controls which compression method is used. At present the compression
1770methods supported are: Store (no compression at all), Deflate,
1771Bzip2, Zstd, Xz and Lzma.
1772
1773The symbols ZIP_CM_STORE, ZIP_CM_DEFLATE, ZIP_CM_BZIP2, ZIP_CM_ZSTD, ZIP_CM_XZ and ZIP_CM_LZMA
1774are used to select the compression method.
1775
1776These constants are not imported by C<IO::Compress::Zip> by default.
1777
1778    use IO::Compress::Zip qw(:zip_method);
1779    use IO::Compress::Zip qw(:constants);
1780    use IO::Compress::Zip qw(:all);
1781
1782Note that to create Bzip2 content, the module C<IO::Compress::Bzip2> must
1783be installed. A fatal error will be thrown if you attempt to create Bzip2
1784content when C<IO::Compress::Bzip2> is not available.
1785
1786Note that to create Lzma content, the module C<IO::Compress::Lzma> must
1787be installed. A fatal error will be thrown if you attempt to create Lzma
1788content when C<IO::Compress::Lzma> is not available.
1789
1790Note that to create Xz content, the module C<IO::Compress::Xz> must
1791be installed. A fatal error will be thrown if you attempt to create Xz
1792content when C<IO::Compress::Xz> is not available.
1793
1794Note that to create Zstd content, the module C<IO::Compress::Zstd> must
1795be installed. A fatal error will be thrown if you attempt to create Zstd
1796content when C<IO::Compress::Zstd> is not available.
1797
1798The default method is ZIP_CM_DEFLATE.
1799
1800=item C<< TextFlag => 0|1 >>
1801
1802This parameter controls the setting of a bit in the zip central header. It
1803is used to signal that the data stored in the zip file/buffer is probably
1804text.
1805
1806In one-shot mode this flag will be set to true if the Perl C<-T> operator thinks
1807the file contains text.
1808
1809The default is 0.
1810
1811=item C<< ExtraFieldLocal => $data >>
1812
1813=item C<< ExtraFieldCentral => $data >>
1814
1815The C<ExtraFieldLocal> option is used to store additional metadata in the
1816local header for the zip file/buffer. The C<ExtraFieldCentral> does the
1817same for the matching central header.
1818
1819An extra field consists of zero or more subfields. Each subfield consists
1820of a two byte header followed by the subfield data.
1821
1822The list of subfields can be supplied in any of the following formats
1823
1824    ExtraFieldLocal => [$id1, $data1,
1825                        $id2, $data2,
1826                         ...
1827                       ]
1828
1829    ExtraFieldLocal => [ [$id1 => $data1],
1830                         [$id2 => $data2],
1831                         ...
1832                       ]
1833
1834    ExtraFieldLocal => { $id1 => $data1,
1835                         $id2 => $data2,
1836                         ...
1837                       }
1838
1839Where C<$id1>, C<$id2> are two byte subfield ID's.
1840
1841If you use the hash syntax, you have no control over the order in which
1842the ExtraSubFields are stored, plus you cannot have SubFields with
1843duplicate ID.
1844
1845Alternatively the list of subfields can by supplied as a scalar, thus
1846
1847    ExtraField => $rawdata
1848
1849In this case C<IO::Compress::Zip> will check that C<$rawdata> consists of
1850zero or more conformant sub-fields.
1851
1852The Extended Time field (ID "UT"), set using the C<exTime> option, and the
1853Unix2 extra field (ID "Ux), set using the C<exUnix2> option, are examples
1854of extra fields.
1855
1856If the C<Minimal> option is set to true, this option will be ignored.
1857
1858The maximum size of an extra field 65535 bytes.
1859
1860=item C<< Strict => 0|1 >>
1861
1862This is a placeholder option.
1863
1864=back
1865
1866=head2 Examples
1867
1868=head3 Streaming
1869
1870This very simple command line example demonstrates the streaming capabilities
1871of the module. The code reads data from STDIN or all the files given on the
1872commandline, compresses it, and writes the compressed data to STDOUT.
1873
1874    use strict ;
1875    use warnings ;
1876    use IO::Compress::Zip qw(zip $ZipError) ;
1877
1878    my $z = IO::Compress::Zip->new("-", Stream => 1)
1879        or die "IO::Compress::Zip failed: $ZipError\n";
1880
1881    while (<>) {
1882        $z->print("abcde");
1883    }
1884    $z->close();
1885
1886Note the use of C<"-"> to means C<STDOUT>. Alternatively you can use C<\*STDOUT>.
1887
1888One problem with creating a zip archive directly from STDIN can be demonstrated by looking at
1889the contents of the zip file, output.zip, that we have just created
1890(assumg you have redirected it to a file called C<output.zip>).
1891
1892    $ unzip -l output.zip
1893    Archive:  output.zip
1894    Length      Date    Time    Name
1895    ---------  ---------- -----   ----
1896        12  2019-08-16 22:21
1897    ---------                     -------
1898        12                     1 file
1899
1900The archive member (filename) used is the empty string.
1901
1902If that doesn't suit your needs, you can explicitly set the filename used
1903in the zip archive by specifying the L<Name|"File Naming Options"> option, like so
1904
1905    my $z = IO::Compress::Zip->new("-", Name => "hello.txt", Stream => 1)
1906
1907Now the contents of the zip file looks like this
1908
1909    $ unzip -l output.zip
1910    Archive:  output.zip
1911    Length      Date    Time    Name
1912    ---------  ---------- -----   ----
1913        12  2019-08-16 22:22   hello.txt
1914    ---------                     -------
1915        12                     1 file
1916
1917=head3 Compressing a file from the filesystem
1918
1919To read the contents of the file C<file1.txt> and write the compressed
1920data to the file C<file1.txt.zip> there are a few options
1921
1922Start by creating the compression object and opening the input file
1923
1924    use strict ;
1925    use warnings ;
1926    use IO::Compress::Zip qw(zip $ZipError) ;
1927
1928    my $input = "file1.txt";
1929    my $z = IO::Compress::Zip->new("file1.txt.zip")
1930        or die "IO::Compress::Zip failed: $ZipError\n";
1931
1932    # open the input file
1933    open my $fh, "<", "file1.txt"
1934        or die "Cannot open file1.txt: $!\n";
1935
1936    # loop through the input file & write to the compressed file
1937    while (<$fh>) {
1938        $z->print($_);
1939    }
1940
1941    # not forgetting to close the compressed file
1942    $z->close();
1943
1944=head3 Compressing multiple files
1945
1946To create a zip file, C<output.zip>, that contains the compressed contents
1947of the files C<alpha.txt> and C<beta.txt>
1948
1949    use strict ;
1950    use warnings ;
1951    use IO::Compress::Zip qw(zip $ZipError) ;
1952
1953    my $z = IO::Compress::Zip->new("output.zip", Name => "alpha.txt")
1954        or die "IO::Compress::Zip failed: $ZipError\n";
1955
1956    # open the input file
1957    open my $fh, "<", "file1.txt"
1958        or die "Cannot open file1.txt: $!\n";
1959
1960    # loop through the input file & write to the compressed file
1961    while (<$fh>) {
1962        $z->print($_);
1963    }
1964
1965    # move to next file
1966    $z->newStream(Name => "beta.txt")
1967
1968    while (<$fh>) {
1969        $z->print($_);
1970    }
1971
1972    $z->close();
1973
1974=head1 Methods
1975
1976=head2 print
1977
1978Usage is
1979
1980    $z->print($data)
1981    print $z $data
1982
1983Compresses and outputs the contents of the C<$data> parameter. This
1984has the same behaviour as the C<print> built-in.
1985
1986Returns true if successful.
1987
1988=head2 printf
1989
1990Usage is
1991
1992    $z->printf($format, $data)
1993    printf $z $format, $data
1994
1995Compresses and outputs the contents of the C<$data> parameter.
1996
1997Returns true if successful.
1998
1999=head2 syswrite
2000
2001Usage is
2002
2003    $z->syswrite $data
2004    $z->syswrite $data, $length
2005    $z->syswrite $data, $length, $offset
2006
2007Compresses and outputs the contents of the C<$data> parameter.
2008
2009Returns the number of uncompressed bytes written, or C<undef> if
2010unsuccessful.
2011
2012=head2 write
2013
2014Usage is
2015
2016    $z->write $data
2017    $z->write $data, $length
2018    $z->write $data, $length, $offset
2019
2020Compresses and outputs the contents of the C<$data> parameter.
2021
2022Returns the number of uncompressed bytes written, or C<undef> if
2023unsuccessful.
2024
2025=head2 flush
2026
2027Usage is
2028
2029    $z->flush;
2030    $z->flush($flush_type);
2031
2032Flushes any pending compressed data to the output file/buffer.
2033
2034This method takes an optional parameter, C<$flush_type>, that controls
2035how the flushing will be carried out. By default the C<$flush_type>
2036used is C<Z_FINISH>. Other valid values for C<$flush_type> are
2037C<Z_NO_FLUSH>, C<Z_SYNC_FLUSH>, C<Z_FULL_FLUSH> and C<Z_BLOCK>. It is
2038strongly recommended that you only set the C<flush_type> parameter if
2039you fully understand the implications of what it does - overuse of C<flush>
2040can seriously degrade the level of compression achieved. See the C<zlib>
2041documentation for details.
2042
2043Returns true on success.
2044
2045=head2 tell
2046
2047Usage is
2048
2049    $z->tell()
2050    tell $z
2051
2052Returns the uncompressed file offset.
2053
2054=head2 eof
2055
2056Usage is
2057
2058    $z->eof();
2059    eof($z);
2060
2061Returns true if the C<close> method has been called.
2062
2063=head2 seek
2064
2065    $z->seek($position, $whence);
2066    seek($z, $position, $whence);
2067
2068Provides a sub-set of the C<seek> functionality, with the restriction
2069that it is only legal to seek forward in the output file/buffer.
2070It is a fatal error to attempt to seek backward.
2071
2072Empty parts of the file/buffer will have NULL (0x00) bytes written to them.
2073
2074The C<$whence> parameter takes one the usual values, namely SEEK_SET,
2075SEEK_CUR or SEEK_END.
2076
2077Returns 1 on success, 0 on failure.
2078
2079=head2 binmode
2080
2081Usage is
2082
2083    $z->binmode
2084    binmode $z ;
2085
2086This is a noop provided for completeness.
2087
2088=head2 opened
2089
2090    $z->opened()
2091
2092Returns true if the object currently refers to a opened file/buffer.
2093
2094=head2 autoflush
2095
2096    my $prev = $z->autoflush()
2097    my $prev = $z->autoflush(EXPR)
2098
2099If the C<$z> object is associated with a file or a filehandle, this method
2100returns the current autoflush setting for the underlying filehandle. If
2101C<EXPR> is present, and is non-zero, it will enable flushing after every
2102write/print operation.
2103
2104If C<$z> is associated with a buffer, this method has no effect and always
2105returns C<undef>.
2106
2107B<Note> that the special variable C<$|> B<cannot> be used to set or
2108retrieve the autoflush setting.
2109
2110=head2 input_line_number
2111
2112    $z->input_line_number()
2113    $z->input_line_number(EXPR)
2114
2115This method always returns C<undef> when compressing.
2116
2117=head2 fileno
2118
2119    $z->fileno()
2120    fileno($z)
2121
2122If the C<$z> object is associated with a file or a filehandle, C<fileno>
2123will return the underlying file descriptor. Once the C<close> method is
2124called C<fileno> will return C<undef>.
2125
2126If the C<$z> object is associated with a buffer, this method will return
2127C<undef>.
2128
2129=head2 close
2130
2131    $z->close() ;
2132    close $z ;
2133
2134Flushes any pending compressed data and then closes the output file/buffer.
2135
2136For most versions of Perl this method will be automatically invoked if
2137the IO::Compress::Zip object is destroyed (either explicitly or by the
2138variable with the reference to the object going out of scope). The
2139exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
2140these cases, the C<close> method will be called automatically, but
2141not until global destruction of all live objects when the program is
2142terminating.
2143
2144Therefore, if you want your scripts to be able to run on all versions
2145of Perl, you should call C<close> explicitly and not rely on automatic
2146closing.
2147
2148Returns true on success, otherwise 0.
2149
2150If the C<AutoClose> option has been enabled when the IO::Compress::Zip
2151object was created, and the object is associated with a file, the
2152underlying file will also be closed.
2153
2154=head2 newStream([OPTS])
2155
2156Usage is
2157
2158    $z->newStream( [OPTS] )
2159
2160Closes the current compressed data stream and starts a new one.
2161
2162OPTS consists of any of the options that are available when creating
2163the C<$z> object.
2164
2165See the L</"Constructor Options"> section for more details.
2166
2167=head2 deflateParams
2168
2169Usage is
2170
2171    $z->deflateParams
2172
2173TODO
2174
2175=head1 Importing
2176
2177A number of symbolic constants are required by some methods in
2178C<IO::Compress::Zip>. None are imported by default.
2179
2180=over 5
2181
2182=item :all
2183
2184Imports C<zip>, C<$ZipError> and all symbolic
2185constants that can be used by C<IO::Compress::Zip>. Same as doing this
2186
2187    use IO::Compress::Zip qw(zip $ZipError :constants) ;
2188
2189=item :constants
2190
2191Import all symbolic constants. Same as doing this
2192
2193    use IO::Compress::Zip qw(:flush :level :strategy :zip_method) ;
2194
2195=item :flush
2196
2197These symbolic constants are used by the C<flush> method.
2198
2199    Z_NO_FLUSH
2200    Z_PARTIAL_FLUSH
2201    Z_SYNC_FLUSH
2202    Z_FULL_FLUSH
2203    Z_FINISH
2204    Z_BLOCK
2205
2206=item :level
2207
2208These symbolic constants are used by the C<Level> option in the constructor.
2209
2210    Z_NO_COMPRESSION
2211    Z_BEST_SPEED
2212    Z_BEST_COMPRESSION
2213    Z_DEFAULT_COMPRESSION
2214
2215=item :strategy
2216
2217These symbolic constants are used by the C<Strategy> option in the constructor.
2218
2219    Z_FILTERED
2220    Z_HUFFMAN_ONLY
2221    Z_RLE
2222    Z_FIXED
2223    Z_DEFAULT_STRATEGY
2224
2225=item :zip_method
2226
2227These symbolic constants are used by the C<Method> option in the
2228constructor.
2229
2230    ZIP_CM_STORE
2231    ZIP_CM_DEFLATE
2232    ZIP_CM_BZIP2
2233
2234=back
2235
2236=head1 EXAMPLES
2237
2238=head2 Apache::GZip Revisited
2239
2240See L<IO::Compress::FAQ|IO::Compress::FAQ/"Apache::GZip Revisited">
2241
2242=head2 Working with Net::FTP
2243
2244See L<IO::Compress::FAQ|IO::Compress::FAQ/"Compressed files and Net::FTP">
2245
2246=head1 SUPPORT
2247
2248General feedback/questions/bug reports should be sent to
2249L<https://github.com/pmqs/IO-Compress/issues> (preferred) or
2250L<https://rt.cpan.org/Public/Dist/Display.html?Name=IO-Compress>.
2251
2252=head1 SEE ALSO
2253
2254L<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>
2255
2256L<IO::Compress::FAQ|IO::Compress::FAQ>
2257
2258L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
2259L<Archive::Tar|Archive::Tar>,
2260L<IO::Zlib|IO::Zlib>
2261
2262For RFC 1950, 1951 and 1952 see
2263L<https://datatracker.ietf.org/doc/html/rfc1950>,
2264L<https://datatracker.ietf.org/doc/html/rfc1951> and
2265L<https://datatracker.ietf.org/doc/html/rfc1952>
2266
2267The I<zlib> compression library was written by Jean-loup Gailly
2268C<gzip@prep.ai.mit.edu> and Mark Adler C<madler@alumni.caltech.edu>.
2269
2270The primary site for the I<zlib> compression library is
2271L<http://www.zlib.org>.
2272
2273The primary site for the I<zlib-ng> compression library is
2274L<https://github.com/zlib-ng/zlib-ng>.
2275
2276The primary site for gzip is L<http://www.gzip.org>.
2277
2278=head1 AUTHOR
2279
2280This module was written by Paul Marquess, C<pmqs@cpan.org>.
2281
2282=head1 MODIFICATION HISTORY
2283
2284See the Changes file.
2285
2286=head1 COPYRIGHT AND LICENSE
2287
2288Copyright (c) 2005-2024 Paul Marquess. All rights reserved.
2289
2290This program is free software; you can redistribute it and/or
2291modify it under the same terms as Perl itself.
2292