File Coverage

blib/lib/IO/Uncompress/Gunzip.pm
Criterion Covered Total %
statement 106 115 92.1
branch 63 72 87.5
condition 14 15 93.3
subroutine 17 18 94.4
pod 2 8 25.0
total 202 228 88.6


line stmt bran cond sub pod time code
1              
2             package IO::Uncompress::Gunzip ;
3              
4             require 5.006 ;
5              
6             # for RFC1952
7              
8 96     96   6411 use strict ;
  96         151  
  96         5933  
9 96     96   2728 use warnings;
  96         2335  
  96         5564  
10 96     96   3727 use bytes;
  96         4692  
  96         4938  
11              
12 96     96   34436 use IO::Uncompress::RawInflate 2.222 ;
  96         1991  
  96         4846  
13              
14 96     96   2585 use Compress::Raw::Zlib 2.222 () ;
  96         1467  
  96         2364  
15 96     96   396 use IO::Compress::Base::Common 2.222 qw(:Status );
  96         899  
  96         9336  
16 96     96   29391 use IO::Compress::Gzip::Constants 2.222 ;
  96         1384  
  96         15443  
17 96     96   27098 use IO::Compress::Zlib::Extra 2.222 ;
  96         2803  
  96         113354  
18              
19             require Exporter ;
20              
21             our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $GunzipError);
22              
23             @ISA = qw(IO::Uncompress::RawInflate Exporter);
24             @EXPORT_OK = qw( $GunzipError gunzip );
25             %EXPORT_TAGS = %IO::Uncompress::RawInflate::DEFLATE_CONSTANTS ;
26             $EXPORT_TAGS{all} = [ defined $EXPORT_TAGS{all} ? @{ $EXPORT_TAGS{all} } : (), @EXPORT_OK ] ;
27             Exporter::export_ok_tags('all');
28              
29             $GunzipError = '';
30              
31             $VERSION = '2.222';
32              
33             sub new
34             {
35 418     418 1 52366 my $class = shift ;
36 418         779 $GunzipError = '';
37 418         1390 my $obj = IO::Compress::Base::Common::createSelfTiedObject($class, \$GunzipError);
38              
39 418         1439 $obj->_create(undef, 0, @_);
40             }
41              
42             sub gunzip
43             {
44 73     73 1 195266 my $obj = IO::Compress::Base::Common::createSelfTiedObject(undef, \$GunzipError);
45 73         1885 return $obj->_inf(@_) ;
46             }
47              
48             sub getExtraParams
49             {
50 474     474 0 3430 return ( 'parseextra' => [IO::Compress::Base::Common::Parse_boolean, 0] ) ;
51             }
52              
53             sub ckParams
54             {
55 482     482 0 560 my $self = shift ;
56 482         504 my $got = shift ;
57              
58             # gunzip always needs crc32
59 482         1310 $got->setValue('crc32' => 1);
60              
61 482         1012 return 1;
62             }
63              
64             sub ckMagic
65             {
66 1670     1670 0 1913 my $self = shift;
67              
68 1670         1757 my $magic ;
69 1670         4275 $self->smartReadExact(\$magic, GZIP_ID_SIZE);
70              
71 1670         2603 *$self->{HeaderPending} = $magic ;
72              
73 1670 100       2923 return $self->HeaderError("Minimum header size is " .
74             GZIP_MIN_HEADER_SIZE . " bytes")
75             if length $magic != GZIP_ID_SIZE ;
76              
77 1634 100       3092 return $self->HeaderError("Bad Magic")
78             if ! isGzipMagic($magic) ;
79              
80 1046         1745 *$self->{Type} = 'rfc1952';
81              
82 1046         2290 return $magic ;
83             }
84              
85             sub readHeader
86             {
87 1046     1046 0 1108 my $self = shift;
88 1046         1170 my $magic = shift;
89              
90 1046         2122 return $self->_readGzipHeader($magic);
91             }
92              
93             sub chkTrailer
94             {
95 1000     1000 0 1042 my $self = shift;
96 1000         1127 my $trailer = shift;
97              
98             # Check CRC & ISIZE
99 1000         2514 my ($CRC32, $ISIZE) = unpack("V V", $trailer) ;
100 1000         1699 *$self->{Info}{CRC32} = $CRC32;
101 1000         1516 *$self->{Info}{ISIZE} = $ISIZE;
102              
103 1000 100       1619 if (*$self->{Strict}) {
104             return $self->TrailerError("CRC mismatch")
105 493 100       1057 if $CRC32 != *$self->{Uncomp}->crc32() ;
106              
107 491         892 my $exp_isize = *$self->{UnCompSize}->get32bit();
108 491 100       795 return $self->TrailerError("ISIZE mismatch. Got $ISIZE"
109             . ", expected $exp_isize")
110             if $ISIZE != $exp_isize ;
111             }
112              
113 997         1903 return STATUS_OK;
114             }
115              
116             sub isGzipMagic
117             {
118 1634     1634 0 2014 my $buffer = shift ;
119 1634 50       2554 return 0 if length $buffer < GZIP_ID_SIZE ;
120 1634         4029 my ($id1, $id2) = unpack("C C", $buffer) ;
121 1634   100     6029 return $id1 == GZIP_ID1 && $id2 == GZIP_ID2 ;
122             }
123              
124             sub _readFullGzipHeader($)
125             {
126 0     0   0 my ($self) = @_ ;
127 0         0 my $magic = '' ;
128              
129 0         0 $self->smartReadExact(\$magic, GZIP_ID_SIZE);
130              
131 0         0 *$self->{HeaderPending} = $magic ;
132              
133 0 0       0 return $self->HeaderError("Minimum header size is " .
134             GZIP_MIN_HEADER_SIZE . " bytes")
135             if length $magic != GZIP_ID_SIZE ;
136              
137              
138 0 0       0 return $self->HeaderError("Bad Magic")
139             if ! isGzipMagic($magic) ;
140              
141 0         0 my $status = $self->_readGzipHeader($magic);
142 0 0       0 delete *$self->{Transparent} if ! defined $status ;
143 0         0 return $status ;
144             }
145              
146             sub _readGzipHeader($)
147             {
148 1046     1046   1665 my ($self, $magic) = @_ ;
149 1046         1047 my ($HeaderCRC) ;
150 1046         1336 my ($buffer) = '' ;
151              
152 1046 50       1806 $self->smartReadExact(\$buffer, GZIP_MIN_HEADER_SIZE - GZIP_ID_SIZE)
153             or return $self->HeaderError("Minimum header size is " .
154             GZIP_MIN_HEADER_SIZE . " bytes") ;
155              
156 1046         2033 my $keep = $magic . $buffer ;
157 1046         1624 *$self->{HeaderPending} = $keep ;
158              
159             # now split out the various parts
160 1046         2629 my ($cm, $flag, $mtime, $xfl, $os) = unpack("C C V C C", $buffer) ;
161              
162 1046 100       1743 $cm == GZIP_CM_DEFLATED
163             or return $self->HeaderError("Not Deflate (CM is $cm)") ;
164              
165             # check for use of reserved bits
166 1045 100       1765 return $self->HeaderError("Use of Reserved Bits in FLG field.")
167             if $flag & GZIP_FLG_RESERVED ;
168              
169 1044         990 my $EXTRA ;
170 1044         1312 my @EXTRA = () ;
171 1044 100       1601 if ($flag & GZIP_FLG_FEXTRA) {
172 471         578 $EXTRA = "" ;
173 471 100       782 $self->smartReadExact(\$buffer, GZIP_FEXTRA_HEADER_SIZE)
174             or return $self->TruncatedHeader("FEXTRA Length") ;
175              
176 470         837 my ($XLEN) = unpack("v", $buffer) ;
177 470 100       756 $self->smartReadExact(\$EXTRA, $XLEN)
178             or return $self->TruncatedHeader("FEXTRA Body");
179 468         977 $keep .= $buffer . $EXTRA ;
180              
181 468 100 100     1232 if ($XLEN && *$self->{'ParseExtra'}) {
182 446         1340 my $bad = IO::Compress::Zlib::Extra::parseRawExtra($EXTRA,
183             \@EXTRA, 1, 1);
184 446 100       782 return $self->HeaderError($bad)
185             if defined $bad;
186             }
187             }
188              
189 1037         1031 my $origname ;
190 1037 100       1683 if ($flag & GZIP_FLG_FNAME) {
191 114         165 $origname = "" ;
192 114         118 while (1) {
193 2108 100       2655 $self->smartReadExact(\$buffer, 1)
194             or return $self->TruncatedHeader("FNAME");
195 2104 100       2665 last if $buffer eq GZIP_NULL_BYTE ;
196 1994         1992 $origname .= $buffer
197             }
198 110         189 $keep .= $origname . GZIP_NULL_BYTE ;
199              
200             return $self->HeaderError("Non ISO 8859-1 Character found in Name")
201 110 100 66     243 if *$self->{Strict} && $origname =~ /$GZIP_FNAME_INVALID_CHAR_RE/o ;
202             }
203              
204 1032         1123 my $comment ;
205 1032 100       1572 if ($flag & GZIP_FLG_FCOMMENT) {
206 451         492 $comment = "";
207 451         422 while (1) {
208 7921 100       10230 $self->smartReadExact(\$buffer, 1)
209             or return $self->TruncatedHeader("FCOMMENT");
210 7914 100       10589 last if $buffer eq GZIP_NULL_BYTE ;
211 7470         7284 $comment .= $buffer
212             }
213 444         743 $keep .= $comment . GZIP_NULL_BYTE ;
214              
215             return $self->HeaderError("Non ISO 8859-1 Character found in Comment")
216 444 100 100     2048 if *$self->{Strict} && $comment =~ /$GZIP_FCOMMENT_INVALID_CHAR_RE/o ;
217             }
218              
219 1024 100       1675 if ($flag & GZIP_FLG_FHCRC) {
220 446 100       847 $self->smartReadExact(\$buffer, GZIP_FHCRC_SIZE)
221             or return $self->TruncatedHeader("FHCRC");
222              
223 444         806 $HeaderCRC = unpack("v", $buffer) ;
224 444         1537 my $crc16 = Compress::Raw::Zlib::crc32($keep) & 0xFF ;
225              
226             return $self->HeaderError("CRC16 mismatch.")
227 444 100 100     1110 if *$self->{Strict} && $crc16 != $HeaderCRC;
228              
229 443         629 $keep .= $buffer ;
230             }
231              
232             # Assume compression method is deflated for xfl tests
233             #if ($xfl) {
234             #}
235              
236 1021         1503 *$self->{Type} = 'rfc1952';
237              
238             return {
239             'Type' => 'rfc1952',
240             'FingerprintLength' => 2,
241             'HeaderLength' => length $keep,
242             'TrailerLength' => GZIP_TRAILER_SIZE,
243             'Header' => $keep,
244             'isMinimalHeader' => $keep eq GZIP_MINIMUM_HEADER ? 1 : 0,
245              
246             'MethodID' => $cm,
247             'MethodName' => $cm == GZIP_CM_DEFLATED ? "Deflated" : "Unknown" ,
248             'TextFlag' => $flag & GZIP_FLG_FTEXT ? 1 : 0,
249             'HeaderCRCFlag' => $flag & GZIP_FLG_FHCRC ? 1 : 0,
250             'NameFlag' => $flag & GZIP_FLG_FNAME ? 1 : 0,
251             'CommentFlag' => $flag & GZIP_FLG_FCOMMENT ? 1 : 0,
252             'ExtraFlag' => $flag & GZIP_FLG_FEXTRA ? 1 : 0,
253             'Name' => $origname,
254             'Comment' => $comment,
255             'Time' => $mtime,
256             'OsID' => $os,
257             'OsName' => defined $GZIP_OS_Names{$os}
258 1021 100       18061 ? $GZIP_OS_Names{$os} : "Unknown",
    50          
    100          
    100          
    100          
    100          
    100          
    100          
259             'HeaderCRC' => $HeaderCRC,
260             'Flags' => $flag,
261             'ExtraFlags' => $xfl,
262             'ExtraFieldRaw' => $EXTRA,
263             'ExtraField' => [ @EXTRA ],
264              
265              
266             #'CompSize'=> $compsize,
267             #'CRC32'=> $CRC32,
268             #'OrigSize'=> $ISIZE,
269             }
270             }
271              
272              
273             1;
274              
275             __END__