File Coverage

blib/lib/Compress/Zlib.pm
Criterion Covered Total %
statement 254 257 98.8
branch 125 146 85.6
condition 39 50 78.0
subroutine 40 41 97.5
pod 7 7 100.0
total 465 501 92.8


line stmt bran cond sub pod time code
1              
2             package Compress::Zlib;
3              
4             require 5.006 ;
5             require Exporter;
6 7     7   66463 use Carp ;
  7         24  
  7         489  
7 7     7   1158 use IO::Handle ;
  7         14174  
  7         286  
8 7     7   64 use Scalar::Util qw(dualvar);
  7         17  
  7         483  
9              
10 7     7   1090 use IO::Compress::Base::Common 2.205 ;
  7         138  
  7         1058  
11 7     7   662 use Compress::Raw::Zlib 2.205 ;
  7         5165  
  7         1486  
12 7     7   3863 use IO::Compress::Gzip 2.205 ;
  7         145  
  7         357  
13 7     7   1145 use IO::Uncompress::Gunzip 2.205 ;
  7         108  
  7         296  
14              
15 7     7   40 use strict ;
  7         14  
  7         145  
16 7     7   33 use warnings ;
  7         12  
  7         189  
17 7     7   34 use bytes ;
  7         13  
  7         35  
18             our ($VERSION, $XS_VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
19              
20             $VERSION = '2.205';
21             $XS_VERSION = $VERSION;
22             $VERSION = eval $VERSION;
23              
24             @ISA = qw(Exporter);
25             # Items to export into callers namespace by default. Note: do not export
26             # names by default without a very good reason. Use EXPORT_OK instead.
27             # Do not simply export all your public functions/methods/constants.
28             @EXPORT = qw(
29             deflateInit inflateInit
30              
31             compress uncompress
32              
33             gzopen $gzerrno
34             );
35              
36             push @EXPORT, @Compress::Raw::Zlib::EXPORT ;
37              
38             @EXPORT_OK = qw(memGunzip memGzip zlib_version);
39             %EXPORT_TAGS = (
40             ALL => \@EXPORT
41             );
42              
43             BEGIN
44             {
45 7     7   1285 *zlib_version = \&Compress::Raw::Zlib::zlib_version;
46             }
47              
48 7     7   52 use constant FLAG_APPEND => 1 ;
  7         15  
  7         500  
49 7     7   43 use constant FLAG_CRC => 2 ;
  7         13  
  7         332  
50 7     7   40 use constant FLAG_ADLER => 4 ;
  7         14  
  7         353  
51 7     7   42 use constant FLAG_CONSUME_INPUT => 8 ;
  7         13  
  7         17118  
52              
53             our (@my_z_errmsg);
54              
55             @my_z_errmsg = (
56             "need dictionary", # Z_NEED_DICT 2
57             "stream end", # Z_STREAM_END 1
58             "", # Z_OK 0
59             "file error", # Z_ERRNO (-1)
60             "stream error", # Z_STREAM_ERROR (-2)
61             "data error", # Z_DATA_ERROR (-3)
62             "insufficient memory", # Z_MEM_ERROR (-4)
63             "buffer error", # Z_BUF_ERROR (-5)
64             "incompatible version",# Z_VERSION_ERROR(-6)
65             );
66              
67              
68             sub _set_gzerr
69             {
70 401     401   722 my $value = shift ;
71              
72 401 100 33     808 if ($value == 0) {
    50          
73 326         513 $Compress::Zlib::gzerrno = 0 ;
74             }
75             elsif ($value == Z_ERRNO() || $value > 2) {
76 0         0 $Compress::Zlib::gzerrno = $! ;
77             }
78             else {
79 75         621 $Compress::Zlib::gzerrno = dualvar($value+0, $my_z_errmsg[2 - $value]);
80             }
81              
82 401         631 return $value ;
83             }
84              
85             sub _set_gzerr_undef
86             {
87 30     30   144 _set_gzerr(@_);
88 30         95 return undef;
89             }
90              
91             sub _save_gzerr
92             {
93 238     238   358 my $gz = shift ;
94 238         321 my $test_eof = shift ;
95              
96 238   100     588 my $value = $gz->errorNo() || 0 ;
97 238         518 my $eof = $gz->eof() ;
98              
99 238 100       527 if ($test_eof) {
100             # gzread uses Z_STREAM_END to denote a successful end
101 53 100 100     111 $value = Z_STREAM_END() if $gz->eof() && $value == 0 ;
102             }
103              
104 238         474 _set_gzerr($value) ;
105             }
106              
107             sub gzopen($$)
108             {
109 71     71 1 26669 my ($file, $mode) = @_ ;
110              
111 71         121 my $gz ;
112 71         213 my %defOpts = (Level => Z_DEFAULT_COMPRESSION(),
113             Strategy => Z_DEFAULT_STRATEGY(),
114             );
115              
116 71         462 my $writing ;
117 71         286 $writing = ! ($mode =~ /r/i) ;
118 71         184 $writing = ($mode =~ /[wa]/i) ;
119              
120 71 100       223 $defOpts{Level} = $1 if $mode =~ /(\d)/;
121 71 100       182 $defOpts{Strategy} = Z_FILTERED() if $mode =~ /f/i;
122 71 100       204 $defOpts{Strategy} = Z_HUFFMAN_ONLY() if $mode =~ /h/i;
123 71 100       207 $defOpts{Append} = 1 if $mode =~ /a/i;
124              
125 71 100       181 my $infDef = $writing ? 'deflate' : 'inflate';
126 71         125 my @params = () ;
127              
128 71 50 100     201 croak "gzopen: file parameter is not a filehandle or filename"
      33        
      66        
129             unless isaFilehandle $file || isaFilename $file ||
130             (ref $file && ref $file eq 'SCALAR');
131              
132 70 100       293 return undef unless $mode =~ /[rwa]/i ;
133              
134 69         185 _set_gzerr(0) ;
135              
136 69 100       137 if ($writing) {
137 33 50       285 $gz = IO::Compress::Gzip->new($file, Minimal => 1, AutoClose => 1,
138             %defOpts)
139             or $Compress::Zlib::gzerrno = $IO::Compress::Gzip::GzipError;
140             }
141             else {
142 36 50       231 $gz = IO::Uncompress::Gunzip->new($file,
143             Transparent => 1,
144             Append => 0,
145             AutoClose => 1,
146             MultiStream => 1,
147             Strict => 0)
148             or $Compress::Zlib::gzerrno = $IO::Uncompress::Gunzip::GunzipError;
149             }
150              
151             return undef
152 69 50       153 if ! defined $gz ;
153              
154 69         645 bless [$gz, $infDef], 'Compress::Zlib::gzFile';
155             }
156              
157             sub Compress::Zlib::gzFile::gzread
158             {
159 34     34   1484 my $self = shift ;
160              
161 34 100       124 return _set_gzerr(Z_STREAM_ERROR())
162             if $self->[1] ne 'inflate';
163              
164 33 100       85 my $len = defined $_[1] ? $_[1] : 4096 ;
165              
166 33         68 my $gz = $self->[0] ;
167 33 100 100     73 if ($self->gzeof() || $len == 0) {
168             # Zap the output buffer to match ver 1 behaviour.
169 9         22 $_[0] = "" ;
170 9         25 _save_gzerr($gz, 1);
171 9         38 return 0 ;
172             }
173              
174 24         89 my $status = $gz->read($_[0], $len) ;
175 24         69 _save_gzerr($gz, 1);
176 24         133 return $status ;
177             }
178              
179             sub Compress::Zlib::gzFile::gzreadline
180             {
181 20     20   899 my $self = shift ;
182              
183 20         40 my $gz = $self->[0] ;
184             {
185             # Maintain backward compatibility with 1.x behaviour
186             # It didn't support $/, so this can't either.
187 20         26 local $/ = "\n" ;
  20         84  
188 20         73 $_[0] = $gz->getline() ;
189             }
190 20         61 _save_gzerr($gz, 1);
191 20 100       111 return defined $_[0] ? length $_[0] : 0 ;
192             }
193              
194             sub Compress::Zlib::gzFile::gzwrite
195             {
196 31     31   1478 my $self = shift ;
197 31         67 my $gz = $self->[0] ;
198              
199 31 100       101 return _set_gzerr(Z_STREAM_ERROR())
200             if $self->[1] ne 'deflate';
201              
202 30 50 66     300 $] >= 5.008 and (utf8::downgrade($_[0], 1)
203             or croak "Wide character in gzwrite");
204              
205 29         144 my $status = $gz->write($_[0]) ;
206 29         93 _save_gzerr($gz);
207 29         123 return $status ;
208             }
209              
210             sub Compress::Zlib::gzFile::gztell
211             {
212 16     16   42 my $self = shift ;
213 16         28 my $gz = $self->[0] ;
214 16         64 my $status = $gz->tell() ;
215 16         48 _save_gzerr($gz);
216 16         120 return $status ;
217             }
218              
219             sub Compress::Zlib::gzFile::gzseek
220             {
221 11     11   1763 my $self = shift ;
222 11         19 my $offset = shift ;
223 11         16 my $whence = shift ;
224              
225 11         20 my $gz = $self->[0] ;
226 11         16 my $status ;
227 11         17 eval { local $SIG{__DIE__}; $status = $gz->seek($offset, $whence) ; };
  11         46  
  11         66  
228 11 100       230 if ($@)
229             {
230 5         10 my $error = $@;
231 5         31 $error =~ s/^.*: /gzseek: /;
232 5         28 $error =~ s/ at .* line \d+\s*$//;
233 5         367 croak $error;
234             }
235 6         16 _save_gzerr($gz);
236 6         32 return $status ;
237             }
238              
239             sub Compress::Zlib::gzFile::gzflush
240             {
241 7     7   1378 my $self = shift ;
242 7         13 my $f = shift ;
243              
244 7         15 my $gz = $self->[0] ;
245 7         49 my $status = $gz->flush($f) ;
246 7         19 my $err = _save_gzerr($gz);
247 7 100       62 return $status ? 0 : $err;
248             }
249              
250             sub Compress::Zlib::gzFile::gzclose
251             {
252 59     59   1078 my $self = shift ;
253 59         119 my $gz = $self->[0] ;
254              
255 59         232 my $status = $gz->close() ;
256 59         154 my $err = _save_gzerr($gz);
257 59 50       301 return $status ? 0 : $err;
258             }
259              
260             sub Compress::Zlib::gzFile::gzeof
261             {
262 68     68   3546 my $self = shift ;
263 68         116 my $gz = $self->[0] ;
264              
265 68 100       174 return 0
266             if $self->[1] ne 'inflate';
267              
268 67         249 my $status = $gz->eof() ;
269 67         176 _save_gzerr($gz);
270 67         281 return $status ;
271             }
272              
273             sub Compress::Zlib::gzFile::gzsetparams
274             {
275 3     3   374 my $self = shift ;
276 3 100       190 croak "Usage: Compress::Zlib::gzFile::gzsetparams(file, level, strategy)"
277             unless @_ eq 2 ;
278              
279 2         6 my $gz = $self->[0] ;
280 2         3 my $level = shift ;
281 2         4 my $strategy = shift;
282              
283 2 100       11 return _set_gzerr(Z_STREAM_ERROR())
284             if $self->[1] ne 'deflate';
285              
286 1         8 my $status = *$gz->{Compress}->deflateParams(-Level => $level,
287             -Strategy => $strategy);
288 1         4 _save_gzerr($gz);
289 1         4 return $status ;
290             }
291              
292             sub Compress::Zlib::gzFile::gzerror
293             {
294 4     4   18 my $self = shift ;
295 4         7 my $gz = $self->[0] ;
296              
297 4         17 return $Compress::Zlib::gzerrno ;
298             }
299              
300              
301             sub compress($;$)
302             {
303 10     10 1 7271 my ($x, $output, $err, $in) =('', '', '', '') ;
304              
305 10 100       27 if (ref $_[0] ) {
306 3         6 $in = $_[0] ;
307 3 100       191 croak "not a scalar reference" unless ref $in eq 'SCALAR' ;
308             }
309             else {
310 7         16 $in = \$_[0] ;
311             }
312              
313 9 50 66     148 $] >= 5.008 and (utf8::downgrade($$in, 1)
314             or croak "Wide character in compress");
315              
316 8 100       28 my $level = (@_ == 2 ? $_[1] : Z_DEFAULT_COMPRESSION() );
317              
318 8 100       30 $x = Compress::Raw::Zlib::_deflateInit(FLAG_APPEND,
319             $level,
320             Z_DEFLATED,
321             MAX_WBITS,
322             MAX_MEM_LEVEL,
323             Z_DEFAULT_STRATEGY,
324             4096,
325             '')
326             or return undef ;
327              
328 7         1065 $err = $x->deflate($in, $output) ;
329 7 50       28 return undef unless $err == Z_OK() ;
330              
331 7         217 $err = $x->flush($output) ;
332 7 50       25 return undef unless $err == Z_OK() ;
333              
334 7         184 return $output ;
335             }
336              
337             sub uncompress($)
338             {
339 10     10 1 2287 my ($output, $in) =('', '') ;
340              
341 10 100       25 if (ref $_[0] ) {
342 4         5 $in = $_[0] ;
343 4 100       83 croak "not a scalar reference" unless ref $in eq 'SCALAR' ;
344             }
345             else {
346 6         14 $in = \$_[0] ;
347             }
348              
349 9 50 66     148 $] >= 5.008 and (utf8::downgrade($$in, 1)
350             or croak "Wide character in uncompress");
351              
352 8         20 my ($obj, $status) = Compress::Raw::Zlib::_inflateInit(0,
353             MAX_WBITS, 4096, "") ;
354              
355 8 50       93 $status == Z_OK
356             or return undef;
357              
358 8 100       104 $obj->inflate($in, $output) == Z_STREAM_END
359             or return undef;
360              
361 7         96 return $output;
362             }
363              
364             sub deflateInit(@)
365             {
366 17     17 1 8901 my ($got) = ParseParameters(0,
367             {
368             'bufsize' => [IO::Compress::Base::Common::Parse_unsigned, 4096],
369             'level' => [IO::Compress::Base::Common::Parse_signed, Z_DEFAULT_COMPRESSION()],
370             'method' => [IO::Compress::Base::Common::Parse_unsigned, Z_DEFLATED()],
371             'windowbits' => [IO::Compress::Base::Common::Parse_signed, MAX_WBITS()],
372             'memlevel' => [IO::Compress::Base::Common::Parse_unsigned, MAX_MEM_LEVEL()],
373             'strategy' => [IO::Compress::Base::Common::Parse_unsigned, Z_DEFAULT_STRATEGY()],
374             'dictionary' => [IO::Compress::Base::Common::Parse_any, ""],
375             }, @_ ) ;
376              
377 13 100       57 croak "Compress::Zlib::deflateInit: Bufsize must be >= 1, you specified " .
378             $got->getValue('bufsize')
379             unless $got->getValue('bufsize') >= 1;
380              
381 12         20 my $obj ;
382              
383 12         16 my $status = 0 ;
384 12         27 ($obj, $status) =
385             Compress::Raw::Zlib::_deflateInit(0,
386             $got->getValue('level'),
387             $got->getValue('method'),
388             $got->getValue('windowbits'),
389             $got->getValue('memlevel'),
390             $got->getValue('strategy'),
391             $got->getValue('bufsize'),
392             $got->getValue('dictionary')) ;
393              
394 12 50       56 my $x = ($status == Z_OK() ? bless $obj, "Zlib::OldDeflate" : undef) ;
395 12 100       191 return wantarray ? ($x, $status) : $x ;
396             }
397              
398             sub inflateInit(@)
399             {
400 16     16 1 15942 my ($got) = ParseParameters(0,
401             {
402             'bufsize' => [IO::Compress::Base::Common::Parse_unsigned, 4096],
403             'windowbits' => [IO::Compress::Base::Common::Parse_signed, MAX_WBITS()],
404             'dictionary' => [IO::Compress::Base::Common::Parse_any, ""],
405             }, @_) ;
406              
407              
408 12 100       46 croak "Compress::Zlib::inflateInit: Bufsize must be >= 1, you specified " .
409             $got->getValue('bufsize')
410             unless $got->getValue('bufsize') >= 1;
411              
412 11         20 my $status = 0 ;
413 11         12 my $obj ;
414 11         22 ($obj, $status) = Compress::Raw::Zlib::_inflateInit(FLAG_CONSUME_INPUT,
415             $got->getValue('windowbits'),
416             $got->getValue('bufsize'),
417             $got->getValue('dictionary')) ;
418              
419 11 50       42 my $x = ($status == Z_OK() ? bless $obj, "Zlib::OldInflate" : undef) ;
420              
421 11 100       132 wantarray ? ($x, $status) : $x ;
422             }
423              
424             package Zlib::OldDeflate ;
425              
426             our (@ISA);
427             @ISA = qw(Compress::Raw::Zlib::deflateStream);
428              
429              
430             sub deflate
431             {
432 61     61   6233 my $self = shift ;
433 61         64 my $output ;
434              
435 61         2167 my $status = $self->SUPER::deflate($_[0], $output) ;
436 61 100       199 wantarray ? ($output, $status) : $output ;
437             }
438              
439             sub flush
440             {
441 15     15   2470 my $self = shift ;
442 15         22 my $output ;
443 15   66     54 my $flag = shift || Compress::Zlib::Z_FINISH();
444 15         567 my $status = $self->SUPER::flush($output, $flag) ;
445              
446 15 100       98 wantarray ? ($output, $status) : $output ;
447             }
448              
449             package Zlib::OldInflate ;
450              
451             our (@ISA);
452             @ISA = qw(Compress::Raw::Zlib::inflateStream);
453              
454             sub inflate
455             {
456 150     150   3900 my $self = shift ;
457 150         159 my $output ;
458 150         1238 my $status = $self->SUPER::inflate($_[0], $output) ;
459 150 100       462 wantarray ? ($output, $status) : $output ;
460             }
461              
462             package Compress::Zlib ;
463              
464 7     7   67 use IO::Compress::Gzip::Constants 2.205 ;
  7         111  
  7         7039  
