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   98706 use strict ;
  33         73  
  33         1262  
6 33     33   188 use warnings;
  33         53  
  33         1864  
7 33     33   6276 use bytes;
  33         5745  
  33         207  
8              
9             require Exporter ;
10              
11 33     33   20926 use IO::Compress::RawDeflate 2.220 () ;
  33         923  
  33         1511  
12 33     33   205 use IO::Compress::Adapter::Deflate 2.220 ;
  33         367  
  33         7286  
13              
14 33     33   229 use IO::Compress::Base::Common 2.220 qw(:Status );
  33         522  
  33         4857  
15 33     33   11641 use IO::Compress::Gzip::Constants 2.220 ;
  33         644  
  33         7293  
16 33     33   35698 use IO::Compress::Zlib::Extra 2.220 ;
  33         632  
  33         2530  
17              
18             BEGIN
19             {
20 33 50   33   192 if (defined &utf8::downgrade )
21 33         31336 { *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.220';
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 675423 my $class = shift ;
41              
42 315         1335 my $obj = IO::Compress::Base::Common::createSelfTiedObject($class, \$GzipError);
43              
44 315         1419 $obj->_create(undef, @_);
45             }
46              
47              
48             sub gzip
49             {
50 162     162 1 9538883 my $obj = IO::Compress::Base::Common::createSelfTiedObject(undef, \$GzipError);
51 162         749 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 819 my $self = shift ;
64              
65             return (
66             # zlib behaviour
67 476         2054 $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 783 my $self = shift ;
87 472         694 my $got = shift ;
88              
89             # gzip always needs crc32
90 472         1538 $got->setValue('crc32' => 1);
91              
92 472 100       1351 return 1
93             if $got->getValue('merge') ;
94              
95 445         1157 my $strict = $got->getValue('strict') ;
96              
97              
98             {
99 445 100       735 if (! $got->parsed('time') ) {
  445         1120  
100             # Modification time defaults to now.
101 379         995 $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     1122 if ($got->parsed('name') && defined $got->getValue('name')) {
107 80         193 my $name = $got->getValue('name');
108              
109 80 100 100     425 return $self->saveErrorString(undef, "Null Character found in Name",
110             Z_DATA_ERROR)
111             if $strict && $name =~ /\x00/ ;
112              
113 78 100 100     548 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     1014 if ($got->parsed('comment') && defined $got->getValue('comment')) {
119 38         92 my $comment = $got->getValue('comment');
120              
121 38 100 100     303 return $self->saveErrorString(undef, "Null Character found in Comment",
122             Z_DATA_ERROR)
123             if $strict && $comment =~ /\x00/ ;
124              
125 36 100 100     276 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       1056 if ($got->parsed('os_code') ) {
131 6         15 my $value = $got->getValue('os_code');
132              
133 6 100 66     34 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         1774 $got->setValue('method' => Z_DEFLATED) ;
140              
141 438 100       957 if ( ! $got->parsed('extraflags')) {
142 437 100       1013 $got->setValue('extraflags' => 2)
143             if $got->getValue('level') == Z_BEST_COMPRESSION ;
144 437 100       4349 $got->setValue('extraflags' => 4)
145             if $got->getValue('level') == Z_BEST_SPEED ;
146             }
147              
148 438         2351 my $data = $got->getValue('extrafield') ;
149 438 100       1220 if (defined $data) {
150 82         308 my $bad = IO::Compress::Zlib::Extra::parseExtraField($data, $strict, 1) ;
151 82 100       210 return $self->saveErrorString(undef, "Error with ExtraField Parameter: $bad", Z_DATA_ERROR)
152             if $bad ;
153              
154 62         152 $got->setValue('extrafield' => $data) ;
155             }
156             }
157              
158 418         1248 return 1;
159             }
160              
161             sub mkTrailer
162             {
163 440     440 0 744 my $self = shift ;
164             return pack("V V", *$self->{Compress}->crc32(),
165 440         1909 *$self->{UnCompSize}->get32bit());
166             }
167              
168             sub getInverseClass
169             {
170 33     33   264 no warnings 'once';
  33         100  
  33         22243  
171 23     23 0 74 return ('IO::Uncompress::Gunzip',
172             \$IO::Uncompress::Gunzip::GunzipError);
173             }
174              
175             sub getFileInfo
176             {
177 110     110 0 210 my $self = shift ;
178 110         182 my $params = shift;
179 110         181 my $filename = shift ;
180              
181 110 100       223 return if IO::Compress::Base::Common::isaScalar($filename);
182              
183 66         1464 my $defaultTime = (stat($filename))[9] ;
184              
185 66 100       300 $params->setValue('name' => $filename)
186             if ! $params->parsed('name') ;
187              
188 66 100       141 $params->setValue('time' => $defaultTime)
189             if ! $params->parsed('time') ;
190             }
191              
192              
193             sub mkHeader
194             {
195 420     420 0 725 my $self = shift ;
196 420         780 my $param = shift ;
197              
198             # short-circuit if a minimal header is requested.
199 420 100       1254 return GZIP_MINIMUM_HEADER if $param->getValue('minimal') ;
200              
201             # METHOD
202 383         1358 my $method = $param->valueOrDefault('method', GZIP_CM_DEFLATED) ;
203              
204             # FLAGS
205 383         707 my $flags = GZIP_FLG_DEFAULT ;
206 383 100       846 $flags |= GZIP_FLG_FTEXT if $param->getValue('textflag') ;
207 383 100       934 $flags |= GZIP_FLG_FHCRC if $param->getValue('headercrc') ;
208 383 100       1092 $flags |= GZIP_FLG_FEXTRA if $param->wantValue('extrafield') ;
209 383 100       989 $flags |= GZIP_FLG_FNAME if $param->wantValue('name') ;
210 383 100       941 $flags |= GZIP_FLG_FCOMMENT if $param->wantValue('comment') ;
211              
212             # MTIME
213 383         907 my $time = $param->valueOrDefault('time', GZIP_MTIME_DEFAULT) ;
214              
215             # EXTRA FLAGS
216 383         902 my $extra_flags = $param->valueOrDefault('extraflags', GZIP_XFL_DEFAULT);
217              
218             # OS CODE
219 383         920 my $os_code = $param->valueOrDefault('os_code', GZIP_OS_DEFAULT) ;
220              
221              
222 383         1961 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       1131 if ($flags & GZIP_FLG_FEXTRA) {
234 62         133 my $extra = $param->getValue('extrafield') ;
235 62         363 $out .= pack("v", length $extra) . $extra ;
236             }
237              
238             # NAME
239 383 100       1075 if ($flags & GZIP_FLG_FNAME) {
240 86         207 my $name .= $param->getValue('name') ;
241 86         245 $name =~ s/\x00.*$//;
242 86         254 $out .= $name ;
243             # Terminate the filename with NULL unless it already is
244 86 50 66     531 $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       1015 if ($flags & GZIP_FLG_FCOMMENT) {
251 53         119 my $comment .= $param->getValue('comment') ;
252 53         139 $comment =~ s/\x00.*$//;
253 53         119 $out .= $comment ;
254             # Terminate the comment with NULL unless it already is
255 53 50 66     312 $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       1038 $out .= pack("v", Compress::Raw::Zlib::crc32($out) & 0x00FF )
262             if $param->getValue('headercrc') ;
263              
264 383         1465 noUTF8($out);
265              
266 383         1657 return $out ;
267             }
268              
269             sub mkFinalTrailer
270             {
271 413     413 0 1174 return '';
272             }
273              
274             1;
275              
276             __END__