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   53135 use Carp ;
  7         21  
  7         374  
7 7     7   890 use IO::Handle ;
  7         11049  
  7         287  
8 7     7   36 use Scalar::Util qw(dualvar);
  7         13  
  7         359  
9              
10 7     7   882 use IO::Compress::Base::Common 2.204 ;
  7         104  
  7         931  
11 7     7   531 use Compress::Raw::Zlib 2.204 ;
  7         3985  
  7         1173  
12 7     7   3134 use IO::Compress::Gzip 2.204 ;
  7         116  
  7         289  
13 7     7   964 use IO::Uncompress::Gunzip 2.204 ;
  7         89  
  7         211  
14              
15 7     7   33 use strict ;
  7         19  
  7         121  
16 7     7   26 use warnings ;
  7         9  
  7         174  
17 7     7   35 use bytes ;
  7         9  
  7         24  
18             our ($VERSION, $XS_VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
19              
20             $VERSION = '2.204';
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   1031 *zlib_version = \&Compress::Raw::Zlib::zlib_version;
46             }
47              
48 7     7   37 use constant FLAG_APPEND => 1 ;
  7         11  
  7         392  
49 7     7   32 use constant FLAG_CRC => 2 ;
  7         11  
  7         293  
50 7     7   32 use constant FLAG_ADLER => 4 ;
  7         12  
  7         276  
