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   70183 use Carp ;
  15         30  
  15         1422  
7 15     15   6431 use IO::Handle ;
  15         73965  
  15         930  
8 15     15   150 use Scalar::Util qw(dualvar);
  15         28  
  15         1366  
9              
10 15     15   5851 use IO::Compress::Base::Common 2.220 ;
  15         314  
  15         2558  
11 15     15   6895 use Compress::Raw::Zlib 2.218 ;
  15         56195  
  15         3912  
12 15     15   9794 use IO::Compress::Gzip 2.220 ;
  15         352  
  15         956  
13 15     15   6220 use IO::Uncompress::Gunzip 2.220 ;
  15         309  
  15         840  
14              
15 15     15   97 use strict ;
  15         31  
  15         471  
16 15     15   74 use warnings ;
  15         27  
  15         717  
17 15     15   93 use bytes ;
  15         24  
  15         86  
18             our ($VERSION, $XS_VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
19              
20             $VERSION = '2.220';
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   3210 *zlib_version = \&Compress::Raw::Zlib::zlib_version;
46             }
47              
48 15     15   99 use constant FLAG_APPEND => 1 ;
  15         28  
  15         1266  
49 15     15   92 use constant FLAG_CRC => 2 ;
  15         40  
  15         817  
50 15     15   81 use constant FLAG_ADLER => 4 ;
  15         30  
  15         869  
