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 15     15   56670 use Carp ;
  15         24  
  15         1014  
7 15     15   4539 use IO::Handle ;
  15         52021  
  15         703  
8 15     15   83 use Scalar::Util qw(dualvar);
  15         20  
  15         1109  
9              
10 15     15   4431 use IO::Compress::Base::Common 2.221 ;
  15         261  
  15         1712  
11 15     15   5746 use Compress::Raw::Zlib 2.218 ;
  15         40708  
  15         2913  
12 15     15   7469 use IO::Compress::Gzip 2.221 ;
  15         251  
  15         781  
13 15     15   4753 use IO::Uncompress::Gunzip 2.221 ;
  15         223  
  15         1249  
14              
15 15     15   76 use strict ;
  15         29  
  15         279  
16 15     15   42 use warnings ;
  15         30  
  15         474  
17 15     15   46 use bytes ;
  15         19  
  15         58  
18             our ($VERSION, $XS_VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
19              
20             $VERSION = '2.221';
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 15     15   2360 *zlib_version = \&Compress::Raw::Zlib::zlib_version;
46             }
47              
48 15     15   65 use constant FLAG_APPEND => 1 ;
  15         28  
  15         812  
49 15     15   54 use constant FLAG_CRC => 2 ;
  15         26  
  15         507  
50 15     15   54 use constant FLAG_ADLER => 4 ;
  15         24  
  15         487  
