File Coverage

blib/lib/IO/Compress/Gzip.pm
Criterion Covered Total %
statement 106 107 99.0
branch 59 62 95.1
condition 24 27 88.8
subroutine 19 19 100.0
pod 2 9 22.2
total 210 224 93.7


line stmt bran cond sub pod time code
1             package IO::Compress::Gzip ;
2              
3             require 5.006 ;
4              
5 33     33   80444 use strict ;
  33         51  
  33         1119  
6 33     33   130 use warnings;
  33         45  
  33         1473  
7 33     33   4661 use bytes;
  33         4863  
  33         194  
8              
9             require Exporter ;
10              
11 33     33   16087 use IO::Compress::RawDeflate 2.223 () ;
  33         673  
  33         1208  
12 33     33   149 use IO::Compress::Adapter::Deflate 2.223 ;
  33         368  
  33         5737  
13              
14 33     33   206 use IO::Compress::Base::Common 2.223 qw(:Status );
  33         464  
  33         3452  
15 33     33   8822 use IO::Compress::Gzip::Constants 2.223 ;
  33         528  
  33         5603  
16 33     33   8691 use IO::Compress::Zlib::Extra 2.223 ;
  33         464  
  33         1958  
17              
18             BEGIN
19             {
20 33 50   33   159 if (defined &utf8::downgrade )
21 33         24324 { *noUTF8 = \&utf8::downgrade }
22             else
23 0         0 { *noUTF8 = sub {} }
24             }
25              
26             our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, %DEFLATE_CONSTANTS, $GzipError);
27              
28             $VERSION = '2.223';
29             $GzipError = '' ;
30              
31             @ISA = qw(IO::Compress::RawDeflate Exporter);
32             @EXPORT_OK = qw( $GzipError gzip ) ;
33             %EXPORT_TAGS = %IO::Compress::RawDeflate::DEFLATE_CONSTANTS ;
34              
35             $EXPORT_TAGS{all} = [ defined $EXPORT_TAGS{all} ? @{ $EXPORT_TAGS{all} } : (), @EXPORT_OK ] ;
36             Exporter::export_ok_tags('all');
37              
38             sub new
39             {
40 315     315 1 456145 my $class = shift ;
41              
42 315         1124 my $obj = IO::Compress::Base::Common::createSelfTiedObject($class, \$GzipError);
43              
44 315         1167 $obj->_create(undef, @_);
45             }
46              
47              
48             sub gzip
49             {
50 162     162 1 9390389 my $obj = IO::Compress::Base::Common::createSelfTiedObject(undef, \$GzipError);
51 162         564 return $obj->_def(@_);
52             }
53              
54             #sub newHeader
55             #{
56             # my $self = shift ;
57             # #return GZIP_MINIMUM_HEADER ;
58             # return $self->mkHeader(*$self->{Got});
59             #}
60              
61             sub getExtraParams
62             {
63 476     476 0 614 my $self = shift ;
64              
65             return (
66             # zlib behaviour
67 476         1485 $self->getZlibParams(),
68              
69             # Gzip header fields
70             'minimal' => [IO::Compress::Base::Common::Parse_boolean, 0],
71             'comment' => [IO::Compress::Base::Common::Parse_any, undef],
72             'name' => [IO::Compress::Base::Common::Parse_any, undef],
73             'time' => [IO::Compress::Base::Common::Parse_any, undef],
74             'textflag' => [IO::Compress::Base::Common::Parse_boolean, 0],
75             'headercrc' => [IO::Compress::Base::Common::Parse_boolean, 0],
76             'os_code' => [IO::Compress::Base::Common::Parse_unsigned, $Compress::Raw::Zlib::gzip_os_code],
77             'extrafield'=> [IO::Compress::Base::Common::Parse_any, undef],
78             'extraflags'=> [IO::Compress::Base::Common::Parse_any, undef],
79              
80             );
81             }
82              
83              
84             sub ckParams
85             {
86 472     472 0 597 my $self = shift ;
87 472         582 my $got = shift ;
88              
89             # gzip always needs crc32
90 472         1162 $got->setValue('crc32' => 1);
91              
92 472 100       787 return 1
93             if $got->getValue('merge') ;
94              
95 445         703 my $strict = $got->getValue('strict') ;
96              
97              
98             {
99 445 100       555 if (! $got->parsed('time') ) {
  445         784  
100             # Modification time defaults to now.
101 379         812 $got->setValue(time => time) ;
102             }
103              
104             # Check that the Name & Comment don't have embedded NULLs
105             # Also check that they only contain ISO 8859-1 chars.
106 445 100 100     769 if ($got->parsed('name') && defined $got->getValue('name')) {
107 80         131 my $name = $got->getValue('name');
108              
109 80 100 100     325 return $self->saveErrorString(undef, "Null Character found in Name",
110             Z_DATA_ERROR)
111             if $strict && $name =~ /\x00/ ;
112              
113 78 100 100     455 return $self->saveErrorString(undef, "Non ISO 8859-1 Character found in Name",
114             Z_DATA_ERROR)
115             if $strict && $name =~ /$GZIP_FNAME_INVALID_CHAR_RE/o ;
116             }
117              
118 442 100 100     725 if ($got->parsed('comment') && defined $got->getValue('comment')) {
119 38         70 my $comment = $got->getValue('comment');
120              
121 38 100 100     130 return $self->saveErrorString(undef, "Null Character found in Comment",
122             Z_DATA_ERROR)
123             if $strict && $comment =~ /\x00/ ;
124              
125 36 100 100     219 return $self->saveErrorString(undef, "Non ISO 8859-1 Character found in Comment",
126             Z_DATA_ERROR)
127             if $strict && $comment =~ /$GZIP_FCOMMENT_INVALID_CHAR_RE/o;
128             }
129              
130 439 100       689 if ($got->parsed('os_code') ) {
131 6         10 my $value = $got->getValue('os_code');
132              
133 6 100 66     23 return $self->saveErrorString(undef, "OS_Code must be between 0 and 255, got '$value'")
134             if $value < 0 || $value > 255 ;
135              
136             }
137              
138             # gzip only supports Deflate at present
139 438         1274 $got->setValue('method' => Z_DEFLATED) ;
140              
141 438 100       693 if ( ! $got->parsed('extraflags')) {
142 437 100       678 $got->setValue('extraflags' => 2)
143             if $got->getValue('level') == Z_BEST_COMPRESSION ;
144 437 100       1978 $got->setValue('extraflags' => 4)
145             if $got->getValue('level') == Z_BEST_SPEED ;
146             }
147              
148 438         1818 my $data = $got->getValue('extrafield') ;
149 438 100       773 if (defined $data) {
150 82         259 my $bad = IO::Compress::Zlib::Extra::parseExtraField($data, $strict, 1) ;
151 82 100       161 return $self->saveErrorString(undef, "Error with ExtraField Parameter: $bad", Z_DATA_ERROR)
152             if $bad ;
153              
154 62         111 $got->setValue('extrafield' => $data) ;
155             }
156             }
157              
158 418         982 return 1;
159             }
160              
161             sub mkTrailer
162             {
163 440     440 0 523 my $self = shift ;
164             return pack("V V", *$self->{Compress}->crc32(),
165 440         1271 *$self->{UnCompSize}->get32bit());
166             }
167              
168             sub getInverseClass
169             {
170 33     33   222 no warnings 'once';
  33         73  
  33         17731  
171 23     23 0 57 return ('IO::Uncompress::Gunzip',
172             \$IO::Uncompress::Gunzip::GunzipError);
173             }
174              
175             sub getFileInfo
176             {
177 110     110 0 171 my $self = shift ;
178 110         128 my $params = shift;
179 110         121 my $filename = shift ;
180              
181 110 100       201 return if IO::Compress::Base::Common::isaScalar($filename);
182              
183 66         980 my $defaultTime = (stat($filename))[9] ;
184              
185 66 100       182 $params->setValue('name' => $filename)
186             if ! $params->parsed('name') ;
187              
188 66 100       106 $params->setValue('time' => $defaultTime)
189             if ! $params->parsed('time') ;
190             }
191              
192              
193             sub mkHeader
194             {
195 420     420 0 634 my $self = shift ;
196 420         509 my $param = shift ;
197              
198             # short-circuit if a minimal header is requested.
199 420 100       901 return GZIP_MINIMUM_HEADER if $param->getValue('minimal') ;
200              
201             # METHOD
202 383         858 my $method = $param->valueOrDefault('method', GZIP_CM_DEFLATED) ;
203              
204             # FLAGS
205 383         499 my $flags = GZIP_FLG_DEFAULT ;
206 383 100       616 $flags |= GZIP_FLG_FTEXT if $param->getValue('textflag') ;
207 383 100       642 $flags |= GZIP_FLG_FHCRC if $param->getValue('headercrc') ;
208 383 100       705 $flags |= GZIP_FLG_FEXTRA if $param->wantValue('extrafield') ;
209 383 100       684 $flags |= GZIP_FLG_FNAME if $param->wantValue('name') ;
210 383 100       640 $flags |= GZIP_FLG_FCOMMENT if $param->wantValue('comment') ;
211              
212             # MTIME
213 383         598 my $time = $param->valueOrDefault('time', GZIP_MTIME_DEFAULT) ;
214              
215             # EXTRA FLAGS
216 383         636 my $extra_flags = $param->valueOrDefault('extraflags', GZIP_XFL_DEFAULT);
217              
218             # OS CODE
219 383         641 my $os_code = $param->valueOrDefault('os_code', GZIP_OS_DEFAULT) ;
220              
221              
222 383         1558 my $out = pack("C4 V C C",
223             GZIP_ID1, # ID1
224             GZIP_ID2, # ID2
225             $method, # Compression Method
226             $flags, # Flags
227             $time, # Modification Time
228             $extra_flags, # Extra Flags
229             $os_code, # Operating System Code
230             ) ;
231              
232             # EXTRA
233 383 100       737 if ($flags & GZIP_FLG_FEXTRA) {
234 62         113 my $extra = $param->getValue('extrafield') ;
235 62         288 $out .= pack("v", length $extra) . $extra ;
236             }
237              
238             # NAME
239 383 100       706 if ($flags & GZIP_FLG_FNAME) {
240 86         185 my $name .= $param->getValue('name') ;
241 86         174 $name =~ s/\x00.*$//;
242 86         173 $out .= $name ;
243             # Terminate the filename with NULL unless it already is
244 86 50 66     405 $out .= GZIP_NULL_BYTE
245             if !length $name or
246             substr($name, 1, -1) ne GZIP_NULL_BYTE ;
247             }
248              
249             # COMMENT
250 383 100       671 if ($flags & GZIP_FLG_FCOMMENT) {
251 53         74 my $comment .= $param->getValue('comment') ;
252 53         91 $comment =~ s/\x00.*$//;
253 53         103 $out .= $comment ;
254             # Terminate the comment with NULL unless it already is
255 53 50 66     247 $out .= GZIP_NULL_BYTE
256             if ! length $comment or
257             substr($comment, 1, -1) ne GZIP_NULL_BYTE;
258             }
259              
260             # HEADER CRC
261 383 100       633 $out .= pack("v", Compress::Raw::Zlib::crc32($out) & 0x00FF )
262             if $param->getValue('headercrc') ;
263              
264 383         975 noUTF8($out);
265              
266 383         1078 return $out ;
267             }
268              
269             sub mkFinalTrailer
270             {
271 413     413 0 775 return '';
272             }
273              
274             1;
275              
276             __END__