51 15     15   146 use constant FLAG_CONSUME_INPUT => 8 ;
  15         29  
  15         46432  
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   961 my $value = shift ;
71              
72 455 100 33     1263 if ($value == 0) {
    50          
73 368         688 $Compress::Zlib::gzerrno = 0 ;
74             }
75             elsif ($value == Z_ERRNO() || $value > 2) {
76 0         0 $Compress::Zlib::gzerrno = $! ;
77             }
78             else {
79 87         961 $Compress::Zlib::gzerrno = dualvar($value+0, $my_z_errmsg[2 - $value]);
80             }
81              
82 455         812 return $value ;
83             }
84              
85             sub _set_gzerr_undef
86             {
87 30     30   201 _set_gzerr(@_);
88 30         150 return undef;
89             }
90              
91             sub _save_gzerr
92             {
93 285     285   443 my $gz = shift ;
94 285         403 my $test_eof = shift ;
95              
96 285   100     791 my $value = $gz->errorNo() || 0 ;
97 285         677 my $eof = $gz->eof() ;
98              
99 285 100       695 if ($test_eof) {
100             # gzread uses Z_STREAM_END to denote a successful end
101 78 100 100     174 $value = Z_STREAM_END() if $gz->eof() && $value == 0 ;
102             }
103              
104 285         657 _set_gzerr($value) ;
105             }
106              
107             sub gzopen($$)
108             {
109 78     78 1 589947 my ($file, $mode) = @_ ;
110              
111 78         147 my $gz ;
112 78         317 my %defOpts = (Level => Z_DEFAULT_COMPRESSION(),
113             Strategy => Z_DEFAULT_STRATEGY(),
114             );
115              
116 78         919 my $writing ;
117 78         451 $writing = ! ($mode =~ /r/i) ;
118 78         223 $writing = ($mode =~ /[wa]/i) ;
119              
120 78 100       446 $defOpts{Level} = $1 if $mode =~ /(\d)/;
121 78 100       254 $defOpts{Strategy} = Z_FILTERED() if $mode =~ /f/i;
122 78 100       280 $defOpts{Strategy} = Z_HUFFMAN_ONLY() if $mode =~ /h/i;
123 78 100       267 $defOpts{Append} = 1 if $mode =~ /a/i;
124              
125 78 100       232 my $infDef = $writing ? 'deflate' : 'inflate';
126 78         151 my @params = () ;
127              
128 78 50 100     311 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       323 return undef unless $mode =~ /[rwa]/i ;
133              
134 76         221 _set_gzerr(0) ;
135              
136 76 100       167 if ($writing) {
137 34 50       319 $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       357 $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       182 if ! defined $gz ;
153              
154 76         854 bless [$gz, $infDef], 'Compress::Zlib::gzFile';
155             }
156              
157             sub Compress::Zlib::gzFile::gzread
158             {
159 42     42   2070 my $self = shift ;
160              
161 42 100       163 return _set_gzerr(Z_STREAM_ERROR())
162             if $self->[1] ne 'inflate';
163              
164 41 100       114 my $len = defined $_[1] ? $_[1] : 4096 ;
165              
166 41         75 my $gz = $self->[0] ;
167 41 100 100     116 if ($self->gzeof() || $len == 0) {
168             # Zap the output buffer to match ver 1 behaviour.
169 13         33 $_[0] = "" ;
170 13         39 _save_gzerr($gz, 1);
171 13         61 return 0 ;
172             }
173              
174 28         104 my $status = $gz->read($_[0], $len) ;
175 28         85 _save_gzerr($gz, 1);
176 28         202 return $status ;
177             }
178              
179             sub Compress::Zlib::gzFile::gzreadline
180             {
181 37     37   630 my $self = shift ;
182              
183 37         60 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         52 local $/ = "\n" ;
  37         124  
188 37         120 $_[0] = $gz->getline() ;
189             }
190 37         99 _save_gzerr($gz, 1);
191 37 100       175 return defined $_[0] ? length $_[0] : 0 ;
192             }
193              
194             sub Compress::Zlib::gzFile::gzwrite
195             {
196 38     38   1544 my $self = shift ;
197 38         86 my $gz = $self->[0] ;
198              
199 38 100       148 return _set_gzerr(Z_STREAM_ERROR())
200             if $self->[1] ne 'deflate';
201              
202 37 50 66     326 $] >= 5.008 and (utf8::downgrade($_[0], 1)
203             or croak "Wide character in gzwrite");
204              
205 36         317 my $status = $gz->write($_[0]) ;
206 36         119 _save_gzerr($gz);
207 36         191 return $status ;
208             }
209              
210             sub Compress::Zlib::gzFile::gztell
211             {
212 16     16   35 my $self = shift ;
213 16         30 my $gz = $self->[0] ;
214 16         80 my $status = $gz->tell() ;
215 16         44 _save_gzerr($gz);
216 16         82 return $status ;
217             }
218              
219             sub Compress::Zlib::gzFile::gzseek
220             {
221 11     11   1055 my $self = shift ;
222 11         20 my $offset = shift ;
223 11         17 my $whence = shift ;
224              
225 11         21 my $gz = $self->[0] ;
226 11         13 my $status ;
227 11         17 eval { local $SIG{__DIE__}; $status = $gz->seek($offset, $whence) ; };
  11         53  
  11         54  
228 11 100       39 if ($@)
229             {
230 5         10 my $error = $@;
231 5         32 $error =~ s/^.*: /gzseek: /;
232 5         32 $error =~ s/ at .* line \d+\s*$//;
233 5         650 croak $error;
234             }
235 6         17 _save_gzerr($gz);
236 6         37 return $status ;
237             }
238              
239             sub Compress::Zlib::gzFile::gzflush
240             {
241 7     7   1482 my $self = shift ;
242 7         16 my $f = shift ;
243              
244 7         15 my $gz = $self->[0] ;
245 7         55 my $status = $gz->flush($f) ;
246 7         26 my $err = _save_gzerr($gz);
247 7 100       45 return $status ? 0 : $err;
248             }
249              
250             sub Compress::Zlib::gzFile::gzclose
251             {
252 66     66   1013 my $self = shift ;
253 66         183 my $gz = $self->[0] ;
254              
255 66         330 my $status = $gz->close() ;
256 66         193 my $err = _save_gzerr($gz);
257 66 50       461 return $status ? 0 : $err;
258             }
259              
260             sub Compress::Zlib::gzFile::gzeof
261             {
262 76     76   1872 my $self = shift ;
263 76         120 my $gz = $self->[0] ;
264              
265 76 100       235 return 0
266             if $self->[1] ne 'inflate';
267              
268 75         309 my $status = $gz->eof() ;
269 75         224 _save_gzerr($gz);
270 75         380 return $status ;
271             }
272              
273             sub Compress::Zlib::gzFile::gzsetparams
274             {
275 3     3   243 my $self = shift ;
276 3 100       217 croak "Usage: Compress::Zlib::gzFile::gzsetparams(file, level, strategy)"
277             unless @_ eq 2 ;
278              
279 2         2 my $gz = $self->[0] ;
280 2         5 my $level = shift ;
281 2         3 my $strategy = shift;
282              
283 2 100       9 return _set_gzerr(Z_STREAM_ERROR())
284             if $self->[1] ne 'deflate';
285              
286 1         5 my $status = *$gz->{Compress}->deflateParams(-Level => $level,
287             -Strategy => $strategy);
288 1         4 _save_gzerr($gz);
289 1         2 return $status ;
290             }
291              
292             sub Compress::Zlib::gzFile::gzerror
293             {
294 4     4   15 my $self = shift ;
295 4         8 my $gz = $self->[0] ;
296              
297 4         18 return $Compress::Zlib::gzerrno ;
298             }
299              
300              
301             sub compress($;$)
302             {
303 10     10 1 302324 my ($x, $output, $err, $in) =('', '', '', '') ;
304              
305 10 100       37 if (ref $_[0] ) {
306 3         8 $in = $_[0] ;
307 3 100       318 croak "not a scalar reference" unless ref $in eq 'SCALAR' ;
308             }
309             else {
310 7         18 $in = \$_[0] ;
311             }
312              
313 9 50 66     146 $] >= 5.008 and (utf8::downgrade($$in, 1)
314             or croak "Wide character in compress");
315              
316 8 100       127 my $level = (@_ == 2 ? $_[1] : Z_DEFAULT_COMPRESSION() );
317              
318 8 100       40 $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         1998 $err = $x->deflate($in, $output) ;
329 7 50       37 return undef unless $err == Z_OK() ;
330              
331 7         406 $err = $x->flush($output) ;
332 7 50       28 return undef unless $err == Z_OK() ;
333              
334 7         503 return $output ;
335             }
336              
337             sub uncompress($)
338             {
339 10     10 1 3745 my ($output, $in) =('', '') ;
340              
341 10 100       29 if (ref $_[0] ) {
342 4         9 $in = $_[0] ;
343 4 100       210 croak "not a scalar reference" unless ref $in eq 'SCALAR' ;
344             }
345             else {
346 6         16 $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         32 my ($obj, $status) = Compress::Raw::Zlib::_inflateInit(0,
353             MAX_WBITS, 4096, "") ;
354              
355 8 50       154 $status == Z_OK
356             or return undef;
357              
358 8 100       148 $obj->inflate($in, $output) == Z_STREAM_END
359             or return undef;
360              
361 7         131 return $output;
362             }
363              
364             sub deflateInit(@)
365             {
366 19     19 1 13649 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       113 croak "Compress::Zlib::deflateInit: Bufsize must be >= 1, you specified " .
378             $got->getValue('bufsize')
379             unless $got->getValue('bufsize') >= 1;
380              
381 14         29 my $obj ;
382              
383 14         27 my $status = 0 ;
384 14         48 ($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       105 my $x = ($status == Z_OK() ? bless $obj, "Zlib::OldDeflate" : undef) ;
395 14 100       430 return wantarray ? ($x, $status) : $x ;
396             }
397              
398             sub inflateInit(@)
399             {
400 17     17 1 32273 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       88 croak "Compress::Zlib::inflateInit: Bufsize must be >= 1, you specified " .
409             $got->getValue('bufsize')
410             unless $got->getValue('bufsize') >= 1;
411              
412 12         46 my $status = 0 ;
413 12         26 my $obj ;
414 12         38 ($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       71 my $x = ($status == Z_OK() ? bless $obj, "Zlib::OldInflate" : undef) ;
420              
421 12 100       244 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   9415 my $self = shift ;
433 91         174 my $output ;
434              
435 91         3445 my $status = $self->SUPER::deflate($_[0], $output) ;
436 91 100       454 wantarray ? ($output, $status) : $output ;
437             }
438              
439             sub flush
440             {
441 17     17   5530 my $self = shift ;
442 17         45 my $output ;
443 17   66     105 my $flag = shift || Compress::Zlib::Z_FINISH();
444 17         1013 my $status = $self->SUPER::flush($output, $flag) ;
445              
446 17 100       141 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   7975 my $self = shift ;
457 151         227 my $output ;
458 151         2955 my $status = $self->SUPER::inflate($_[0], $output) ;
459 151 100       913 wantarray ? ($output, $status) : $output ;
460             }
461              
462             package Compress::Zlib ;
463              
464 15     15   162 use IO::Compress::Gzip::Constants 2.220 ;
  15         276  
  15         18762  
465              
466             sub memGzip($)
467             {
468 6     6 1 173403 _set_gzerr(0);
469 6 50       32 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       700 my $string = (ref $_[0] ? $_[0] : \$_[0]) ;
481              
482 6 50 66     242 $] >= 5.008 and (utf8::downgrade($$string, 1)
483             or croak "Wide character in memGzip");
484              
485 5         10 my $out;
486             my $status ;
487              
488 5 50       966 $x->deflate($string, $out) == Z_OK
489             or return undef ;
490              
491 5 50       325 $x->flush($out) == Z_OK
492             or return undef ;
493              
494 5         197 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   85 my $string = shift ;
503              
504 54 100       158 return Z_DATA_ERROR()
505             if length($$string) < GZIP_MIN_HEADER_SIZE ;
506              
507 53         377 my ($magic1, $magic2, $method, $flags, $time, $xflags, $oscode) =
508             unpack ('CCCCVCC', $$string);
509              
510 53 100 100     383 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         361 substr($$string, 0, GZIP_MIN_HEADER_SIZE) = '' ;
514              
515             # skip extra field
516 44 100       121 if ($flags & GZIP_FLG_FEXTRA)
517             {
518 4 100       20 return Z_DATA_ERROR()
519             if length($$string) < GZIP_FEXTRA_HEADER_SIZE ;
520              
521 3         11 my ($extra_len) = unpack ('v', $$string);
522 3         8 $extra_len += GZIP_FEXTRA_HEADER_SIZE;
523 3 100       17 return Z_DATA_ERROR()
524             if length($$string) < $extra_len ;
525              
526 1         4 substr($$string, 0, $extra_len) = '';
527             }
528              
529             # skip orig name
530 41 100       206 if ($flags & GZIP_FLG_FNAME)
531             {
532 5         15 my $name_end = index ($$string, GZIP_NULL_BYTE);
533 5 100       28 return Z_DATA_ERROR()
534             if $name_end == -1 ;
535 1         4 substr($$string, 0, $name_end + 1) = '';
536             }
537              
538             # skip comment
539 37 100       95 if ($flags & GZIP_FLG_FCOMMENT)
540             {
541 8         26 my $comment_end = index ($$string, GZIP_NULL_BYTE);
542 8 100       44 return Z_DATA_ERROR()
543             if $comment_end == -1 ;
544 1         4 substr($$string, 0, $comment_end + 1) = '';
545             }
546              
547             # skip header crc
548 30 100       80 if ($flags & GZIP_FLG_FHCRC)
549             {
550 3 100       20 return Z_DATA_ERROR()
551             if length ($$string) < GZIP_FHCRC_SIZE ;
552 1         3 substr($$string, 0, GZIP_FHCRC_SIZE) = '';
553             }
554              
555 28         84 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 18707 my $string = (ref $_[0] ? $_[0] : \$_[0]);
569              
570 55 50 66     408 $] >= 5.008 and (utf8::downgrade($$string, 1)
571             or croak "Wide character in memGunzip");
572              
573 54         223 _set_gzerr(0);
574              
575 54         185 my $status = _removeGzipHeader($string) ;
576 54 100       334 $status == Z_OK()
577             or return _set_gzerr_undef($status);
578              
579 28 100       133 my $bufsize = length $$string > 4096 ? length $$string : 4096 ;
580 28 50       70 my $x = Compress::Raw::Zlib::_inflateInit(FLAG_CRC | FLAG_CONSUME_INPUT,
581             -MAX_WBITS(), $bufsize, '')
582             or return _ret_gun_error();
583              
584 28         454 my $output = '' ;
585 28         436 $status = $x->inflate($string, $output);
586              
587 28 100       75 if ( $status == Z_OK() )
588             {
589 1         12 _set_gzerr(Z_DATA_ERROR());
590 1         6 return undef;
591             }
592              
593 27 50       151 return _ret_gun_error()
594             if ($status != Z_STREAM_END());
595              
596 27 100       151 if (length $$string >= 8)
597             {
598 11         48 my ($crc, $len) = unpack ("VV", substr($$string, 0, 8));
599 11         31 substr($$string, 0, 8) = '';
600 11 100 100     155 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         32 $$string = '';
607             }
608              
609 23         163 return $output;
610             }
611              
612             # Autoload methods go after __END__, and are processed by the autosplit program.
613              
614             1;
615             __END__