51 15     15   55 use constant FLAG_CONSUME_INPUT => 8 ;
  15         21  
  15         30771  
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 455     455   683 my $value = shift ;
71              
72 455 100 33     812 if ($value == 0) {
    50          
73 368         463 $Compress::Zlib::gzerrno = 0 ;
74             }
75             elsif ($value == Z_ERRNO() || $value > 2) {
76 0         0 $Compress::Zlib::gzerrno = $! ;
77             }
78             else {
79 87         715 $Compress::Zlib::gzerrno = dualvar($value+0, $my_z_errmsg[2 - $value]);
80             }
81              
82 455         586 return $value ;
83             }
84              
85             sub _set_gzerr_undef
86             {
87 30     30   162 _set_gzerr(@_);
88 30         104 return undef;
89             }
90              
91             sub _save_gzerr
92             {
93 285     285   313 my $gz = shift ;
94 285         342 my $test_eof = shift ;
95              
96 285   100     549 my $value = $gz->errorNo() || 0 ;
97 285         523 my $eof = $gz->eof() ;
98              
99 285 100       431 if ($test_eof) {
100             # gzread uses Z_STREAM_END to denote a successful end
101 78 100 100     153 $value = Z_STREAM_END() if $gz->eof() && $value == 0 ;
102             }
103              
104 285         445 _set_gzerr($value) ;
105             }
106              
107             sub gzopen($$)
108             {
109 78     78 1 420424 my ($file, $mode) = @_ ;
110              
111 78         113 my $gz ;
112 78         282 my %defOpts = (Level => Z_DEFAULT_COMPRESSION(),
113             Strategy => Z_DEFAULT_STRATEGY(),
114             );
115              
116 78         575 my $writing ;
117 78         255 $writing = ! ($mode =~ /r/i) ;
118 78         312 $writing = ($mode =~ /[wa]/i) ;
119              
120 78 100       227 $defOpts{Level} = $1 if $mode =~ /(\d)/;
121 78 100       200 $defOpts{Strategy} = Z_FILTERED() if $mode =~ /f/i;
122 78 100       186 $defOpts{Strategy} = Z_HUFFMAN_ONLY() if $mode =~ /h/i;
123 78 100       230 $defOpts{Append} = 1 if $mode =~ /a/i;
124              
125 78 100       182 my $infDef = $writing ? 'deflate' : 'inflate';
126 78         112 my @params = () ;
127              
128 78 50 100     234 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 77 100       252 return undef unless $mode =~ /[rwa]/i ;
133              
134 76         159 _set_gzerr(0) ;
135              
136 76 100       132 if ($writing) {
137 34 50       250 $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 42 50       301 $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 76 50       139 if ! defined $gz ;
153              
154 76         727 bless [$gz, $infDef], 'Compress::Zlib::gzFile';
155             }
156              
157             sub Compress::Zlib::gzFile::gzread
158             {
159 42     42   1408 my $self = shift ;
160              
161 42 100       117 return _set_gzerr(Z_STREAM_ERROR())
162             if $self->[1] ne 'inflate';
163              
164 41 100       86 my $len = defined $_[1] ? $_[1] : 4096 ;
165              
166 41         54 my $gz = $self->[0] ;
167 41 100 100     79 if ($self->gzeof() || $len == 0) {
168             # Zap the output buffer to match ver 1 behaviour.
169 13         19 $_[0] = "" ;
170 13         28 _save_gzerr($gz, 1);
171 13         39 return 0 ;
172             }
173              
174 28         80 my $status = $gz->read($_[0], $len) ;
175 28         68 _save_gzerr($gz, 1);
176 28         140 return $status ;
177             }
178              
179             sub Compress::Zlib::gzFile::gzreadline
180             {
181 37     37   366 my $self = shift ;
182              
183 37         41 my $gz = $self->[0] ;
184             {
185             # Maintain backward compatibility with 1.x behaviour
186             # It didn't support $/, so this can't either.
187 37         39 local $/ = "\n" ;
  37         82  
188 37         85 $_[0] = $gz->getline() ;
189             }
190 37         85 _save_gzerr($gz, 1);
191 37 100       106 return defined $_[0] ? length $_[0] : 0 ;
192             }
193              
194             sub Compress::Zlib::gzFile::gzwrite
195             {
196 38     38   1159 my $self = shift ;
197 38         57 my $gz = $self->[0] ;
198              
199 38 100       94 return _set_gzerr(Z_STREAM_ERROR())
200             if $self->[1] ne 'deflate';
201              
202 37 50 66     272 $] >= 5.008 and (utf8::downgrade($_[0], 1)
203             or croak "Wide character in gzwrite");
204              
205 36         162 my $status = $gz->write($_[0]) ;
206 36         88 _save_gzerr($gz);
207 36         166 return $status ;
208             }
209              
210             sub Compress::Zlib::gzFile::gztell
211             {
212 16     16   22 my $self = shift ;
213 16         25 my $gz = $self->[0] ;
214 16         55 my $status = $gz->tell() ;
215 16         39 _save_gzerr($gz);
216 16         92 return $status ;
217             }
218              
219             sub Compress::Zlib::gzFile::gzseek
220             {
221 11     11   940 my $self = shift ;
222 11         13 my $offset = shift ;
223 11         12 my $whence = shift ;
224              
225 11         17 my $gz = $self->[0] ;
226 11         12 my $status ;
227 11         12 eval { local $SIG{__DIE__}; $status = $gz->seek($offset, $whence) ; };
  11         36  
  11         60  
228 11 100       30 if ($@)
229             {
230 5         9 my $error = $@;
231 5         30 $error =~ s/^.*: /gzseek: /;
232 5         27 $error =~ s/ at .* line \d+\s*$//;
233 5         418 croak $error;
234             }
235 6         10 _save_gzerr($gz);
236 6         19 return $status ;
237             }
238              
239             sub Compress::Zlib::gzFile::gzflush
240             {
241 7     7   913 my $self = shift ;
242 7         12 my $f = shift ;
243              
244 7         10 my $gz = $self->[0] ;
245 7         41 my $status = $gz->flush($f) ;
246 7         15 my $err = _save_gzerr($gz);
247 7 100       30 return $status ? 0 : $err;
248             }
249              
250             sub Compress::Zlib::gzFile::gzclose
251             {
252 66     66   502 my $self = shift ;
253 66         94 my $gz = $self->[0] ;
254              
255 66         256 my $status = $gz->close() ;
256 66         130 my $err = _save_gzerr($gz);
257 66 50       286 return $status ? 0 : $err;
258             }
259              
260             sub Compress::Zlib::gzFile::gzeof
261             {
262 76     76   1607 my $self = shift ;
263 76         98 my $gz = $self->[0] ;
264              
265 76 100       167 return 0
266             if $self->[1] ne 'inflate';
267              
268 75         226 my $status = $gz->eof() ;
269 75         157 _save_gzerr($gz);
270 75         231 return $status ;
271             }
272              
273             sub Compress::Zlib::gzFile::gzsetparams
274             {
275 3     3   255 my $self = shift ;
276 3 100       172 croak "Usage: Compress::Zlib::gzFile::gzsetparams(file, level, strategy)"
277             unless @_ eq 2 ;
278              
279 2         3 my $gz = $self->[0] ;
280 2         4 my $level = shift ;
281 2         2 my $strategy = shift;
282              
283 2 100       9 return _set_gzerr(Z_STREAM_ERROR())
284             if $self->[1] ne 'deflate';
285              
286 1         7 my $status = *$gz->{Compress}->deflateParams(-Level => $level,
287             -Strategy => $strategy);
288 1         3 _save_gzerr($gz);
289 1         2 return $status ;
290             }
291              
292             sub Compress::Zlib::gzFile::gzerror
293             {
294 4     4   10 my $self = shift ;
295 4         195 my $gz = $self->[0] ;
296              
297 4         19 return $Compress::Zlib::gzerrno ;
298             }
299              
300              
301             sub compress($;$)
302             {
303 10     10 1 156268 my ($x, $output, $err, $in) =('', '', '', '') ;
304              
305 10 100       23 if (ref $_[0] ) {
306 3         4 $in = $_[0] ;
307 3 100       203 croak "not a scalar reference" unless ref $in eq 'SCALAR' ;
308             }
309             else {
310 7         12 $in = \$_[0] ;
311             }
312              
313 9 50 66     207 $] >= 5.008 and (utf8::downgrade($$in, 1)
314             or croak "Wide character in compress");
315              
316 8 100       24 my $level = (@_ == 2 ? $_[1] : Z_DEFAULT_COMPRESSION() );
317              
318 8 100       23 $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         739 $err = $x->deflate($in, $output) ;
329 7 50       22 return undef unless $err == Z_OK() ;
330              
331 7         194 $err = $x->flush($output) ;
332 7 50       16 return undef unless $err == Z_OK() ;
333              
334 7         308 return $output ;
335             }
336              
337             sub uncompress($)
338             {
339 10     10 1 1362 my ($output, $in) =('', '') ;
340              
341 10 100       20 if (ref $_[0] ) {
342 4         5 $in = $_[0] ;
343 4 100       82 croak "not a scalar reference" unless ref $in eq 'SCALAR' ;
344             }
345             else {
346 6         9 $in = \$_[0] ;
347             }
348              
349 9 50 66     121 $] >= 5.008 and (utf8::downgrade($$in, 1)
350             or croak "Wide character in uncompress");
351              
352 8         23 my ($obj, $status) = Compress::Raw::Zlib::_inflateInit(0,
353             MAX_WBITS, 4096, "") ;
354              
355 8 50       109 $status == Z_OK
356             or return undef;
357              
358 8 100       83 $obj->inflate($in, $output) == Z_STREAM_END
359             or return undef;
360              
361 7         86 return $output;
362             }
363              
364             sub deflateInit(@)
365             {
366 19     19 1 10988 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 15 100       71 croak "Compress::Zlib::deflateInit: Bufsize must be >= 1, you specified " .
378             $got->getValue('bufsize')
379             unless $got->getValue('bufsize') >= 1;
380              
381 14         20 my $obj ;
382              
383 14         18 my $status = 0 ;
384 14         30 ($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 14 50       72 my $x = ($status == Z_OK() ? bless $obj, "Zlib::OldDeflate" : undef) ;
395 14 100       270 return wantarray ? ($x, $status) : $x ;
396             }
397              
398             sub inflateInit(@)
399             {
400 17     17 1 21540 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 13 100       71 croak "Compress::Zlib::inflateInit: Bufsize must be >= 1, you specified " .
409             $got->getValue('bufsize')
410             unless $got->getValue('bufsize') >= 1;
411              
412 12         16 my $status = 0 ;
413 12         16 my $obj ;
414 12         24 ($obj, $status) = Compress::Raw::Zlib::_inflateInit(FLAG_CONSUME_INPUT,
415             $got->getValue('windowbits'),
416             $got->getValue('bufsize'),
417             $got->getValue('dictionary')) ;
418              
419 12 50       50 my $x = ($status == Z_OK() ? bless $obj, "Zlib::OldInflate" : undef) ;
420              
421 12 100       187 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 91     91   5193 my $self = shift ;
433 91         79 my $output ;
434              
435 91         2418 my $status = $self->SUPER::deflate($_[0], $output) ;
436 91 100       302 wantarray ? ($output, $status) : $output ;
437             }
438              
439             sub flush
440             {
441 17     17   1869 my $self = shift ;
442 17         20 my $output ;
443 17   66     71 my $flag = shift || Compress::Zlib::Z_FINISH();
444 17         685 my $status = $self->SUPER::flush($output, $flag) ;
445              
446 17 100       90 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 151     151   3183 my $self = shift ;
457 151         156 my $output ;
458 151         1596 my $status = $self->SUPER::inflate($_[0], $output) ;
459 151 100       525 wantarray ? ($output, $status) : $output ;
460             }
461              
462             package Compress::Zlib ;
463              
464 15     15   123 use IO::Compress::Gzip::Constants 2.221 ;
  15         192  
  15         13065  
465              
466             sub memGzip($)
467             {
468 6     6 1 153778 _set_gzerr(0);
469 6 50       28 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       774 my $string = (ref $_[0] ? $_[0] : \$_[0]) ;
481              
482 6 50 66     246 $] >= 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       540 $x->deflate($string, $out) == Z_OK
489             or return undef ;
490              
491 5 50       247 $x->flush($out) == Z_OK
492             or return undef ;
493              
494 5         224 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   81 my $string = shift ;
503              
504 54 100       110 return Z_DATA_ERROR()
505             if length($$string) < GZIP_MIN_HEADER_SIZE ;
506              
507 53         235 my ($magic1, $magic2, $method, $flags, $time, $xflags, $oscode) =
508             unpack ('CCCCVCC', $$string);
509              
510 53 100 100     272 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         297 substr($$string, 0, GZIP_MIN_HEADER_SIZE) = '' ;
514              
515             # skip extra field
516 44 100       79 if ($flags & GZIP_FLG_FEXTRA)
517             {
518 4 100       15 return Z_DATA_ERROR()
519             if length($$string) < GZIP_FEXTRA_HEADER_SIZE ;
520              
521 3         6 my ($extra_len) = unpack ('v', $$string);
522 3         5 $extra_len += GZIP_FEXTRA_HEADER_SIZE;
523 3 100       10 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       87 if ($flags & GZIP_FLG_FNAME)
531             {
532 5         9 my $name_end = index ($$string, GZIP_NULL_BYTE);
533 5 100       19 return Z_DATA_ERROR()
534             if $name_end == -1 ;
535 1         2 substr($$string, 0, $name_end + 1) = '';
536             }
537              
538             # skip comment
539 37 100       62 if ($flags & GZIP_FLG_FCOMMENT)
540             {
541 8         34 my $comment_end = index ($$string, GZIP_NULL_BYTE);
542 8 100       24 return Z_DATA_ERROR()
543             if $comment_end == -1 ;
544 1         1 substr($$string, 0, $comment_end + 1) = '';
545             }
546              
547             # skip header crc
548 30 100       56 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         77 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 11112 my $string = (ref $_[0] ? $_[0] : \$_[0]);
569              
570 55 50 66     302 $] >= 5.008 and (utf8::downgrade($$string, 1)
571             or croak "Wide character in memGunzip");
572              
573 54         134 _set_gzerr(0);
574              
575 54         102 my $status = _removeGzipHeader($string) ;
576 54 100       243 $status == Z_OK()
577             or return _set_gzerr_undef($status);
578              
579 28 100       113 my $bufsize = length $$string > 4096 ? length $$string : 4096 ;
580 28 50       80 my $x = Compress::Raw::Zlib::_inflateInit(FLAG_CRC | FLAG_CONSUME_INPUT,
581             -MAX_WBITS(), $bufsize, '')
582             or return _ret_gun_error();
583              
584 28         359 my $output = '' ;
585 28         321 $status = $x->inflate($string, $output);
586              
587 28 100       60 if ( $status == Z_OK() )
588             {
589 1         16 _set_gzerr(Z_DATA_ERROR());
590 1         11 return undef;
591             }
592              
593 27 50       134 return _ret_gun_error()
594             if ($status != Z_STREAM_END());
595              
596 27 100       118 if (length $$string >= 8)
597             {
598 11         33 my ($crc, $len) = unpack ("VV", substr($$string, 0, 8));
599 11         19 substr($$string, 0, 8) = '';
600 11 100 100     171 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         31 $$string = '';
607             }
608              
609 23         146 return $output;
610             }
611              
612             # Autoload methods go after __END__, and are processed by the autosplit program.
613              
614             1;
615             __END__