| 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 |  | 6982 | use strict ; | 
|  | 84 |  |  |  |  | 182 |  | 
|  | 84 |  |  |  |  | 2982 |  | 
| 9 | 84 |  |  | 84 |  | 444 | use warnings; | 
|  | 84 |  |  |  |  | 153 |  | 
|  | 84 |  |  |  |  | 1844 |  | 
| 10 | 84 |  |  | 84 |  | 396 | use bytes; | 
|  | 84 |  |  |  |  | 166 |  | 
|  | 84 |  |  |  |  | 418 |  | 
| 11 |  |  |  |  |  |  |  | 
| 12 | 84 |  |  | 84 |  | 29517 | use IO::Uncompress::RawInflate 2.206 ; | 
|  | 84 |  |  |  |  | 1856 |  | 
|  | 84 |  |  |  |  | 3783 |  | 
| 13 |  |  |  |  |  |  |  | 
| 14 | 84 |  |  | 84 |  | 529 | use Compress::Raw::Zlib 2.206 () ; | 
|  | 84 |  |  |  |  | 1144 |  | 
|  | 84 |  |  |  |  | 2079 |  | 
| 15 | 84 |  |  | 84 |  | 438 | use IO::Compress::Base::Common 2.206 qw(:Status ); | 
|  | 84 |  |  |  |  | 902 |  | 
|  | 84 |  |  |  |  | 7957 |  | 
| 16 | 84 |  |  | 84 |  | 26070 | use IO::Compress::Gzip::Constants 2.206 ; | 
|  | 84 |  |  |  |  | 1366 |  | 
|  | 84 |  |  |  |  | 14179 |  | 
| 17 | 84 |  |  | 84 |  | 27923 | use IO::Compress::Zlib::Extra 2.206 ; | 
|  | 84 |  |  |  |  | 1307 |  | 
|  | 84 |  |  |  |  | 106748 |  | 
| 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.206'; | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | sub new | 
| 34 |  |  |  |  |  |  | { | 
| 35 | 406 |  |  | 406 | 1 | 46268 | my $class = shift ; | 
| 36 | 406 |  |  |  |  | 774 | $GunzipError = ''; | 
| 37 | 406 |  |  |  |  | 1162 | my $obj = IO::Compress::Base::Common::createSelfTiedObject($class, \$GunzipError); | 
| 38 |  |  |  |  |  |  |  | 
| 39 | 406 |  |  |  |  | 1405 | $obj->_create(undef, 0, @_); | 
| 40 |  |  |  |  |  |  | } | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | sub gunzip | 
| 43 |  |  |  |  |  |  | { | 
| 44 | 73 |  |  | 73 | 1 | 61616 | my $obj = IO::Compress::Base::Common::createSelfTiedObject(undef, \$GunzipError); | 
| 45 | 73 |  |  |  |  | 293 | return $obj->_inf(@_) ; | 
| 46 |  |  |  |  |  |  | } | 
| 47 |  |  |  |  |  |  |  | 
| 48 |  |  |  |  |  |  | sub getExtraParams | 
| 49 |  |  |  |  |  |  | { | 
| 50 | 462 |  |  | 462 | 0 | 4282 | return ( 'parseextra' => [IO::Compress::Base::Common::Parse_boolean,  0] ) ; | 
| 51 |  |  |  |  |  |  | } | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | sub ckParams | 
| 54 |  |  |  |  |  |  | { | 
| 55 | 470 |  |  | 470 | 0 | 720 | my $self = shift ; | 
| 56 | 470 |  |  |  |  | 602 | my $got = shift ; | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  | # gunzip always needs crc32 | 
| 59 | 470 |  |  |  |  | 1235 | $got->setValue('crc32' => 1); | 
| 60 |  |  |  |  |  |  |  | 
| 61 | 470 |  |  |  |  | 1135 | return 1; | 
| 62 |  |  |  |  |  |  | } | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | sub ckMagic | 
| 65 |  |  |  |  |  |  | { | 
| 66 | 1658 |  |  | 1658 | 0 | 2509 | my $self = shift; | 
| 67 |  |  |  |  |  |  |  | 
| 68 | 1658 |  |  |  |  | 2116 | my $magic ; | 
| 69 | 1658 |  |  |  |  | 5613 | $self->smartReadExact(\$magic, GZIP_ID_SIZE); | 
| 70 |  |  |  |  |  |  |  | 
| 71 | 1658 |  |  |  |  | 3285 | *$self->{HeaderPending} = $magic ; | 
| 72 |  |  |  |  |  |  |  | 
| 73 | 1658 | 100 |  |  |  | 3354 | return $self->HeaderError("Minimum header size is " . | 
| 74 |  |  |  |  |  |  | GZIP_MIN_HEADER_SIZE . " bytes") | 
| 75 |  |  |  |  |  |  | if length $magic != GZIP_ID_SIZE ; | 
| 76 |  |  |  |  |  |  |  | 
| 77 | 1622 | 100 |  |  |  | 3312 | return $self->HeaderError("Bad Magic") | 
| 78 |  |  |  |  |  |  | if ! isGzipMagic($magic) ; | 
| 79 |  |  |  |  |  |  |  | 
| 80 | 1034 |  |  |  |  | 2206 | *$self->{Type} = 'rfc1952'; | 
| 81 |  |  |  |  |  |  |  | 
| 82 | 1034 |  |  |  |  | 2717 | return $magic ; | 
| 83 |  |  |  |  |  |  | } | 
| 84 |  |  |  |  |  |  |  | 
| 85 |  |  |  |  |  |  | sub readHeader | 
| 86 |  |  |  |  |  |  | { | 
| 87 | 1034 |  |  | 1034 | 0 | 1440 | my $self = shift; | 
| 88 | 1034 |  |  |  |  | 1377 | my $magic = shift; | 
| 89 |  |  |  |  |  |  |  | 
| 90 | 1034 |  |  |  |  | 2131 | return $self->_readGzipHeader($magic); | 
| 91 |  |  |  |  |  |  | } | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | sub chkTrailer | 
| 94 |  |  |  |  |  |  | { | 
| 95 | 988 |  |  | 988 | 0 | 1475 | my $self = shift; | 
| 96 | 988 |  |  |  |  | 1360 | my $trailer = shift; | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | # Check CRC & ISIZE | 
| 99 | 988 |  |  |  |  | 2809 | my ($CRC32, $ISIZE) = unpack("V V", $trailer) ; | 
| 100 | 988 |  |  |  |  | 2017 | *$self->{Info}{CRC32} = $CRC32; | 
| 101 | 988 |  |  |  |  | 1639 | *$self->{Info}{ISIZE} = $ISIZE; | 
| 102 |  |  |  |  |  |  |  | 
| 103 | 988 | 100 |  |  |  | 1928 | if (*$self->{Strict}) { | 
| 104 |  |  |  |  |  |  | return $self->TrailerError("CRC mismatch") | 
| 105 | 493 | 100 |  |  |  | 1111 | if $CRC32 != *$self->{Uncomp}->crc32() ; | 
| 106 |  |  |  |  |  |  |  | 
| 107 | 491 |  |  |  |  | 1092 | my $exp_isize = *$self->{UnCompSize}->get32bit(); | 
| 108 | 491 | 100 |  |  |  | 849 | return $self->TrailerError("ISIZE mismatch. Got $ISIZE" | 
| 109 |  |  |  |  |  |  | . ", expected $exp_isize") | 
| 110 |  |  |  |  |  |  | if $ISIZE != $exp_isize ; | 
| 111 |  |  |  |  |  |  | } | 
| 112 |  |  |  |  |  |  |  | 
| 113 | 985 |  |  |  |  | 2475 | return STATUS_OK; | 
| 114 |  |  |  |  |  |  | } | 
| 115 |  |  |  |  |  |  |  | 
| 116 |  |  |  |  |  |  | sub isGzipMagic | 
| 117 |  |  |  |  |  |  | { | 
| 118 | 1622 |  |  | 1622 | 0 | 3318 | my $buffer = shift ; | 
| 119 | 1622 | 50 |  |  |  | 2936 | return 0 if length $buffer < GZIP_ID_SIZE ; | 
| 120 | 1622 |  |  |  |  | 4607 | my ($id1, $id2) = unpack("C C", $buffer) ; | 
| 121 | 1622 |  | 100 |  |  | 7050 | 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 |  | 1816 | my ($self, $magic) = @_ ; | 
| 149 | 1034 |  |  |  |  | 1314 | my ($HeaderCRC) ; | 
| 150 | 1034 |  |  |  |  | 1533 | my ($buffer) = '' ; | 
| 151 |  |  |  |  |  |  |  | 
| 152 | 1034 | 50 |  |  |  | 3242 | $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 |  |  |  |  | 2260 | my $keep = $magic . $buffer ; | 
| 157 | 1034 |  |  |  |  | 1677 | *$self->{HeaderPending} = $keep ; | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | # now split out the various parts | 
| 160 | 1034 |  |  |  |  | 3082 | my ($cm, $flag, $mtime, $xfl, $os) = unpack("C C V C C", $buffer) ; | 
| 161 |  |  |  |  |  |  |  | 
| 162 | 1034 | 100 |  |  |  | 2194 | $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 |  |  |  | 2047 | return $self->HeaderError("Use of Reserved Bits in FLG field.") | 
| 167 |  |  |  |  |  |  | if $flag & GZIP_FLG_RESERVED ; | 
| 168 |  |  |  |  |  |  |  | 
| 169 | 1032 |  |  |  |  | 1417 | my $EXTRA ; | 
| 170 | 1032 |  |  |  |  | 1434 | my @EXTRA = () ; | 
| 171 | 1032 | 100 |  |  |  | 1736 | if ($flag & GZIP_FLG_FEXTRA) { | 
| 172 | 471 |  |  |  |  | 531 | $EXTRA = "" ; | 
| 173 | 471 | 100 |  |  |  | 874 | $self->smartReadExact(\$buffer, GZIP_FEXTRA_HEADER_SIZE) | 
| 174 |  |  |  |  |  |  | or return $self->TruncatedHeader("FEXTRA Length") ; | 
| 175 |  |  |  |  |  |  |  | 
| 176 | 470 |  |  |  |  | 927 | my ($XLEN) = unpack("v", $buffer) ; | 
| 177 | 470 | 100 |  |  |  | 894 | $self->smartReadExact(\$EXTRA, $XLEN) | 
| 178 |  |  |  |  |  |  | or return $self->TruncatedHeader("FEXTRA Body"); | 
| 179 | 468 |  |  |  |  | 1198 | $keep .= $buffer . $EXTRA ; | 
| 180 |  |  |  |  |  |  |  | 
| 181 | 468 | 100 | 100 |  |  | 1327 | if ($XLEN && *$self->{'ParseExtra'}) { | 
| 182 | 446 |  |  |  |  | 1105 | my $bad = IO::Compress::Zlib::Extra::parseRawExtra($EXTRA, | 
| 183 |  |  |  |  |  |  | \@EXTRA, 1, 1); | 
| 184 | 446 | 100 |  |  |  | 775 | return $self->HeaderError($bad) | 
| 185 |  |  |  |  |  |  | if defined $bad; | 
| 186 |  |  |  |  |  |  | } | 
| 187 |  |  |  |  |  |  | } | 
| 188 |  |  |  |  |  |  |  | 
| 189 | 1025 |  |  |  |  | 1268 | my $origname ; | 
| 190 | 1025 | 100 |  |  |  | 1842 | if ($flag & GZIP_FLG_FNAME) { | 
| 191 | 114 |  |  |  |  | 199 | $origname = "" ; | 
| 192 | 114 |  |  |  |  | 155 | while (1) { | 
| 193 | 2201 | 100 |  |  |  | 4238 | $self->smartReadExact(\$buffer, 1) | 
| 194 |  |  |  |  |  |  | or return $self->TruncatedHeader("FNAME"); | 
| 195 | 2197 | 100 |  |  |  | 4264 | last if $buffer eq GZIP_NULL_BYTE ; | 
| 196 | 2087 |  |  |  |  | 2966 | $origname .= $buffer | 
| 197 |  |  |  |  |  |  | } | 
| 198 | 110 |  |  |  |  | 300 | $keep .= $origname . GZIP_NULL_BYTE ; | 
| 199 |  |  |  |  |  |  |  | 
| 200 |  |  |  |  |  |  | return $self->HeaderError("Non ISO 8859-1 Character found in Name") | 
| 201 | 110 | 100 | 66 |  |  | 332 | if *$self->{Strict} && $origname =~ /$GZIP_FNAME_INVALID_CHAR_RE/o ; | 
| 202 |  |  |  |  |  |  | } | 
| 203 |  |  |  |  |  |  |  | 
| 204 | 1020 |  |  |  |  | 1297 | my $comment ; | 
| 205 | 1020 | 100 |  |  |  | 1824 | if ($flag & GZIP_FLG_FCOMMENT) { | 
| 206 | 451 |  |  |  |  | 566 | $comment = ""; | 
| 207 | 451 |  |  |  |  | 492 | while (1) { | 
| 208 | 7921 | 100 |  |  |  | 12968 | $self->smartReadExact(\$buffer, 1) | 
| 209 |  |  |  |  |  |  | or return $self->TruncatedHeader("FCOMMENT"); | 
| 210 | 7914 | 100 |  |  |  | 12856 | last if $buffer eq GZIP_NULL_BYTE ; | 
| 211 | 7470 |  |  |  |  | 8780 | $comment .= $buffer | 
| 212 |  |  |  |  |  |  | } | 
| 213 | 444 |  |  |  |  | 754 | $keep .= $comment . GZIP_NULL_BYTE ; | 
| 214 |  |  |  |  |  |  |  | 
| 215 |  |  |  |  |  |  | return $self->HeaderError("Non ISO 8859-1 Character found in Comment") | 
| 216 | 444 | 100 | 100 |  |  | 1925 | if *$self->{Strict} && $comment =~ /$GZIP_FCOMMENT_INVALID_CHAR_RE/o ; | 
| 217 |  |  |  |  |  |  | } | 
| 218 |  |  |  |  |  |  |  | 
| 219 | 1012 | 100 |  |  |  | 1977 | if ($flag & GZIP_FLG_FHCRC) { | 
| 220 | 446 | 100 |  |  |  | 875 | $self->smartReadExact(\$buffer, GZIP_FHCRC_SIZE) | 
| 221 |  |  |  |  |  |  | or return $self->TruncatedHeader("FHCRC"); | 
| 222 |  |  |  |  |  |  |  | 
| 223 | 444 |  |  |  |  | 872 | $HeaderCRC = unpack("v", $buffer) ; | 
| 224 | 444 |  |  |  |  | 1406 | my $crc16 = Compress::Raw::Zlib::crc32($keep) & 0xFF ; | 
| 225 |  |  |  |  |  |  |  | 
| 226 |  |  |  |  |  |  | return $self->HeaderError("CRC16 mismatch.") | 
| 227 | 444 | 100 | 100 |  |  | 1206 | if *$self->{Strict} && $crc16 != $HeaderCRC; | 
| 228 |  |  |  |  |  |  |  | 
| 229 | 443 |  |  |  |  | 613 | $keep .= $buffer ; | 
| 230 |  |  |  |  |  |  | } | 
| 231 |  |  |  |  |  |  |  | 
| 232 |  |  |  |  |  |  | # Assume compression method is deflated for xfl tests | 
| 233 |  |  |  |  |  |  | #if ($xfl) { | 
| 234 |  |  |  |  |  |  | #} | 
| 235 |  |  |  |  |  |  |  | 
| 236 | 1009 |  |  |  |  | 1658 | *$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 |  |  |  | 18936 | ? $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__ |