465              
466             sub memGzip($)
467             {
468 6     6 1 20183 _set_gzerr(0);
469 6 50       26 my $x = Compress::Raw::Zlib::_deflateInit(FLAG_APPEND|FLAG_CRC,
470             Z_BEST_COMPRESSION,
471             Z_DEFLATED,
472             -MAX_WBITS(),
473             MAX_MEM_LEVEL,
474             Z_DEFAULT_STRATEGY,
475             4096,
476             '')
477             or return undef ;
478              
479             # if the deflation buffer isn't a reference, make it one
480 6 100       846 my $string = (ref $_[0] ? $_[0] : \$_[0]) ;
481              
482 6 50 66     615 $] >= 5.008 and (utf8::downgrade($$string, 1)
483             or croak "Wide character in memGzip");
484              
485 5         12 my $out;
486             my $status ;
487              
488 5 50       504 $x->deflate($string, $out) == Z_OK
489             or return undef ;
490              
491 5 50       235 $x->flush($out) == Z_OK
492             or return undef ;
493              
494 5         210 return IO::Compress::Gzip::Constants::GZIP_MINIMUM_HEADER .
495             $out .
496             pack("V V", $x->crc32(), $x->total_in());
497             }
498              
499              
500             sub _removeGzipHeader($)
501             {
502 54     54   64 my $string = shift ;
503              
504 54 100       105 return Z_DATA_ERROR()
505             if length($$string) < GZIP_MIN_HEADER_SIZE ;
506              
507 53         186 my ($magic1, $magic2, $method, $flags, $time, $xflags, $oscode) =
508             unpack ('CCCCVCC', $$string);
509              
510 53 100 100     266 return Z_DATA_ERROR()
      100        
      100        
511             unless $magic1 == GZIP_ID1 and $magic2 == GZIP_ID2 and
512             $method == Z_DEFLATED() and !($flags & GZIP_FLG_RESERVED) ;
513 44         242 substr($$string, 0, GZIP_MIN_HEADER_SIZE) = '' ;
514              
515             # skip extra field
516 44 100       77 if ($flags & GZIP_FLG_FEXTRA)
517             {
518 4 100       10 return Z_DATA_ERROR()
519             if length($$string) < GZIP_FEXTRA_HEADER_SIZE ;
520              
521 3         9 my ($extra_len) = unpack ('v', $$string);
522 3         5 $extra_len += GZIP_FEXTRA_HEADER_SIZE;
523 3 100       12 return Z_DATA_ERROR()
524             if length($$string) < $extra_len ;
525              
526 1         2 substr($$string, 0, $extra_len) = '';
527             }
528              
529             # skip orig name
530 41 100       68 if ($flags & GZIP_FLG_FNAME)
531             {
532 5         11 my $name_end = index ($$string, GZIP_NULL_BYTE);
533 5 100       15 return Z_DATA_ERROR()
534             if $name_end == -1 ;
535 1         3 substr($$string, 0, $name_end + 1) = '';
536             }
537              
538             # skip comment
539 37 100       64 if ($flags & GZIP_FLG_FCOMMENT)
540             {
541 8         14 my $comment_end = index ($$string, GZIP_NULL_BYTE);
542 8 100       26 return Z_DATA_ERROR()
543             if $comment_end == -1 ;
544 1         2 substr($$string, 0, $comment_end + 1) = '';
545             }
546              
547             # skip header crc
548 30 100       54 if ($flags & GZIP_FLG_FHCRC)
549             {
550 3 100       11 return Z_DATA_ERROR()
551             if length ($$string) < GZIP_FHCRC_SIZE ;
552 1         3 substr($$string, 0, GZIP_FHCRC_SIZE) = '';
553             }
554              
555 28         59 return Z_OK();
556             }
557              
558             sub _ret_gun_error
559             {
560 0     0   0 $Compress::Zlib::gzerrno = $IO::Uncompress::Gunzip::GunzipError;
561 0         0 return undef;
562             }
563              
564              
565             sub memGunzip($)
566             {
567             # if the buffer isn't a reference, make it one
568 55 100   55 1 9323 my $string = (ref $_[0] ? $_[0] : \$_[0]);
569              
570 55 50 66     315 $] >= 5.008 and (utf8::downgrade($$string, 1)
571             or croak "Wide character in memGunzip");
572              
573 54         110 _set_gzerr(0);
574              
575 54         98 my $status = _removeGzipHeader($string) ;
576 54 100       248 $status == Z_OK()
577             or return _set_gzerr_undef($status);
578              
579 28 100       104 my $bufsize = length $$string > 4096 ? length $$string : 4096 ;
580 28 50       55 my $x = Compress::Raw::Zlib::_inflateInit(FLAG_CRC | FLAG_CONSUME_INPUT,
581             -MAX_WBITS(), $bufsize, '')
582             or return _ret_gun_error();
583              
584 28         276 my $output = '' ;
585 28         279 $status = $x->inflate($string, $output);
586              
587 28 100       64 if ( $status == Z_OK() )
588             {
589 1         13 _set_gzerr(Z_DATA_ERROR());
590 1         6 return undef;
591             }
592              
593 27 50       121 return _ret_gun_error()
594             if ($status != Z_STREAM_END());
595              
596 27 100       125 if (length $$string >= 8)
597             {
598 11         37 my ($crc, $len) = unpack ("VV", substr($$string, 0, 8));
599 11         21 substr($$string, 0, 8) = '';
600 11 100 100     119 return _set_gzerr_undef(Z_DATA_ERROR())
601             unless $len == length($output) and
602             $crc == Compress::Raw::Zlib::crc32($output);
603             }
604             else
605             {
606 16         21 $$string = '';
607             }
608              
609 23         122 return $output;
610             }
611              
612             # Autoload methods go after __END__, and are processed by the autosplit program.
613              
614             1;
615             __END__