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 84     84   6427 use strict ;
  84         166  
  84         2776  
9 84     84   408 use warnings;
  84         147  
  84         1878  
10 84     84   397 use bytes;
  84         140  
  84         375  
11              
12 84     84   27597 use IO::Uncompress::RawInflate 2.204 ;
  84         1777  
  84         3764  
13              
14 84     84   521 use Compress::Raw::Zlib 2.204 () ;
  84         1101  
  84         2072  
15 84     84   421 use IO::Compress::Base::Common 2.204 qw(:Status );
  84         879  
  84         7963  
16 84     84   24990 use IO::Compress::Gzip::Constants 2.204 ;
  84         1308  
  84         13998  
17 84     84   25920 use IO::Compress::Zlib::Extra 2.204 ;
  84         1308  
  84         103423  
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             push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
27             Exporter::export_ok_tags('all');
28              
29             $GunzipError = '';
30              
31             $VERSION = '2.204';
32              
33             sub new
34             {
35 406     406 1 59114 my $class = shift ;
36 406         751 $GunzipError = '';
37 406         1278 my $obj = IO::Compress::Base::Common::createSelfTiedObject($class, \$GunzipError);
38              
39 406         1373 $obj->_create(undef, 0, @_);
40             }
41              
42             sub gunzip
43             {
44 73     73 1 66206 my $obj = IO::Compress::Base::Common::createSelfTiedObject(undef, \$GunzipError);
45 73         301 return $obj->_inf(@_) ;
46             }
47              
48             sub getExtraParams
49             {
50 462     462 0 3413 return ( 'parseextra' => [IO::Compress::Base::Common::Parse_boolean, 0] ) ;
51             }
52              
53             sub ckParams
54             {
55 470     470 0 755 my $self = shift ;
56 470         645 my $got = shift ;
57              
58             # gunzip always needs crc32
59 470         1348 $got->setValue('crc32' => 1);
60              
61 470         1136 return 1;
62             }
63              
64             sub ckMagic
65             {
66 1658     1658 0 2594 my $self = shift;
67              
68 1658         2236 my $magic ;
69 1658         5028 $self->smartReadExact(\$magic, GZIP_ID_SIZE);
70              
71 1658         3213 *$self->{HeaderPending} = $magic ;
72              
73 1658 100       3437 return $self->HeaderError("Minimum header size is " .
74             GZIP_MIN_HEADER_SIZE . " bytes")
75             if length $magic != GZIP_ID_SIZE ;
76              
77 1622 100       3311 return $self->HeaderError("Bad Magic")
78             if ! isGzipMagic($magic) ;
79              
80 1034         2292 *$self->{Type} = 'rfc1952';
81              
82 1034         2770 return $magic ;
83             }
84              
85             sub readHeader
86             {
87 1034     1034 0 1834 my $self = shift;
88 1034         2262 my $magic = shift;
89              
90 1034         2162 return $self->_readGzipHeader($magic);
91             }
92              
93             sub chkTrailer
94             {
95 988     988 0 1516 my $self = shift;
96 988         1390 my $trailer = shift;
97              
98             # Check CRC & ISIZE
99 988         2856 my ($CRC32, $ISIZE) = unpack("V V", $trailer) ;
100 988         2099 *$self->{Info}{CRC32} = $CRC32;
101 988         1715 *$self->{Info}{ISIZE} = $ISIZE;
102              
103 988 100       1994 if (*$self->{Strict}) {
104             return $self->TrailerError("CRC mismatch")
105 493 100       1183 if $CRC32 != *$self->{Uncomp}->crc32() ;
106              
107 491         1260 my $exp_isize = *$self->{UnCompSize}->get32bit();
108 491 100       1027 return $self->TrailerError("ISIZE mismatch. Got $ISIZE"
109             . ", expected $exp_isize")
110             if $ISIZE != $exp_isize ;
111             }
112              
113 985         2649 return STATUS_OK;
114             }
115              
116             sub isGzipMagic
117             {
118 1622     1622 0 2475 my $buffer = shift ;
119 1622 50       3213 return 0 if length $buffer < GZIP_ID_SIZE ;
120 1622         4942 my ($id1, $id2) = unpack("C C", $buffer) ;
121 1622   100     7335 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 1034     1034   1830 my ($self, $magic) = @_ ;
149 1034         1471 my ($HeaderCRC) ;
150 1034         1592 my ($buffer) = '' ;
151              
152 1034 50       2403 $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 1034         2388 my $keep = $magic . $buffer ;
157 1034         1678 *$self->{HeaderPending} = $keep ;
158              
159             # now split out the various parts
160 1034         3182 my ($cm, $flag, $mtime, $xfl, $os) = unpack("C C V C C", $buffer) ;
161              
162 1034 100       2366 $cm == GZIP_CM_DEFLATED
163             or return $self->HeaderError("Not Deflate (CM is $cm)") ;
164              
165             # check for use of reserved bits
166 1033 100       2069 return $self->HeaderError("Use of Reserved Bits in FLG field.")
167             if $flag & GZIP_FLG_RESERVED ;
168              
169 1032         1291 my $EXTRA ;
170 1032         1552 my @EXTRA = () ;
171 1032 100       1905 if ($flag & GZIP_FLG_FEXTRA) {
172 471         634 $EXTRA = "" ;
173 471 100       979 $self->smartReadExact(\$buffer, GZIP_FEXTRA_HEADER_SIZE)
174             or return $self->TruncatedHeader("FEXTRA Length") ;
175              
176 470         1080 my ($XLEN) = unpack("v", $buffer) ;
177 470 100       968 $self->smartReadExact(\$EXTRA, $XLEN)
178             or return $self->TruncatedHeader("FEXTRA Body");
179 468         1315 $keep .= $buffer . $EXTRA ;
180              
181 468 100 100     1524 if ($XLEN && *$self->{'ParseExtra'}) {
182 446         1162 my $bad = IO::Compress::Zlib::Extra::parseRawExtra($EXTRA,
183             \@EXTRA, 1, 1);
184 446 100       866 return $self->HeaderError($bad)
185             if defined $bad;
186             }
187             }
188              
189 1025         1443 my $origname ;
190 1025 100       1984 if ($flag & GZIP_FLG_FNAME) {
191 114         201 $origname = "" ;
192 114         176 while (1) {
193 2108 100       4281 $self->smartReadExact(\$buffer, 1)
194             or return $self->TruncatedHeader("FNAME");
195 2104 100       4200 last if $buffer eq GZIP_NULL_BYTE ;
196 1994         2866 $origname .= $buffer
197             }
198 110         258 $keep .= $origname . GZIP_NULL_BYTE ;
199              
200             return $self->HeaderError("Non ISO 8859-1 Character found in Name")
201 110 100 66     320 if *$self->{Strict} && $origname =~ /$GZIP_FNAME_INVALID_CHAR_RE/o ;
202             }
203              
204 1020         1347 my $comment ;
205 1020 100       1815 if ($flag & GZIP_FLG_FCOMMENT) {
206 451         587 $comment = "";
207 451         547 while (1) {
208 7921 100       14176 $self->smartReadExact(\$buffer, 1)
209             or return $self->TruncatedHeader("FCOMMENT");
210 7914 100       14899 last if $buffer eq GZIP_NULL_BYTE ;
211 7470         9619 $comment .= $buffer
212             }
213 444         863 $keep .= $comment . GZIP_NULL_BYTE ;
214              
215             return $self->HeaderError("Non ISO 8859-1 Character found in Comment")
216 444 100 100     2053 if *$self->{Strict} && $comment =~ /$GZIP_FCOMMENT_INVALID_CHAR_RE/o ;
217             }
218              
219 1012 100       1905 if ($flag & GZIP_FLG_FHCRC) {
220 446 100       919 $self->smartReadExact(\$buffer, GZIP_FHCRC_SIZE)
221             or return $self->TruncatedHeader("FHCRC");
222              
223 444         1028 $HeaderCRC = unpack("v", $buffer) ;
224 444         1633 my $crc16 = Compress::Raw::Zlib::crc32($keep) & 0xFF ;
225              
226             return $self->HeaderError("CRC16 mismatch.")
227 444 100 100     1494 if *$self->{Strict} && $crc16 != $HeaderCRC;
228              
229 443         660 $keep .= $buffer ;
230             }
231              
232             # Assume compression method is deflated for xfl tests
233             #if ($xfl) {
234             #}
235              
236 1009         1781 *$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 1009 100       19290 ? $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__