1package IO::Uncompress::Unzip;
2
3require 5.006 ;
4
5# for RFC1952
6
7use strict ;
8use warnings;
9use bytes;
10
11use IO::File;
12use IO::Uncompress::RawInflate  2.084 ;
13use IO::Compress::Base::Common  2.084 qw(:Status );
14use IO::Uncompress::Adapter::Inflate  2.084 ;
15use IO::Uncompress::Adapter::Identity 2.084 ;
16use IO::Compress::Zlib::Extra 2.084 ;
17use IO::Compress::Zip::Constants 2.084 ;
18
19use Compress::Raw::Zlib  2.084 () ;
20
21BEGIN
22{
23    eval{ require IO::Uncompress::Adapter::Bunzip2 ;
24          import  IO::Uncompress::Adapter::Bunzip2 } ;
25    eval{ require IO::Uncompress::Adapter::UnLzma ;
26          import  IO::Uncompress::Adapter::UnLzma } ;
27}
28
29
30require Exporter ;
31
32our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $UnzipError, %headerLookup);
33
34$VERSION = '2.084';
35$UnzipError = '';
36
37@ISA    = qw(IO::Uncompress::RawInflate Exporter);
38@EXPORT_OK = qw( $UnzipError unzip );
39%EXPORT_TAGS = %IO::Uncompress::RawInflate::EXPORT_TAGS ;
40push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
41Exporter::export_ok_tags('all');
42
43%headerLookup = (
44        ZIP_CENTRAL_HDR_SIG,            \&skipCentralDirectory,
45        ZIP_END_CENTRAL_HDR_SIG,        \&skipEndCentralDirectory,
46        ZIP64_END_CENTRAL_REC_HDR_SIG,  \&skipCentralDirectory64Rec,
47        ZIP64_END_CENTRAL_LOC_HDR_SIG,  \&skipCentralDirectory64Loc,
48        ZIP64_ARCHIVE_EXTRA_SIG,        \&skipArchiveExtra,
49        ZIP64_DIGITAL_SIGNATURE_SIG,    \&skipDigitalSignature,
50        );
51
52sub new
53{
54    my $class = shift ;
55    my $obj = IO::Compress::Base::Common::createSelfTiedObject($class, \$UnzipError);
56    $obj->_create(undef, 0, @_);
57}
58
59sub unzip
60{
61    my $obj = IO::Compress::Base::Common::createSelfTiedObject(undef, \$UnzipError);
62    return $obj->_inf(@_) ;
63}
64
65sub getExtraParams
66{
67
68    return (
69#            # Zip header fields
70            'name'    => [IO::Compress::Base::Common::Parse_any,       undef],
71
72            'stream'  => [IO::Compress::Base::Common::Parse_boolean,   0],
73
74            # TODO - This means reading the central directory to get
75            # 1. the local header offsets
76            # 2. The compressed data length
77        );
78}
79
80sub ckParams
81{
82    my $self = shift ;
83    my $got = shift ;
84
85    # unzip always needs crc32
86    $got->setValue('crc32' => 1);
87
88    *$self->{UnzipData}{Name} = $got->getValue('name');
89
90    return 1;
91}
92
93sub mkUncomp
94{
95    my $self = shift ;
96    my $got = shift ;
97
98     my $magic = $self->ckMagic()
99        or return 0;
100
101    *$self->{Info} = $self->readHeader($magic)
102        or return undef ;
103
104    return 1;
105
106}
107
108sub ckMagic
109{
110    my $self = shift;
111
112    my $magic ;
113    $self->smartReadExact(\$magic, 4);
114
115    *$self->{HeaderPending} = $magic ;
116
117    return $self->HeaderError("Minimum header size is " .
118                              4 . " bytes")
119        if length $magic != 4 ;
120
121    return $self->HeaderError("Bad Magic")
122        if ! _isZipMagic($magic) ;
123
124    *$self->{Type} = 'zip';
125
126    return $magic ;
127}
128
129
130sub fastForward
131{
132    my $self = shift;
133    my $offset = shift;
134
135    # TODO - if Stream isn't enabled & reading from file, use seek
136
137    my $buffer = '';
138    my $c = 1024 * 16;
139
140    while ($offset > 0)
141    {
142        $c = length $offset
143            if length $offset < $c ;
144
145        $offset -= $c;
146
147        $self->smartReadExact(\$buffer, $c)
148            or return 0;
149    }
150
151    return 1;
152}
153
154
155sub readHeader
156{
157    my $self = shift;
158    my $magic = shift ;
159
160    my $name =  *$self->{UnzipData}{Name} ;
161    my $hdr = $self->_readZipHeader($magic) ;
162
163    while (defined $hdr)
164    {
165        if (! defined $name || $hdr->{Name} eq $name)
166        {
167            return $hdr ;
168        }
169
170        # skip the data
171        # TODO - when Stream is off, use seek
172        my $buffer;
173        if (*$self->{ZipData}{Streaming}) {
174            while (1) {
175
176                my $b;
177                my $status = $self->smartRead(\$b, 1024 * 16);
178
179                return $self->saveErrorString(undef, "Truncated file")
180                    if $status <= 0 ;
181
182                my $temp_buf ;
183                my $out;
184
185                $status = *$self->{Uncomp}->uncompr(\$b, \$temp_buf, 0, $out);
186
187                return $self->saveErrorString(undef, *$self->{Uncomp}{Error},
188                                                     *$self->{Uncomp}{ErrorNo})
189                    if $self->saveStatus($status) == STATUS_ERROR;
190
191                $self->pushBack($b)  ;
192
193                if ($status == STATUS_ENDSTREAM) {
194                    *$self->{Uncomp}->reset();
195                    last;
196                }
197            }
198
199            # skip the trailer
200            $self->smartReadExact(\$buffer, $hdr->{TrailerLength})
201                or return $self->saveErrorString(undef, "Truncated file");
202        }
203        else {
204            my $c = $hdr->{CompressedLength}->get64bit();
205            $self->fastForward($c)
206                or return $self->saveErrorString(undef, "Truncated file");
207            $buffer = '';
208        }
209
210        $self->chkTrailer($buffer) == STATUS_OK
211            or return $self->saveErrorString(undef, "Truncated file");
212
213        $hdr = $self->_readFullZipHeader();
214
215        return $self->saveErrorString(undef, "Cannot find '$name'")
216            if $self->smartEof();
217    }
218
219    return undef;
220}
221
222sub chkTrailer
223{
224    my $self = shift;
225    my $trailer = shift;
226
227    my ($sig, $CRC32, $cSize, $uSize) ;
228    my ($cSizeHi, $uSizeHi) = (0, 0);
229    if (*$self->{ZipData}{Streaming}) {
230        $sig   = unpack ("V", substr($trailer, 0, 4));
231        $CRC32 = unpack ("V", substr($trailer, 4, 4));
232
233        if (*$self->{ZipData}{Zip64} ) {
234            $cSize = U64::newUnpack_V64 substr($trailer,  8, 8);
235            $uSize = U64::newUnpack_V64 substr($trailer, 16, 8);
236        }
237        else {
238            $cSize = U64::newUnpack_V32 substr($trailer,  8, 4);
239            $uSize = U64::newUnpack_V32 substr($trailer, 12, 4);
240        }
241
242        return $self->TrailerError("Data Descriptor signature, got $sig")
243            if $sig != ZIP_DATA_HDR_SIG;
244    }
245    else {
246        ($CRC32, $cSize, $uSize) =
247            (*$self->{ZipData}{Crc32},
248             *$self->{ZipData}{CompressedLen},
249             *$self->{ZipData}{UnCompressedLen});
250    }
251
252    *$self->{Info}{CRC32} = *$self->{ZipData}{CRC32} ;
253    *$self->{Info}{CompressedLength} = $cSize->get64bit();
254    *$self->{Info}{UncompressedLength} = $uSize->get64bit();
255
256    if (*$self->{Strict}) {
257        return $self->TrailerError("CRC mismatch")
258            if $CRC32  != *$self->{ZipData}{CRC32} ;
259
260        return $self->TrailerError("CSIZE mismatch.")
261            if ! $cSize->equal(*$self->{CompSize});
262
263        return $self->TrailerError("USIZE mismatch.")
264            if ! $uSize->equal(*$self->{UnCompSize});
265    }
266
267    my $reachedEnd = STATUS_ERROR ;
268    # check for central directory or end of central directory
269    while (1)
270    {
271        my $magic ;
272        my $got = $self->smartRead(\$magic, 4);
273
274        return $self->saveErrorString(STATUS_ERROR, "Truncated file")
275            if $got != 4 && *$self->{Strict};
276
277        if ($got == 0) {
278            return STATUS_EOF ;
279        }
280        elsif ($got < 0) {
281            return STATUS_ERROR ;
282        }
283        elsif ($got < 4) {
284            $self->pushBack($magic)  ;
285            return STATUS_OK ;
286        }
287
288        my $sig = unpack("V", $magic) ;
289
290        my $hdr;
291        if ($hdr = $headerLookup{$sig})
292        {
293            if (&$hdr($self, $magic) != STATUS_OK ) {
294                if (*$self->{Strict}) {
295                    return STATUS_ERROR ;
296                }
297                else {
298                    $self->clearError();
299                    return STATUS_OK ;
300                }
301            }
302
303            if ($sig == ZIP_END_CENTRAL_HDR_SIG)
304            {
305                return STATUS_OK ;
306                last;
307            }
308        }
309        elsif ($sig == ZIP_LOCAL_HDR_SIG)
310        {
311            $self->pushBack($magic)  ;
312            return STATUS_OK ;
313        }
314        else
315        {
316            # put the data back
317            $self->pushBack($magic)  ;
318            last;
319        }
320    }
321
322    return $reachedEnd ;
323}
324
325sub skipCentralDirectory
326{
327    my $self = shift;
328    my $magic = shift ;
329
330    my $buffer;
331    $self->smartReadExact(\$buffer, 46 - 4)
332        or return $self->TrailerError("Minimum header size is " .
333                                     46 . " bytes") ;
334
335    my $keep = $magic . $buffer ;
336    *$self->{HeaderPending} = $keep ;
337
338   #my $versionMadeBy      = unpack ("v", substr($buffer, 4-4,  2));
339   #my $extractVersion     = unpack ("v", substr($buffer, 6-4,  2));
340   #my $gpFlag             = unpack ("v", substr($buffer, 8-4,  2));
341   #my $compressedMethod   = unpack ("v", substr($buffer, 10-4, 2));
342   #my $lastModTime        = unpack ("V", substr($buffer, 12-4, 4));
343   #my $crc32              = unpack ("V", substr($buffer, 16-4, 4));
344    my $compressedLength   = unpack ("V", substr($buffer, 20-4, 4));
345    my $uncompressedLength = unpack ("V", substr($buffer, 24-4, 4));
346    my $filename_length    = unpack ("v", substr($buffer, 28-4, 2));
347    my $extra_length       = unpack ("v", substr($buffer, 30-4, 2));
348    my $comment_length     = unpack ("v", substr($buffer, 32-4, 2));
349   #my $disk_start         = unpack ("v", substr($buffer, 34-4, 2));
350   #my $int_file_attrib    = unpack ("v", substr($buffer, 36-4, 2));
351   #my $ext_file_attrib    = unpack ("V", substr($buffer, 38-4, 2));
352   #my $lcl_hdr_offset     = unpack ("V", substr($buffer, 42-4, 2));
353
354
355    my $filename;
356    my $extraField;
357    my $comment ;
358    if ($filename_length)
359    {
360        $self->smartReadExact(\$filename, $filename_length)
361            or return $self->TruncatedTrailer("filename");
362        $keep .= $filename ;
363    }
364
365    if ($extra_length)
366    {
367        $self->smartReadExact(\$extraField, $extra_length)
368            or return $self->TruncatedTrailer("extra");
369        $keep .= $extraField ;
370    }
371
372    if ($comment_length)
373    {
374        $self->smartReadExact(\$comment, $comment_length)
375            or return $self->TruncatedTrailer("comment");
376        $keep .= $comment ;
377    }
378
379    return STATUS_OK ;
380}
381
382sub skipArchiveExtra
383{
384    my $self = shift;
385    my $magic = shift ;
386
387    my $buffer;
388    $self->smartReadExact(\$buffer, 4)
389        or return $self->TrailerError("Minimum header size is " .
390                                     4 . " bytes") ;
391
392    my $keep = $magic . $buffer ;
393
394    my $size = unpack ("V", $buffer);
395
396    $self->smartReadExact(\$buffer, $size)
397        or return $self->TrailerError("Minimum header size is " .
398                                     $size . " bytes") ;
399
400    $keep .= $buffer ;
401    *$self->{HeaderPending} = $keep ;
402
403    return STATUS_OK ;
404}
405
406
407sub skipCentralDirectory64Rec
408{
409    my $self = shift;
410    my $magic = shift ;
411
412    my $buffer;
413    $self->smartReadExact(\$buffer, 8)
414        or return $self->TrailerError("Minimum header size is " .
415                                     8 . " bytes") ;
416
417    my $keep = $magic . $buffer ;
418
419    my ($sizeLo, $sizeHi)  = unpack ("V V", $buffer);
420    my $size = $sizeHi * U64::MAX32 + $sizeLo;
421
422    $self->fastForward($size)
423        or return $self->TrailerError("Minimum header size is " .
424                                     $size . " bytes") ;
425
426   #$keep .= $buffer ;
427   #*$self->{HeaderPending} = $keep ;
428
429   #my $versionMadeBy      = unpack ("v",   substr($buffer,  0, 2));
430   #my $extractVersion     = unpack ("v",   substr($buffer,  2, 2));
431   #my $diskNumber         = unpack ("V",   substr($buffer,  4, 4));
432   #my $cntrlDirDiskNo     = unpack ("V",   substr($buffer,  8, 4));
433   #my $entriesInThisCD    = unpack ("V V", substr($buffer, 12, 8));
434   #my $entriesInCD        = unpack ("V V", substr($buffer, 20, 8));
435   #my $sizeOfCD           = unpack ("V V", substr($buffer, 28, 8));
436   #my $offsetToCD         = unpack ("V V", substr($buffer, 36, 8));
437
438    return STATUS_OK ;
439}
440
441sub skipCentralDirectory64Loc
442{
443    my $self = shift;
444    my $magic = shift ;
445
446    my $buffer;
447    $self->smartReadExact(\$buffer, 20 - 4)
448        or return $self->TrailerError("Minimum header size is " .
449                                     20 . " bytes") ;
450
451    my $keep = $magic . $buffer ;
452    *$self->{HeaderPending} = $keep ;
453
454   #my $startCdDisk        = unpack ("V",   substr($buffer,  4-4, 4));
455   #my $offsetToCD         = unpack ("V V", substr($buffer,  8-4, 8));
456   #my $diskCount          = unpack ("V",   substr($buffer, 16-4, 4));
457
458    return STATUS_OK ;
459}
460
461sub skipEndCentralDirectory
462{
463    my $self = shift;
464    my $magic = shift ;
465
466
467    my $buffer;
468    $self->smartReadExact(\$buffer, 22 - 4)
469        or return $self->TrailerError("Minimum header size is " .
470                                     22 . " bytes") ;
471
472    my $keep = $magic . $buffer ;
473    *$self->{HeaderPending} = $keep ;
474
475   #my $diskNumber         = unpack ("v", substr($buffer, 4-4,  2));
476   #my $cntrlDirDiskNo     = unpack ("v", substr($buffer, 6-4,  2));
477   #my $entriesInThisCD    = unpack ("v", substr($buffer, 8-4,  2));
478   #my $entriesInCD        = unpack ("v", substr($buffer, 10-4, 2));
479   #my $sizeOfCD           = unpack ("V", substr($buffer, 12-4, 4));
480   #my $offsetToCD         = unpack ("V", substr($buffer, 16-4, 4));
481    my $comment_length     = unpack ("v", substr($buffer, 20-4, 2));
482
483
484    my $comment ;
485    if ($comment_length)
486    {
487        $self->smartReadExact(\$comment, $comment_length)
488            or return $self->TruncatedTrailer("comment");
489        $keep .= $comment ;
490    }
491
492    return STATUS_OK ;
493}
494
495
496sub _isZipMagic
497{
498    my $buffer = shift ;
499    return 0 if length $buffer < 4 ;
500    my $sig = unpack("V", $buffer) ;
501    return $sig == ZIP_LOCAL_HDR_SIG ;
502}
503
504
505sub _readFullZipHeader($)
506{
507    my ($self) = @_ ;
508    my $magic = '' ;
509
510    $self->smartReadExact(\$magic, 4);
511
512    *$self->{HeaderPending} = $magic ;
513
514    return $self->HeaderError("Minimum header size is " .
515                              30 . " bytes")
516        if length $magic != 4 ;
517
518
519    return $self->HeaderError("Bad Magic")
520        if ! _isZipMagic($magic) ;
521
522    my $status = $self->_readZipHeader($magic);
523    delete *$self->{Transparent} if ! defined $status ;
524    return $status ;
525}
526
527sub _readZipHeader($)
528{
529    my ($self, $magic) = @_ ;
530    my ($HeaderCRC) ;
531    my ($buffer) = '' ;
532
533    $self->smartReadExact(\$buffer, 30 - 4)
534        or return $self->HeaderError("Minimum header size is " .
535                                     30 . " bytes") ;
536
537    my $keep = $magic . $buffer ;
538    *$self->{HeaderPending} = $keep ;
539
540    my $extractVersion     = unpack ("v", substr($buffer, 4-4,  2));
541    my $gpFlag             = unpack ("v", substr($buffer, 6-4,  2));
542    my $compressedMethod   = unpack ("v", substr($buffer, 8-4,  2));
543    my $lastModTime        = unpack ("V", substr($buffer, 10-4, 4));
544    my $crc32              = unpack ("V", substr($buffer, 14-4, 4));
545    my $compressedLength   = U64::newUnpack_V32 substr($buffer, 18-4, 4);
546    my $uncompressedLength = U64::newUnpack_V32 substr($buffer, 22-4, 4);
547    my $filename_length    = unpack ("v", substr($buffer, 26-4, 2));
548    my $extra_length       = unpack ("v", substr($buffer, 28-4, 2));
549
550    my $filename;
551    my $extraField;
552    my @EXTRA = ();
553    my $streamingMode = ($gpFlag & ZIP_GP_FLAG_STREAMING_MASK) ? 1 : 0 ;
554
555    return $self->HeaderError("Encrypted content not supported")
556        if $gpFlag & (ZIP_GP_FLAG_ENCRYPTED_MASK|ZIP_GP_FLAG_STRONG_ENCRYPTED_MASK);
557
558    return $self->HeaderError("Patch content not supported")
559        if $gpFlag & ZIP_GP_FLAG_PATCHED_MASK;
560
561    *$self->{ZipData}{Streaming} = $streamingMode;
562
563
564    if ($filename_length)
565    {
566        $self->smartReadExact(\$filename, $filename_length)
567            or return $self->TruncatedHeader("Filename");
568        $keep .= $filename ;
569    }
570
571    my $zip64 = 0 ;
572
573    if ($extra_length)
574    {
575        $self->smartReadExact(\$extraField, $extra_length)
576            or return $self->TruncatedHeader("Extra Field");
577
578        my $bad = IO::Compress::Zlib::Extra::parseRawExtra($extraField,
579                                                \@EXTRA, 1, 0);
580        return $self->HeaderError($bad)
581            if defined $bad;
582
583        $keep .= $extraField ;
584
585        my %Extra ;
586        for (@EXTRA)
587        {
588            $Extra{$_->[0]} = \$_->[1];
589        }
590
591        if (defined $Extra{ZIP_EXTRA_ID_ZIP64()})
592        {
593            $zip64 = 1 ;
594
595            my $buff = ${ $Extra{ZIP_EXTRA_ID_ZIP64()} };
596
597            # This code assumes that all the fields in the Zip64
598            # extra field aren't necessarily present. The spec says that
599            # they only exist if the equivalent local headers are -1.
600
601            if (! $streamingMode) {
602                my $offset = 0 ;
603
604                if (U64::full32 $uncompressedLength->get32bit() ) {
605                    $uncompressedLength
606                            = U64::newUnpack_V64 substr($buff, 0, 8);
607
608                    $offset += 8 ;
609                }
610
611                if (U64::full32 $compressedLength->get32bit() ) {
612
613                    $compressedLength
614                        = U64::newUnpack_V64 substr($buff, $offset, 8);
615
616                    $offset += 8 ;
617                }
618           }
619        }
620    }
621
622    *$self->{ZipData}{Zip64} = $zip64;
623
624    if (! $streamingMode) {
625        *$self->{ZipData}{Streaming} = 0;
626        *$self->{ZipData}{Crc32} = $crc32;
627        *$self->{ZipData}{CompressedLen} = $compressedLength;
628        *$self->{ZipData}{UnCompressedLen} = $uncompressedLength;
629        *$self->{CompressedInputLengthRemaining} =
630            *$self->{CompressedInputLength} = $compressedLength->get64bit();
631    }
632
633    *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32(undef);
634    *$self->{ZipData}{Method} = $compressedMethod;
635    if ($compressedMethod == ZIP_CM_DEFLATE)
636    {
637        *$self->{Type} = 'zip-deflate';
638        my $obj = IO::Uncompress::Adapter::Inflate::mkUncompObject(1,0,0);
639
640        *$self->{Uncomp} = $obj;
641    }
642    elsif ($compressedMethod == ZIP_CM_BZIP2)
643    {
644        return $self->HeaderError("Unsupported Compression format $compressedMethod")
645            if ! defined $IO::Uncompress::Adapter::Bunzip2::VERSION ;
646
647        *$self->{Type} = 'zip-bzip2';
648
649        my $obj = IO::Uncompress::Adapter::Bunzip2::mkUncompObject();
650
651        *$self->{Uncomp} = $obj;
652    }
653    elsif ($compressedMethod == ZIP_CM_LZMA)
654    {
655        return $self->HeaderError("Unsupported Compression format $compressedMethod")
656            if ! defined $IO::Uncompress::Adapter::UnLzma::VERSION ;
657
658        *$self->{Type} = 'zip-lzma';
659        my $LzmaHeader;
660        $self->smartReadExact(\$LzmaHeader, 4)
661                or return $self->saveErrorString(undef, "Truncated file");
662        my ($verHi, $verLo)   = unpack ("CC", substr($LzmaHeader, 0, 2));
663        my $LzmaPropertiesSize   = unpack ("v", substr($LzmaHeader, 2, 2));
664
665
666        my $LzmaPropertyData;
667        $self->smartReadExact(\$LzmaPropertyData, $LzmaPropertiesSize)
668                or return $self->saveErrorString(undef, "Truncated file");
669
670        if (! $streamingMode) {
671            *$self->{ZipData}{CompressedLen}->subtract(4 + $LzmaPropertiesSize) ;
672            *$self->{CompressedInputLengthRemaining} =
673                *$self->{CompressedInputLength} = *$self->{ZipData}{CompressedLen}->get64bit();
674        }
675
676        my $obj =
677            IO::Uncompress::Adapter::UnLzma::mkUncompZipObject($LzmaPropertyData);
678
679        *$self->{Uncomp} = $obj;
680    }
681    elsif ($compressedMethod == ZIP_CM_STORE)
682    {
683        *$self->{Type} = 'zip-stored';
684
685        my $obj =
686        IO::Uncompress::Adapter::Identity::mkUncompObject($streamingMode,
687                                                          $zip64);
688
689        *$self->{Uncomp} = $obj;
690    }
691    else
692    {
693        return $self->HeaderError("Unsupported Compression format $compressedMethod");
694    }
695
696    return {
697        'Type'               => 'zip',
698        'FingerprintLength'  => 4,
699        #'HeaderLength'       => $compressedMethod == 8 ? length $keep : 0,
700        'HeaderLength'       => length $keep,
701        'Zip64'              => $zip64,
702        'TrailerLength'      => ! $streamingMode ? 0 : $zip64 ? 24 : 16,
703        'Header'             => $keep,
704        'CompressedLength'   => $compressedLength ,
705        'UncompressedLength' => $uncompressedLength ,
706        'CRC32'              => $crc32 ,
707        'Name'               => $filename,
708        'Time'               => _dosToUnixTime($lastModTime),
709        'Stream'             => $streamingMode,
710
711        'MethodID'           => $compressedMethod,
712        'MethodName'         => $compressedMethod == ZIP_CM_DEFLATE
713                                 ? "Deflated"
714                                 : $compressedMethod == ZIP_CM_BZIP2
715                                     ? "Bzip2"
716                                     : $compressedMethod == ZIP_CM_LZMA
717                                         ? "Lzma"
718                                         : $compressedMethod == ZIP_CM_STORE
719                                             ? "Stored"
720                                             : "Unknown" ,
721
722#        'TextFlag'      => $flag & GZIP_FLG_FTEXT ? 1 : 0,
723#        'HeaderCRCFlag' => $flag & GZIP_FLG_FHCRC ? 1 : 0,
724#        'NameFlag'      => $flag & GZIP_FLG_FNAME ? 1 : 0,
725#        'CommentFlag'   => $flag & GZIP_FLG_FCOMMENT ? 1 : 0,
726#        'ExtraFlag'     => $flag & GZIP_FLG_FEXTRA ? 1 : 0,
727#        'Comment'       => $comment,
728#        'OsID'          => $os,
729#        'OsName'        => defined $GZIP_OS_Names{$os}
730#                                 ? $GZIP_OS_Names{$os} : "Unknown",
731#        'HeaderCRC'     => $HeaderCRC,
732#        'Flags'         => $flag,
733#        'ExtraFlags'    => $xfl,
734        'ExtraFieldRaw' => $extraField,
735        'ExtraField'    => [ @EXTRA ],
736
737
738      }
739}
740
741sub filterUncompressed
742{
743    my $self = shift ;
744
745    if (*$self->{ZipData}{Method} == ZIP_CM_DEFLATE) {
746        *$self->{ZipData}{CRC32} = *$self->{Uncomp}->crc32() ;
747    }
748    else {
749        *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32(${$_[0]}, *$self->{ZipData}{CRC32}, $_[1]);
750    }
751}
752
753
754# from Archive::Zip & info-zip
755sub _dosToUnixTime
756{
757	my $dt = shift;
758
759	my $year = ( ( $dt >> 25 ) & 0x7f ) + 80;
760	my $mon  = ( ( $dt >> 21 ) & 0x0f ) - 1;
761	my $mday = ( ( $dt >> 16 ) & 0x1f );
762
763	my $hour = ( ( $dt >> 11 ) & 0x1f );
764	my $min  = ( ( $dt >> 5 ) & 0x3f );
765	my $sec  = ( ( $dt << 1 ) & 0x3e );
766
767
768    use POSIX 'mktime';
769
770    my $time_t = mktime( $sec, $min, $hour, $mday, $mon, $year, 0, 0, -1 );
771    return 0 if ! defined $time_t;
772	return $time_t;
773}
774
775#sub scanCentralDirectory
776#{
777#    # Use cases
778#    # 1 32-bit CD
779#    # 2 64-bit CD
780#
781#    my $self = shift ;
782#
783#    my @CD = ();
784#    my $offset = $self->findCentralDirectoryOffset();
785#
786#    return 0
787#        if ! defined $offset;
788#
789#    $self->smarkSeek($offset, 0, SEEK_SET) ;
790#
791#    # Now walk the Central Directory Records
792#    my $buffer ;
793#    while ($self->smartReadExact(\$buffer, 46) &&
794#           unpack("V", $buffer) == ZIP_CENTRAL_HDR_SIG) {
795#
796#        my $compressedLength   = unpack ("V", substr($buffer, 20, 4));
797#        my $filename_length    = unpack ("v", substr($buffer, 28, 2));
798#        my $extra_length       = unpack ("v", substr($buffer, 30, 2));
799#        my $comment_length     = unpack ("v", substr($buffer, 32, 2));
800#
801#        $self->smarkSeek($filename_length + $extra_length + $comment_length, 0, SEEK_CUR)
802#            if $extra_length || $comment_length || $filename_length;
803#        push @CD, $compressedLength ;
804#    }
805#
806#}
807#
808#sub findCentralDirectoryOffset
809#{
810#    my $self = shift ;
811#
812#    # Most common use-case is where there is no comment, so
813#    # know exactly where the end of central directory record
814#    # should be.
815#
816#    $self->smarkSeek(-22, 0, SEEK_END) ;
817#
818#    my $buffer;
819#    $self->smartReadExact(\$buffer, 22) ;
820#
821#    my $zip64 = 0;
822#    my $centralDirOffset ;
823#    if ( unpack("V", $buffer) == ZIP_END_CENTRAL_HDR_SIG ) {
824#        $centralDirOffset = unpack ("V", substr($buffer, 16, 2));
825#    }
826#    else {
827#        die "xxxx";
828#    }
829#
830#    return $centralDirOffset ;
831#}
832#
833#sub is84BitCD
834#{
835#    # TODO
836#    my $self = shift ;
837#}
838
839
840sub skip
841{
842    my $self = shift;
843    my $size = shift;
844
845    use Fcntl qw(SEEK_CUR);
846    if (ref $size eq 'U64') {
847        $self->smartSeek($size->get64bit(), SEEK_CUR);
848    }
849    else {
850        $self->smartSeek($size, SEEK_CUR);
851    }
852
853}
854
855
856sub scanCentralDirectory
857{
858    my $self = shift;
859
860    my $here = $self->tell();
861
862    # Use cases
863    # 1 32-bit CD
864    # 2 64-bit CD
865
866    my @CD = ();
867    my $offset = $self->findCentralDirectoryOffset();
868
869    return ()
870        if ! defined $offset;
871
872    $self->smarkSeek($offset, 0, SEEK_SET) ;
873
874    # Now walk the Central Directory Records
875    my $buffer ;
876    while ($self->smartReadExact(\$buffer, 46) &&
877           unpack("V", $buffer) == ZIP_CENTRAL_HDR_SIG) {
878
879        my $compressedLength   = unpack("V", substr($buffer, 20, 4));
880        my $uncompressedLength = unpack("V", substr($buffer, 24, 4));
881        my $filename_length    = unpack("v", substr($buffer, 28, 2));
882        my $extra_length       = unpack("v", substr($buffer, 30, 2));
883        my $comment_length     = unpack("v", substr($buffer, 32, 2));
884
885        $self->skip($filename_length ) ;
886
887        my $v64 = new U64 $compressedLength ;
888
889        if (U64::full32 $compressedLength ) {
890            $self->smartReadExact(\$buffer, $extra_length) ;
891            die "xxx $offset $comment_length $filename_length $extra_length" . length($buffer)
892                if length($buffer) != $extra_length;
893            my $got = $self->get64Extra($buffer, U64::full32 $uncompressedLength);
894
895            # If not Zip64 extra field, assume size is 0xFFFFFFFF
896            $v64 = $got if defined $got;
897        }
898        else {
899            $self->skip($extra_length) ;
900        }
901
902        $self->skip($comment_length ) ;
903
904        push @CD, $v64 ;
905    }
906
907    $self->smartSeek($here, 0, SEEK_SET) ;
908
909    return @CD;
910}
911
912sub get64Extra
913{
914    my $self = shift ;
915
916    my $buffer = shift;
917    my $is_uncomp = shift ;
918
919    my $extra = IO::Compress::Zlib::Extra::findID(0x0001, $buffer);
920
921    if (! defined $extra)
922    {
923        return undef;
924    }
925    else
926    {
927        my $u64 = U64::newUnpack_V64(substr($extra,  $is_uncomp ? 8 : 0)) ;
928        return $u64;
929    }
930}
931
932sub offsetFromZip64
933{
934    my $self = shift ;
935    my $here = shift;
936
937    $self->smartSeek($here - 20, 0, SEEK_SET)
938        or die "xx $!" ;
939
940    my $buffer;
941    my $got = 0;
942    $self->smartReadExact(\$buffer, 20)
943        or die "xxx $here $got $!" ;
944
945    if ( unpack("V", $buffer) == ZIP64_END_CENTRAL_LOC_HDR_SIG ) {
946        my $cd64 = U64::Value_VV64 substr($buffer,  8, 8);
947
948        $self->smartSeek($cd64, 0, SEEK_SET) ;
949
950        $self->smartReadExact(\$buffer, 4)
951            or die "xxx" ;
952
953        if ( unpack("V", $buffer) == ZIP64_END_CENTRAL_REC_HDR_SIG ) {
954
955            $self->smartReadExact(\$buffer, 8)
956                or die "xxx" ;
957            my $size  = U64::Value_VV64($buffer);
958            $self->smartReadExact(\$buffer, $size)
959                or die "xxx" ;
960
961            my $cd64 =  U64::Value_VV64 substr($buffer,  36, 8);
962
963            return $cd64 ;
964        }
965
966        die "zzz";
967    }
968
969    die "zzz";
970}
971
972use constant Pack_ZIP_END_CENTRAL_HDR_SIG => pack("V", ZIP_END_CENTRAL_HDR_SIG);
973
974sub findCentralDirectoryOffset
975{
976    my $self = shift ;
977
978    # Most common use-case is where there is no comment, so
979    # know exactly where the end of central directory record
980    # should be.
981
982    $self->smartSeek(-22, 0, SEEK_END) ;
983    my $here = $self->tell();
984
985    my $buffer;
986    $self->smartReadExact(\$buffer, 22)
987        or die "xxx" ;
988
989    my $zip64 = 0;
990    my $centralDirOffset ;
991    if ( unpack("V", $buffer) == ZIP_END_CENTRAL_HDR_SIG ) {
992        $centralDirOffset = unpack("V", substr($buffer, 16,  4));
993    }
994    else {
995        $self->smartSeek(0, 0, SEEK_END) ;
996
997        my $fileLen = $self->tell();
998        my $want = 0 ;
999
1000        while(1) {
1001            $want += 1024;
1002            my $seekTo = $fileLen - $want;
1003            if ($seekTo < 0 ) {
1004                $seekTo = 0;
1005                $want = $fileLen ;
1006            }
1007            $self->smartSeek( $seekTo, 0, SEEK_SET)
1008                or die "xxx $!" ;
1009            my $got;
1010            $self->smartReadExact($buffer, $want)
1011                or die "xxx " ;
1012            my $pos = rindex( $buffer, Pack_ZIP_END_CENTRAL_HDR_SIG);
1013
1014            if ($pos >= 0) {
1015                #$here = $self->tell();
1016                $here = $seekTo + $pos ;
1017                $centralDirOffset = unpack("V", substr($buffer, $pos + 16,  4));
1018                last ;
1019            }
1020
1021            return undef
1022                if $want == $fileLen;
1023        }
1024    }
1025
1026    $centralDirOffset = $self->offsetFromZip64($here)
1027        if U64::full32 $centralDirOffset ;
1028
1029    return $centralDirOffset ;
1030}
1031
10321;
1033
1034__END__
1035
1036
1037=head1 NAME
1038
1039IO::Uncompress::Unzip - Read zip files/buffers
1040
1041=head1 SYNOPSIS
1042
1043    use IO::Uncompress::Unzip qw(unzip $UnzipError) ;
1044
1045    my $status = unzip $input => $output [,OPTS]
1046        or die "unzip failed: $UnzipError\n";
1047
1048    my $z = new IO::Uncompress::Unzip $input [OPTS]
1049        or die "unzip failed: $UnzipError\n";
1050
1051    $status = $z->read($buffer)
1052    $status = $z->read($buffer, $length)
1053    $status = $z->read($buffer, $length, $offset)
1054    $line = $z->getline()
1055    $char = $z->getc()
1056    $char = $z->ungetc()
1057    $char = $z->opened()
1058
1059    $status = $z->inflateSync()
1060
1061    $data = $z->trailingData()
1062    $status = $z->nextStream()
1063    $data = $z->getHeaderInfo()
1064    $z->tell()
1065    $z->seek($position, $whence)
1066    $z->binmode()
1067    $z->fileno()
1068    $z->eof()
1069    $z->close()
1070
1071    $UnzipError ;
1072
1073    # IO::File mode
1074
1075    <$z>
1076    read($z, $buffer);
1077    read($z, $buffer, $length);
1078    read($z, $buffer, $length, $offset);
1079    tell($z)
1080    seek($z, $position, $whence)
1081    binmode($z)
1082    fileno($z)
1083    eof($z)
1084    close($z)
1085
1086=head1 DESCRIPTION
1087
1088This module provides a Perl interface that allows the reading of
1089zlib files/buffers.
1090
1091For writing zip files/buffers, see the companion module IO::Compress::Zip.
1092
1093=head1 Functional Interface
1094
1095A top-level function, C<unzip>, is provided to carry out
1096"one-shot" uncompression between buffers and/or files. For finer
1097control over the uncompression process, see the L</"OO Interface">
1098section.
1099
1100    use IO::Uncompress::Unzip qw(unzip $UnzipError) ;
1101
1102    unzip $input_filename_or_reference => $output_filename_or_reference [,OPTS]
1103        or die "unzip failed: $UnzipError\n";
1104
1105The functional interface needs Perl5.005 or better.
1106
1107=head2 unzip $input_filename_or_reference => $output_filename_or_reference [, OPTS]
1108
1109C<unzip> expects at least two parameters,
1110C<$input_filename_or_reference> and C<$output_filename_or_reference>.
1111
1112=head3 The C<$input_filename_or_reference> parameter
1113
1114The parameter, C<$input_filename_or_reference>, is used to define the
1115source of the compressed data.
1116
1117It can take one of the following forms:
1118
1119=over 5
1120
1121=item A filename
1122
1123If the <$input_filename_or_reference> parameter is a simple scalar, it is
1124assumed to be a filename. This file will be opened for reading and the
1125input data will be read from it.
1126
1127=item A filehandle
1128
1129If the C<$input_filename_or_reference> parameter is a filehandle, the input
1130data will be read from it.  The string '-' can be used as an alias for
1131standard input.
1132
1133=item A scalar reference
1134
1135If C<$input_filename_or_reference> is a scalar reference, the input data
1136will be read from C<$$input_filename_or_reference>.
1137
1138=item An array reference
1139
1140If C<$input_filename_or_reference> is an array reference, each element in
1141the array must be a filename.
1142
1143The input data will be read from each file in turn.
1144
1145The complete array will be walked to ensure that it only
1146contains valid filenames before any data is uncompressed.
1147
1148=item An Input FileGlob string
1149
1150If C<$input_filename_or_reference> is a string that is delimited by the
1151characters "<" and ">" C<unzip> will assume that it is an
1152I<input fileglob string>. The input is the list of files that match the
1153fileglob.
1154
1155See L<File::GlobMapper|File::GlobMapper> for more details.
1156
1157=back
1158
1159If the C<$input_filename_or_reference> parameter is any other type,
1160C<undef> will be returned.
1161
1162=head3 The C<$output_filename_or_reference> parameter
1163
1164The parameter C<$output_filename_or_reference> is used to control the
1165destination of the uncompressed data. This parameter can take one of
1166these forms.
1167
1168=over 5
1169
1170=item A filename
1171
1172If the C<$output_filename_or_reference> parameter is a simple scalar, it is
1173assumed to be a filename.  This file will be opened for writing and the
1174uncompressed data will be written to it.
1175
1176=item A filehandle
1177
1178If the C<$output_filename_or_reference> parameter is a filehandle, the
1179uncompressed data will be written to it.  The string '-' can be used as
1180an alias for standard output.
1181
1182=item A scalar reference
1183
1184If C<$output_filename_or_reference> is a scalar reference, the
1185uncompressed data will be stored in C<$$output_filename_or_reference>.
1186
1187=item An Array Reference
1188
1189If C<$output_filename_or_reference> is an array reference,
1190the uncompressed data will be pushed onto the array.
1191
1192=item An Output FileGlob
1193
1194If C<$output_filename_or_reference> is a string that is delimited by the
1195characters "<" and ">" C<unzip> will assume that it is an
1196I<output fileglob string>. The output is the list of files that match the
1197fileglob.
1198
1199When C<$output_filename_or_reference> is an fileglob string,
1200C<$input_filename_or_reference> must also be a fileglob string. Anything
1201else is an error.
1202
1203See L<File::GlobMapper|File::GlobMapper> for more details.
1204
1205=back
1206
1207If the C<$output_filename_or_reference> parameter is any other type,
1208C<undef> will be returned.
1209
1210=head2 Notes
1211
1212When C<$input_filename_or_reference> maps to multiple compressed
1213files/buffers and C<$output_filename_or_reference> is
1214a single file/buffer, after uncompression C<$output_filename_or_reference> will contain a
1215concatenation of all the uncompressed data from each of the input
1216files/buffers.
1217
1218=head2 Optional Parameters
1219
1220Unless specified below, the optional parameters for C<unzip>,
1221C<OPTS>, are the same as those used with the OO interface defined in the
1222L</"Constructor Options"> section below.
1223
1224=over 5
1225
1226=item C<< AutoClose => 0|1 >>
1227
1228This option applies to any input or output data streams to
1229C<unzip> that are filehandles.
1230
1231If C<AutoClose> is specified, and the value is true, it will result in all
1232input and/or output filehandles being closed once C<unzip> has
1233completed.
1234
1235This parameter defaults to 0.
1236
1237=item C<< BinModeOut => 0|1 >>
1238
1239This option is now a no-op. All files will be written  in binmode.
1240
1241=item C<< Append => 0|1 >>
1242
1243The behaviour of this option is dependent on the type of output data
1244stream.
1245
1246=over 5
1247
1248=item * A Buffer
1249
1250If C<Append> is enabled, all uncompressed data will be append to the end of
1251the output buffer. Otherwise the output buffer will be cleared before any
1252uncompressed data is written to it.
1253
1254=item * A Filename
1255
1256If C<Append> is enabled, the file will be opened in append mode. Otherwise
1257the contents of the file, if any, will be truncated before any uncompressed
1258data is written to it.
1259
1260=item * A Filehandle
1261
1262If C<Append> is enabled, the filehandle will be positioned to the end of
1263the file via a call to C<seek> before any uncompressed data is
1264written to it.  Otherwise the file pointer will not be moved.
1265
1266=back
1267
1268When C<Append> is specified, and set to true, it will I<append> all uncompressed
1269data to the output data stream.
1270
1271So when the output is a filehandle it will carry out a seek to the eof
1272before writing any uncompressed data. If the output is a filename, it will be opened for
1273appending. If the output is a buffer, all uncompressed data will be
1274appended to the existing buffer.
1275
1276Conversely when C<Append> is not specified, or it is present and is set to
1277false, it will operate as follows.
1278
1279When the output is a filename, it will truncate the contents of the file
1280before writing any uncompressed data. If the output is a filehandle
1281its position will not be changed. If the output is a buffer, it will be
1282wiped before any uncompressed data is output.
1283
1284Defaults to 0.
1285
1286=item C<< MultiStream => 0|1 >>
1287
1288If the input file/buffer contains multiple compressed data streams, this
1289option will uncompress the whole lot as a single data stream.
1290
1291Defaults to 0.
1292
1293=item C<< TrailingData => $scalar >>
1294
1295Returns the data, if any, that is present immediately after the compressed
1296data stream once uncompression is complete.
1297
1298This option can be used when there is useful information immediately
1299following the compressed data stream, and you don't know the length of the
1300compressed data stream.
1301
1302If the input is a buffer, C<trailingData> will return everything from the
1303end of the compressed data stream to the end of the buffer.
1304
1305If the input is a filehandle, C<trailingData> will return the data that is
1306left in the filehandle input buffer once the end of the compressed data
1307stream has been reached. You can then use the filehandle to read the rest
1308of the input file.
1309
1310Don't bother using C<trailingData> if the input is a filename.
1311
1312If you know the length of the compressed data stream before you start
1313uncompressing, you can avoid having to use C<trailingData> by setting the
1314C<InputLength> option.
1315
1316=back
1317
1318=head2 Examples
1319
1320Say you have a zip file, C<file1.zip>, that only contains a
1321single member, you can read it and write the uncompressed data to the
1322file C<file1.txt> like this.
1323
1324    use strict ;
1325    use warnings ;
1326    use IO::Uncompress::Unzip qw(unzip $UnzipError) ;
1327
1328    my $input = "file1.zip";
1329    my $output = "file1.txt";
1330    unzip $input => $output
1331        or die "unzip failed: $UnzipError\n";
1332
1333If you have a zip file that contains multiple members and want to read a
1334specific member from the file, say C<"data1">, use the C<Name> option
1335
1336    use strict ;
1337    use warnings ;
1338    use IO::Uncompress::Unzip qw(unzip $UnzipError) ;
1339
1340    my $input = "file1.zip";
1341    my $output = "file1.txt";
1342    unzip $input => $output, Name => "data1"
1343        or die "unzip failed: $UnzipError\n";
1344
1345Alternatively, if you want to read the  C<"data1"> member into memory, use
1346a scalar reference for the C<output> parameter.
1347
1348    use strict ;
1349    use warnings ;
1350    use IO::Uncompress::Unzip qw(unzip $UnzipError) ;
1351
1352    my $input = "file1.zip";
1353    my $output ;
1354    unzip $input => \$output, Name => "data1"
1355        or die "unzip failed: $UnzipError\n";
1356    # $output now contains the uncompressed data
1357
1358To read from an existing Perl filehandle, C<$input>, and write the
1359uncompressed data to a buffer, C<$buffer>.
1360
1361    use strict ;
1362    use warnings ;
1363    use IO::Uncompress::Unzip qw(unzip $UnzipError) ;
1364    use IO::File ;
1365
1366    my $input = new IO::File "<file1.zip"
1367        or die "Cannot open 'file1.zip': $!\n" ;
1368    my $buffer ;
1369    unzip $input => \$buffer
1370        or die "unzip failed: $UnzipError\n";
1371
1372=head1 OO Interface
1373
1374=head2 Constructor
1375
1376The format of the constructor for IO::Uncompress::Unzip is shown below
1377
1378    my $z = new IO::Uncompress::Unzip $input [OPTS]
1379        or die "IO::Uncompress::Unzip failed: $UnzipError\n";
1380
1381Returns an C<IO::Uncompress::Unzip> object on success and undef on failure.
1382The variable C<$UnzipError> will contain an error message on failure.
1383
1384If you are running Perl 5.005 or better the object, C<$z>, returned from
1385IO::Uncompress::Unzip can be used exactly like an L<IO::File|IO::File> filehandle.
1386This means that all normal input file operations can be carried out with
1387C<$z>.  For example, to read a line from a compressed file/buffer you can
1388use either of these forms
1389
1390    $line = $z->getline();
1391    $line = <$z>;
1392
1393The mandatory parameter C<$input> is used to determine the source of the
1394compressed data. This parameter can take one of three forms.
1395
1396=over 5
1397
1398=item A filename
1399
1400If the C<$input> parameter is a scalar, it is assumed to be a filename. This
1401file will be opened for reading and the compressed data will be read from it.
1402
1403=item A filehandle
1404
1405If the C<$input> parameter is a filehandle, the compressed data will be
1406read from it.
1407The string '-' can be used as an alias for standard input.
1408
1409=item A scalar reference
1410
1411If C<$input> is a scalar reference, the compressed data will be read from
1412C<$$input>.
1413
1414=back
1415
1416=head2 Constructor Options
1417
1418The option names defined below are case insensitive and can be optionally
1419prefixed by a '-'.  So all of the following are valid
1420
1421    -AutoClose
1422    -autoclose
1423    AUTOCLOSE
1424    autoclose
1425
1426OPTS is a combination of the following options:
1427
1428=over 5
1429
1430=item C<< Name => "membername" >>
1431
1432Open "membername" from the zip file for reading.
1433
1434=item C<< AutoClose => 0|1 >>
1435
1436This option is only valid when the C<$input> parameter is a filehandle. If
1437specified, and the value is true, it will result in the file being closed once
1438either the C<close> method is called or the IO::Uncompress::Unzip object is
1439destroyed.
1440
1441This parameter defaults to 0.
1442
1443=item C<< MultiStream => 0|1 >>
1444
1445Treats the complete zip file/buffer as a single compressed data
1446stream. When reading in multi-stream mode each member of the zip
1447file/buffer will be uncompressed in turn until the end of the file/buffer
1448is encountered.
1449
1450This parameter defaults to 0.
1451
1452=item C<< Prime => $string >>
1453
1454This option will uncompress the contents of C<$string> before processing the
1455input file/buffer.
1456
1457This option can be useful when the compressed data is embedded in another
1458file/data structure and it is not possible to work out where the compressed
1459data begins without having to read the first few bytes. If this is the
1460case, the uncompression can be I<primed> with these bytes using this
1461option.
1462
1463=item C<< Transparent => 0|1 >>
1464
1465If this option is set and the input file/buffer is not compressed data,
1466the module will allow reading of it anyway.
1467
1468In addition, if the input file/buffer does contain compressed data and
1469there is non-compressed data immediately following it, setting this option
1470will make this module treat the whole file/buffer as a single data stream.
1471
1472This option defaults to 1.
1473
1474=item C<< BlockSize => $num >>
1475
1476When reading the compressed input data, IO::Uncompress::Unzip will read it in
1477blocks of C<$num> bytes.
1478
1479This option defaults to 4096.
1480
1481=item C<< InputLength => $size >>
1482
1483When present this option will limit the number of compressed bytes read
1484from the input file/buffer to C<$size>. This option can be used in the
1485situation where there is useful data directly after the compressed data
1486stream and you know beforehand the exact length of the compressed data
1487stream.
1488
1489This option is mostly used when reading from a filehandle, in which case
1490the file pointer will be left pointing to the first byte directly after the
1491compressed data stream.
1492
1493This option defaults to off.
1494
1495=item C<< Append => 0|1 >>
1496
1497This option controls what the C<read> method does with uncompressed data.
1498
1499If set to 1, all uncompressed data will be appended to the output parameter
1500of the C<read> method.
1501
1502If set to 0, the contents of the output parameter of the C<read> method
1503will be overwritten by the uncompressed data.
1504
1505Defaults to 0.
1506
1507=item C<< Strict => 0|1 >>
1508
1509This option controls whether the extra checks defined below are used when
1510carrying out the decompression. When Strict is on, the extra tests are
1511carried out, when Strict is off they are not.
1512
1513The default for this option is off.
1514
1515=back
1516
1517=head2 Examples
1518
1519TODO
1520
1521=head1 Methods
1522
1523=head2 read
1524
1525Usage is
1526
1527    $status = $z->read($buffer)
1528
1529Reads a block of compressed data (the size of the compressed block is
1530determined by the C<Buffer> option in the constructor), uncompresses it and
1531writes any uncompressed data into C<$buffer>. If the C<Append> parameter is
1532set in the constructor, the uncompressed data will be appended to the
1533C<$buffer> parameter. Otherwise C<$buffer> will be overwritten.
1534
1535Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
1536or a negative number on error.
1537
1538=head2 read
1539
1540Usage is
1541
1542    $status = $z->read($buffer, $length)
1543    $status = $z->read($buffer, $length, $offset)
1544
1545    $status = read($z, $buffer, $length)
1546    $status = read($z, $buffer, $length, $offset)
1547
1548Attempt to read C<$length> bytes of uncompressed data into C<$buffer>.
1549
1550The main difference between this form of the C<read> method and the
1551previous one, is that this one will attempt to return I<exactly> C<$length>
1552bytes. The only circumstances that this function will not is if end-of-file
1553or an IO error is encountered.
1554
1555Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
1556or a negative number on error.
1557
1558=head2 getline
1559
1560Usage is
1561
1562    $line = $z->getline()
1563    $line = <$z>
1564
1565Reads a single line.
1566
1567This method fully supports the use of the variable C<$/> (or
1568C<$INPUT_RECORD_SEPARATOR> or C<$RS> when C<English> is in use) to
1569determine what constitutes an end of line. Paragraph mode, record mode and
1570file slurp mode are all supported.
1571
1572=head2 getc
1573
1574Usage is
1575
1576    $char = $z->getc()
1577
1578Read a single character.
1579
1580=head2 ungetc
1581
1582Usage is
1583
1584    $char = $z->ungetc($string)
1585
1586=head2 inflateSync
1587
1588Usage is
1589
1590    $status = $z->inflateSync()
1591
1592TODO
1593
1594=head2 getHeaderInfo
1595
1596Usage is
1597
1598    $hdr  = $z->getHeaderInfo();
1599    @hdrs = $z->getHeaderInfo();
1600
1601This method returns either a hash reference (in scalar context) or a list
1602or hash references (in array context) that contains information about each
1603of the header fields in the compressed data stream(s).
1604
1605=head2 tell
1606
1607Usage is
1608
1609    $z->tell()
1610    tell $z
1611
1612Returns the uncompressed file offset.
1613
1614=head2 eof
1615
1616Usage is
1617
1618    $z->eof();
1619    eof($z);
1620
1621Returns true if the end of the compressed input stream has been reached.
1622
1623=head2 seek
1624
1625    $z->seek($position, $whence);
1626    seek($z, $position, $whence);
1627
1628Provides a sub-set of the C<seek> functionality, with the restriction
1629that it is only legal to seek forward in the input file/buffer.
1630It is a fatal error to attempt to seek backward.
1631
1632Note that the implementation of C<seek> in this module does not provide
1633true random access to a compressed file/buffer. It  works by uncompressing
1634data from the current offset in the file/buffer until it reaches the
1635uncompressed offset specified in the parameters to C<seek>. For very small
1636files this may be acceptable behaviour. For large files it may cause an
1637unacceptable delay.
1638
1639The C<$whence> parameter takes one the usual values, namely SEEK_SET,
1640SEEK_CUR or SEEK_END.
1641
1642Returns 1 on success, 0 on failure.
1643
1644=head2 binmode
1645
1646Usage is
1647
1648    $z->binmode
1649    binmode $z ;
1650
1651This is a noop provided for completeness.
1652
1653=head2 opened
1654
1655    $z->opened()
1656
1657Returns true if the object currently refers to a opened file/buffer.
1658
1659=head2 autoflush
1660
1661    my $prev = $z->autoflush()
1662    my $prev = $z->autoflush(EXPR)
1663
1664If the C<$z> object is associated with a file or a filehandle, this method
1665returns the current autoflush setting for the underlying filehandle. If
1666C<EXPR> is present, and is non-zero, it will enable flushing after every
1667write/print operation.
1668
1669If C<$z> is associated with a buffer, this method has no effect and always
1670returns C<undef>.
1671
1672B<Note> that the special variable C<$|> B<cannot> be used to set or
1673retrieve the autoflush setting.
1674
1675=head2 input_line_number
1676
1677    $z->input_line_number()
1678    $z->input_line_number(EXPR)
1679
1680Returns the current uncompressed line number. If C<EXPR> is present it has
1681the effect of setting the line number. Note that setting the line number
1682does not change the current position within the file/buffer being read.
1683
1684The contents of C<$/> are used to determine what constitutes a line
1685terminator.
1686
1687=head2 fileno
1688
1689    $z->fileno()
1690    fileno($z)
1691
1692If the C<$z> object is associated with a file or a filehandle, C<fileno>
1693will return the underlying file descriptor. Once the C<close> method is
1694called C<fileno> will return C<undef>.
1695
1696If the C<$z> object is associated with a buffer, this method will return
1697C<undef>.
1698
1699=head2 close
1700
1701    $z->close() ;
1702    close $z ;
1703
1704Closes the output file/buffer.
1705
1706For most versions of Perl this method will be automatically invoked if
1707the IO::Uncompress::Unzip object is destroyed (either explicitly or by the
1708variable with the reference to the object going out of scope). The
1709exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
1710these cases, the C<close> method will be called automatically, but
1711not until global destruction of all live objects when the program is
1712terminating.
1713
1714Therefore, if you want your scripts to be able to run on all versions
1715of Perl, you should call C<close> explicitly and not rely on automatic
1716closing.
1717
1718Returns true on success, otherwise 0.
1719
1720If the C<AutoClose> option has been enabled when the IO::Uncompress::Unzip
1721object was created, and the object is associated with a file, the
1722underlying file will also be closed.
1723
1724=head2 nextStream
1725
1726Usage is
1727
1728    my $status = $z->nextStream();
1729
1730Skips to the next compressed data stream in the input file/buffer. If a new
1731compressed data stream is found, the eof marker will be cleared and C<$.>
1732will be reset to 0.
1733
1734Returns 1 if a new stream was found, 0 if none was found, and -1 if an
1735error was encountered.
1736
1737=head2 trailingData
1738
1739Usage is
1740
1741    my $data = $z->trailingData();
1742
1743Returns the data, if any, that is present immediately after the compressed
1744data stream once uncompression is complete. It only makes sense to call
1745this method once the end of the compressed data stream has been
1746encountered.
1747
1748This option can be used when there is useful information immediately
1749following the compressed data stream, and you don't know the length of the
1750compressed data stream.
1751
1752If the input is a buffer, C<trailingData> will return everything from the
1753end of the compressed data stream to the end of the buffer.
1754
1755If the input is a filehandle, C<trailingData> will return the data that is
1756left in the filehandle input buffer once the end of the compressed data
1757stream has been reached. You can then use the filehandle to read the rest
1758of the input file.
1759
1760Don't bother using C<trailingData> if the input is a filename.
1761
1762If you know the length of the compressed data stream before you start
1763uncompressing, you can avoid having to use C<trailingData> by setting the
1764C<InputLength> option in the constructor.
1765
1766=head1 Importing
1767
1768No symbolic constants are required by this IO::Uncompress::Unzip at present.
1769
1770=over 5
1771
1772=item :all
1773
1774Imports C<unzip> and C<$UnzipError>.
1775Same as doing this
1776
1777    use IO::Uncompress::Unzip qw(unzip $UnzipError) ;
1778
1779=back
1780
1781=head1 EXAMPLES
1782
1783=head2 Working with Net::FTP
1784
1785See L<IO::Compress::FAQ|IO::Compress::FAQ/"Compressed files and Net::FTP">
1786
1787=head2 Walking through a zip file
1788
1789The code below can be used to traverse a zip file, one compressed data
1790stream at a time.
1791
1792    use IO::Uncompress::Unzip qw($UnzipError);
1793
1794    my $zipfile = "somefile.zip";
1795    my $u = new IO::Uncompress::Unzip $zipfile
1796        or die "Cannot open $zipfile: $UnzipError";
1797
1798    my $status;
1799    for ($status = 1; $status > 0; $status = $u->nextStream())
1800    {
1801
1802        my $name = $u->getHeaderInfo()->{Name};
1803        warn "Processing member $name\n" ;
1804
1805        my $buff;
1806        while (($status = $u->read($buff)) > 0) {
1807            # Do something here
1808        }
1809
1810        last if $status < 0;
1811    }
1812
1813    die "Error processing $zipfile: $!\n"
1814        if $status < 0 ;
1815
1816Each individual compressed data stream is read until the logical
1817end-of-file is reached. Then C<nextStream> is called. This will skip to the
1818start of the next compressed data stream and clear the end-of-file flag.
1819
1820It is also worth noting that C<nextStream> can be called at any time -- you
1821don't have to wait until you have exhausted a compressed data stream before
1822skipping to the next one.
1823
1824=head2 Unzipping a complete zip file to disk
1825
1826Daniel S. Sterling has written a script that uses C<IO::Uncompress::UnZip>
1827to read a zip file and unzip its contents to disk.
1828
1829The script is available from L<https://gist.github.com/eqhmcow/5389877>
1830
1831=head1 SEE ALSO
1832
1833L<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>
1834
1835L<IO::Compress::FAQ|IO::Compress::FAQ>
1836
1837L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
1838L<Archive::Tar|Archive::Tar>,
1839L<IO::Zlib|IO::Zlib>
1840
1841For RFC 1950, 1951 and 1952 see
1842L<http://www.faqs.org/rfcs/rfc1950.html>,
1843L<http://www.faqs.org/rfcs/rfc1951.html> and
1844L<http://www.faqs.org/rfcs/rfc1952.html>
1845
1846The I<zlib> compression library was written by Jean-loup Gailly
1847C<gzip@prep.ai.mit.edu> and Mark Adler C<madler@alumni.caltech.edu>.
1848
1849The primary site for the I<zlib> compression library is
1850L<http://www.zlib.org>.
1851
1852The primary site for gzip is L<http://www.gzip.org>.
1853
1854=head1 AUTHOR
1855
1856This module was written by Paul Marquess, C<pmqs@cpan.org>.
1857
1858=head1 MODIFICATION HISTORY
1859
1860See the Changes file.
1861
1862=head1 COPYRIGHT AND LICENSE
1863
1864Copyright (c) 2005-2019 Paul Marquess. All rights reserved.
1865
1866This program is free software; you can redistribute it and/or
1867modify it under the same terms as Perl itself.
1868
1869