51 7     7   35 use constant FLAG_CONSUME_INPUT => 8 ;
  7         20  
  7         13746  
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   603 my $value = shift ;
71              
72 401 100 33     695 if ($value == 0) {
    50          
73 326         423 $Compress::Zlib::gzerrno = 0 ;
74             }
75             elsif ($value == Z_ERRNO() || $value > 2) {
76 0         0 $Compress::Zlib::gzerrno = $! ;
77             }
78             else {
79 75         550 $Compress::Zlib::gzerrno = dualvar($value+0, $my_z_errmsg[2 - $value]);
80             }
81              
82 401         546 return $value ;
83             }
84              
85             sub _set_gzerr_undef
86             {
87 30     30   127 _set_gzerr(@_);
88 30         96 return undef;
89             }
90              
91             sub _save_gzerr
92             {
93 238     238   296 my $gz = shift ;
94 238         256 my $test_eof = shift ;
95              
96 238   100     450 my $value = $gz->errorNo() || 0 ;
97 238         445 my $eof = $gz->eof() ;
98              
99 238 100       389 if ($test_eof) {
100             # gzread uses Z_STREAM_END to denote a successful end
101 53 100 100     97 $value = Z_STREAM_END() if $gz->eof() && $value == 0 ;
102             }
103              
104 238         412 _set_gzerr($value) ;
105             }
106              
107             sub gzopen($$)
108             {
109 71     71 1 20867 my ($file, $mode) = @_ ;
110              
111 71         100 my $gz ;
112 71         186 my %defOpts = (Level => Z_DEFAULT_COMPRESSION(),
113             Strategy => Z_DEFAULT_STRATEGY(),
114             );
115              
116 71         365 my $writing ;
117 71         229 $writing = ! ($mode =~ /r/i) ;
118 71         166 $writing = ($mode =~ /[wa]/i) ;
119              
120 71 100       187 $defOpts{Level} = $1 if $mode =~ /(\d)/;
121 71 100       146 $defOpts{Strategy} = Z_FILTERED() if $mode =~ /f/i;
122 71 100       158 $defOpts{Strategy} = Z_HUFFMAN_ONLY() if $mode =~ /h/i;
123 71 100       142 $defOpts{Append} = 1 if $mode =~ /a/i;
124              
125 71 100       148 my $infDef = $writing ? 'deflate' : 'inflate';
126 71         101 my @params = () ;
127              
128 71 50 100     179 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       213 return undef unless $mode =~ /[rwa]/i ;
133              
134 69         145 _set_gzerr(0) ;
135              
136 69 100       95 if ($writing) {
137 33 50       193 $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       219 $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       139 if ! defined $gz ;
153              
154 69         503 bless [$gz, $infDef], 'Compress::Zlib::gzFile';
155             }
156              
157             sub Compress::Zlib::gzFile::gzread
158             {
159 34     34   1380 my $self = shift ;
160              
161 34 100       90 return _set_gzerr(Z_STREAM_ERROR())
162             if $self->[1] ne 'inflate';
163              
164 33 100       64 my $len = defined $_[1] ? $_[1] : 4096 ;
165              
166 33         42 my $gz = $self->[0] ;
167 33 100 100     63 if ($self->gzeof() || $len == 0) {
168             # Zap the output buffer to match ver 1 behaviour.
169 9         14 $_[0] = "" ;
170 9         19 _save_gzerr($gz, 1);
171 9         28 return 0 ;
172             }
173              
174 24         64 my $status = $gz->read($_[0], $len) ;
175 24         56 _save_gzerr($gz, 1);
176 24         82 return $status ;
177             }
178              
179             sub Compress::Zlib::gzFile::gzreadline
180             {
181 20     20   725 my $self = shift ;
182              
183 20         29 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         23 local $/ = "\n" ;
  20         59  
188 20         52 $_[0] = $gz->getline() ;
189             }
190 20         42 _save_gzerr($gz, 1);
191 20 100       90 return defined $_[0] ? length $_[0] : 0 ;
192             }
193              
194             sub Compress::Zlib::gzFile::gzwrite
195             {
196 31     31   1273 my $self = shift ;
197 31         46 my $gz = $self->[0] ;
198              
199 31 100       87 return _set_gzerr(Z_STREAM_ERROR())
200             if $self->[1] ne 'deflate';
201              
202 30 50 66     223 $] >= 5.008 and (utf8::downgrade($_[0], 1)
203             or croak "Wide character in gzwrite");
204              
205 29         98 my $status = $gz->write($_[0]) ;
206 29         66 _save_gzerr($gz);
207 29         103 return $status ;
208             }
209              
210             sub Compress::Zlib::gzFile::gztell
211             {
212 16     16   31 my $self = shift ;
213 16         24 my $gz = $self->[0] ;
214 16         53 my $status = $gz->tell() ;
215 16         41 _save_gzerr($gz);
216 16         63 return $status ;
217             }
218              
219             sub Compress::Zlib::gzFile::gzseek
220             {
221 11     11   1360 my $self = shift ;
222 11         15 my $offset = shift ;
223 11         12 my $whence = shift ;
224              
225 11         16 my $gz = $self->[0] ;
226 11         12 my $status ;
227 11         12 eval { local $SIG{__DIE__}; $status = $gz->seek($offset, $whence) ; };
  11         34  
  11         47  
228 11 100       175 if ($@)
229             {
230 5         9 my $error = $@;
231 5         27 $error =~ s/^.*: /gzseek: /;
232 5         55 $error =~ s/ at .* line \d+\s*$//;
233 5         309 croak $error;
234             }
235 6         13 _save_gzerr($gz);
236 6         19 return $status ;
237             }
238              
239             sub Compress::Zlib::gzFile::gzflush
240             {
241 7     7   928 my $self = shift ;
242 7         10 my $f = shift ;
243              
244 7         15 my $gz = $self->[0] ;
245 7         39 my $status = $gz->flush($f) ;
246 7         17 my $err = _save_gzerr($gz);
247 7 100       47 return $status ? 0 : $err;
248             }
249              
250             sub Compress::Zlib::gzFile::gzclose
251             {
252 59     59   850 my $self = shift ;
253 59         95 my $gz = $self->[0] ;
254              
255 59         180 my $status = $gz->close() ;
256 59         122 my $err = _save_gzerr($gz);
257 59 50       232 return $status ? 0 : $err;
258             }
259              
260             sub Compress::Zlib::gzFile::gzeof
261             {
262 68     68   2784 my $self = shift ;
263 68         105 my $gz = $self->[0] ;
264              
265 68 100       146 return 0
266             if $self->[1] ne 'inflate';
267              
268 67         177 my $status = $gz->eof() ;
269 67         154 _save_gzerr($gz);
270 67         223 return $status ;
271             }
272              
273             sub Compress::Zlib::gzFile::gzsetparams
274             {
275 3     3   337 my $self = shift ;
276 3 100       172 croak "Usage: Compress::Zlib::gzFile::gzsetparams(file, level, strategy)"
277             unless @_ eq 2 ;
278              
279 2         5 my $gz = $self->[0] ;
280 2         3 my $level = shift ;
281 2         2 my $strategy = shift;
282              
283 2 100       11 return _set_gzerr(Z_STREAM_ERROR())
284             if $self->[1] ne 'deflate';
285              
286 1         6 my $status = *$gz->{Compress}->deflateParams(-Level => $level,
287             -Strategy => $strategy);
288 1         3 _save_gzerr($gz);
289 1         3 return $status ;
290             }
291              
292             sub Compress::Zlib::gzFile::gzerror
293             {
294 4     4   12 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 6937 my ($x, $output, $err, $in) =('', '', '', '') ;
304              
305 10 100       25 if (ref $_[0] ) {
306 3         5 $in = $_[0] ;
307 3 100       167 croak "not a scalar reference" unless ref $in eq 'SCALAR' ;
308             }
309             else {
310 7         12 $in = \$_[0] ;
311             }
312              
313 9 50 66     123 $] >= 5.008 and (utf8::downgrade($$in, 1)
314             or croak "Wide character in compress");
315              
316 8 100       27 my $level = (@_ == 2 ? $_[1] : Z_DEFAULT_COMPRESSION() );
317              
318 8 100       26 $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         996 $err = $x->deflate($in, $output) ;
329 7 50       25 return undef unless $err == Z_OK() ;
330              
331 7         207 $err = $x->flush($output) ;
332 7 50       23 return undef unless $err == Z_OK() ;
333              
334 7         172 return $output ;
335             }
336              
337             sub uncompress($)
338             {
339 10     10 1 2059 my ($output, $in) =('', '') ;
340              
341 10 100       24 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         12 $in = \$_[0] ;
347             }
348              
349 9 50 66     129 $] >= 5.008 and (utf8::downgrade($$in, 1)
350             or croak "Wide character in uncompress");
351              
352 8         22 my ($obj, $status) = Compress::Raw::Zlib::_inflateInit(0,
353             MAX_WBITS, 4096, "") ;
354              
355 8 50       94 $status == Z_OK
356             or return undef;
357              
358 8 100       97 $obj->inflate($in, $output) == Z_STREAM_END
359             or return undef;
360              
361 7         71 return $output;
362             }
363              
364             sub deflateInit(@)
365             {
366 17     17 1 8451 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       53 croak "Compress::Zlib::deflateInit: Bufsize must be >= 1, you specified " .
378             $got->getValue('bufsize')
379             unless $got->getValue('bufsize') >= 1;
380              
381 12         16 my $obj ;
382              
383 12         18 my $status = 0 ;
384 12         23 ($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       53 my $x = ($status == Z_OK() ? bless $obj, "Zlib::OldDeflate" : undef) ;
395 12 100       203 return wantarray ? ($x, $status) : $x ;
396             }
397              
398             sub inflateInit(@)
399             {
400 16     16 1 14938 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       41 croak "Compress::Zlib::inflateInit: Bufsize must be >= 1, you specified " .
409             $got->getValue('bufsize')
410             unless $got->getValue('bufsize') >= 1;
411              
412 11         19 my $status = 0 ;
413 11         11 my $obj ;
414 11         20 ($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       41 my $x = ($status == Z_OK() ? bless $obj, "Zlib::OldInflate" : undef) ;
420              
421 11 100       123 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   5907 my $self = shift ;
433 61         73 my $output ;
434              
435 61         2000 my $status = $self->SUPER::deflate($_[0], $output) ;
436 61 100       195 wantarray ? ($output, $status) : $output ;
437             }
438              
439             sub flush
440             {
441 15     15   2434 my $self = shift ;
442 15         21 my $output ;
443 15   66     52 my $flag = shift || Compress::Zlib::Z_FINISH();
444 15         561 my $status = $self->SUPER::flush($output, $flag) ;
445              
446 15 100       94 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   3863 my $self = shift ;
457 150         146 my $output ;
458 150         1218 my $status = $self->SUPER::inflate($_[0], $output) ;
459 150 100       459 wantarray ? ($output, $status) : $output ;
460             }
461              
462             package Compress::Zlib ;
463              
464 7     7   49 use IO::Compress::Gzip::Constants 2.204 ;
  7         117  
  7         5975  
465              
466             sub memGzip($)
467             {
468 6     6 1 19726 _set_gzerr(0);
469 6 50       23 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       810 my $string = (ref $_[0] ? $_[0] : \$_[0]) ;
481              
482 6 50 66     218 $] >= 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       495 $x->deflate($string, $out) == Z_OK
489             or return undef ;
490              
491 5 50       224 $x->flush($out) == Z_OK
492             or return undef ;
493              
494 5         190 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   59 my $string = shift ;
503              
504 54 100       97 return Z_DATA_ERROR()
505             if length($$string) < GZIP_MIN_HEADER_SIZE ;
506              
507 53         173 my ($magic1, $magic2, $method, $flags, $time, $xflags, $oscode) =
508             unpack ('CCCCVCC', $$string);
509              
510 53 100 100     254 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         232 substr($$string, 0, GZIP_MIN_HEADER_SIZE) = '' ;
514              
515             # skip extra field
516 44 100       76 if ($flags & GZIP_FLG_FEXTRA)
517             {
518 4 100       12 return Z_DATA_ERROR()
519             if length($$string) < GZIP_FEXTRA_HEADER_SIZE ;
520              
521 3         8 my ($extra_len) = unpack ('v', $$string);
522 3         5 $extra_len += GZIP_FEXTRA_HEADER_SIZE;
523 3 100       11 return Z_DATA_ERROR()
524             if length($$string) < $extra_len ;
525              
526 1         3 substr($$string, 0, $extra_len) = '';
527             }
528              
529             # skip orig name
530 41 100       66 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       65 if ($flags & GZIP_FLG_FCOMMENT)
540             {
541 8         12 my $comment_end = index ($$string, GZIP_NULL_BYTE);
542 8 100       23 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       51 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         65 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 9157 my $string = (ref $_[0] ? $_[0] : \$_[0]);
569              
570 55 50 66     308 $] >= 5.008 and (utf8::downgrade($$string, 1)
571             or croak "Wide character in memGunzip");
572              
573 54         117 _set_gzerr(0);
574              
575 54         97 my $status = _removeGzipHeader($string) ;
576 54 100       241 $status == Z_OK()
577             or return _set_gzerr_undef($status);
578              
579 28 100       94 my $bufsize = length $$string > 4096 ? length $$string : 4096 ;
580 28 50       43 my $x = Compress::Raw::Zlib::_inflateInit(FLAG_CRC | FLAG_CONSUME_INPUT,
581             -MAX_WBITS(), $bufsize, '')
582             or return _ret_gun_error();
583              
584 28         256 my $output = '' ;
585 28         276 $status = $x->inflate($string, $output);
586              
587 28 100       66 if ( $status == Z_OK() )
588             {
589 1         9 _set_gzerr(Z_DATA_ERROR());
590 1         7 return undef;
591             }
592              
593 27 50       115 return _ret_gun_error()
594             if ($status != Z_STREAM_END());
595              
596 27 100       116 if (length $$string >= 8)
597             {
598 11         35 my ($crc, $len) = unpack ("VV", substr($$string, 0, 8));
599 11         19 substr($$string, 0, 8) = '';
600 11 100 100     116 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         36 $$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__