1package IO::Compress::Zip ; 2 3use strict ; 4use warnings; 5use bytes; 6 7use IO::Compress::Base::Common 2.106 qw(:Status ); 8use IO::Compress::RawDeflate 2.106 (); 9use IO::Compress::Adapter::Deflate 2.106 ; 10use IO::Compress::Adapter::Identity 2.106 ; 11use IO::Compress::Zlib::Extra 2.106 ; 12use IO::Compress::Zip::Constants 2.106 ; 13 14use File::Spec(); 15use Config; 16 17use Compress::Raw::Zlib 2.103 (); 18 19BEGIN 20{ 21 eval { require IO::Compress::Adapter::Bzip2 ; 22 IO::Compress::Adapter::Bzip2->import( 2.103 ); 23 require IO::Compress::Bzip2 ; 24 IO::Compress::Bzip2->import( 2.103 ); 25 } ; 26 27 eval { require IO::Compress::Adapter::Lzma ; 28 IO::Compress::Adapter::Lzma->import( 2.103 ); 29 require IO::Compress::Lzma ; 30 IO::Compress::Lzma->import( 2.103 ); 31 } ; 32 33 eval { require IO::Compress::Adapter::Xz ; 34 IO::Compress::Adapter::Xz->import( 2.103 ); 35 require IO::Compress::Xz ; 36 IO::Compress::Xz->import( 2.103 ); 37 } ; 38 eval { require IO::Compress::Adapter::Zstd ; 39 IO::Compress::Adapter::Zstd->import( 2.103 ); 40 require IO::Compress::Zstd ; 41 IO::Compress::Zstd->import( 2.103 ); 42 } ; 43} 44 45 46require Exporter ; 47 48our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, %DEFLATE_CONSTANTS, $ZipError); 49 50$VERSION = '2.106'; 51$ZipError = ''; 52 53@ISA = qw(IO::Compress::RawDeflate Exporter); 54@EXPORT_OK = qw( $ZipError zip ) ; 55%EXPORT_TAGS = %IO::Compress::RawDeflate::DEFLATE_CONSTANTS ; 56 57push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ; 58 59$EXPORT_TAGS{zip_method} = [qw( ZIP_CM_STORE ZIP_CM_DEFLATE ZIP_CM_BZIP2 ZIP_CM_LZMA ZIP_CM_XZ ZIP_CM_ZSTD)]; 60push @{ $EXPORT_TAGS{all} }, @{ $EXPORT_TAGS{zip_method} }; 61 62Exporter::export_ok_tags('all'); 63 64sub new 65{ 66 my $class = shift ; 67 68 my $obj = IO::Compress::Base::Common::createSelfTiedObject($class, \$ZipError); 69 $obj->_create(undef, @_); 70 71} 72 73sub zip 74{ 75 my $obj = IO::Compress::Base::Common::createSelfTiedObject(undef, \$ZipError); 76 return $obj->_def(@_); 77} 78 79sub isMethodAvailable 80{ 81 my $method = shift; 82 83 # Store & Deflate are always available 84 return 1 85 if $method == ZIP_CM_STORE || $method == ZIP_CM_DEFLATE ; 86 87 return 1 88 if $method == ZIP_CM_BZIP2 and 89 defined $IO::Compress::Adapter::Bzip2::VERSION; 90 91 return 1 92 if $method == ZIP_CM_LZMA and 93 defined $IO::Compress::Adapter::Lzma::VERSION; 94 95 return 1 96 if $method == ZIP_CM_XZ and 97 defined $IO::Compress::Adapter::Xz::VERSION; 98 99 return 1 100 if $method == ZIP_CM_ZSTD and 101 defined $IO::Compress::Adapter::ZSTD::VERSION; 102 103 return 0; 104} 105 106sub beforePayload 107{ 108 my $self = shift ; 109 110 if (*$self->{ZipData}{Sparse} ) { 111 my $inc = 1024 * 100 ; 112 my $NULLS = ("\x00" x $inc) ; 113 my $sparse = *$self->{ZipData}{Sparse} ; 114 *$self->{CompSize}->add( $sparse ); 115 *$self->{UnCompSize}->add( $sparse ); 116 117 *$self->{FH}->seek($sparse, IO::Handle::SEEK_CUR); 118 119 *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32($NULLS, *$self->{ZipData}{CRC32}) 120 for 1 .. int $sparse / $inc; 121 *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32(substr($NULLS, 0, $sparse % $inc), 122 *$self->{ZipData}{CRC32}) 123 if $sparse % $inc; 124 } 125} 126 127sub mkComp 128{ 129 my $self = shift ; 130 my $got = shift ; 131 132 my ($obj, $errstr, $errno) ; 133 134 if (*$self->{ZipData}{Method} == ZIP_CM_STORE) { 135 ($obj, $errstr, $errno) = IO::Compress::Adapter::Identity::mkCompObject( 136 $got->getValue('level'), 137 $got->getValue('strategy') 138 ); 139 *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32(undef); 140 } 141 elsif (*$self->{ZipData}{Method} == ZIP_CM_DEFLATE) { 142 ($obj, $errstr, $errno) = IO::Compress::Adapter::Deflate::mkCompObject( 143 $got->getValue('crc32'), 144 $got->getValue('adler32'), 145 $got->getValue('level'), 146 $got->getValue('strategy') 147 ); 148 } 149 elsif (*$self->{ZipData}{Method} == ZIP_CM_BZIP2) { 150 ($obj, $errstr, $errno) = IO::Compress::Adapter::Bzip2::mkCompObject( 151 $got->getValue('blocksize100k'), 152 $got->getValue('workfactor'), 153 $got->getValue('verbosity') 154 ); 155 *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32(undef); 156 } 157 elsif (*$self->{ZipData}{Method} == ZIP_CM_LZMA) { 158 ($obj, $errstr, $errno) = IO::Compress::Adapter::Lzma::mkRawZipCompObject($got->getValue('preset'), 159 $got->getValue('extreme'), 160 ); 161 *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32(undef); 162 } 163 elsif (*$self->{ZipData}{Method} == ZIP_CM_XZ) { 164 ($obj, $errstr, $errno) = IO::Compress::Adapter::Xz::mkCompObject($got->getValue('preset'), 165 $got->getValue('extreme'), 166 0 167 ); 168 *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32(undef); 169 } 170 elsif (*$self->{ZipData}{Method} == ZIP_CM_ZSTD) { 171 ($obj, $errstr, $errno) = IO::Compress::Adapter::Zstd::mkCompObject(defined $got->getValue('level') ? $got->getValue('level') : 3, 172 ); 173 *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32(undef); 174 } 175 176 return $self->saveErrorString(undef, $errstr, $errno) 177 if ! defined $obj; 178 179 if (! defined *$self->{ZipData}{SizesOffset}) { 180 *$self->{ZipData}{SizesOffset} = 0; 181 *$self->{ZipData}{Offset} = U64->new(); 182 } 183 184 *$self->{ZipData}{AnyZip64} = 0 185 if ! defined *$self->{ZipData}{AnyZip64} ; 186 187 return $obj; 188} 189 190sub reset 191{ 192 my $self = shift ; 193 194 *$self->{Compress}->reset(); 195 *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32(''); 196 197 return STATUS_OK; 198} 199 200sub filterUncompressed 201{ 202 my $self = shift ; 203 204 if (*$self->{ZipData}{Method} == ZIP_CM_DEFLATE) { 205 *$self->{ZipData}{CRC32} = *$self->{Compress}->crc32(); 206 } 207 else { 208 *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32(${$_[0]}, *$self->{ZipData}{CRC32}); 209 210 } 211} 212 213sub canonicalName 214{ 215 # This sub is derived from Archive::Zip::_asZipDirName 216 217 # Return the normalized name as used in a zip file (path 218 # separators become slashes, etc.). 219 # Will translate internal slashes in path components (i.e. on Macs) to 220 # underscores. Discards volume names. 221 # When $forceDir is set, returns paths with trailing slashes 222 # 223 # input output 224 # . '.' 225 # ./a a 226 # ./a/b a/b 227 # ./a/b/ a/b 228 # a/b/ a/b 229 # /a/b/ a/b 230 # c:\a\b\c.doc a/b/c.doc # on Windows 231 # "i/o maps:whatever" i_o maps/whatever # on Macs 232 233 my $name = shift; 234 my $forceDir = shift ; 235 236 my ( $volume, $directories, $file ) = 237 File::Spec->splitpath( File::Spec->canonpath($name), $forceDir ); 238 239 my @dirs = map { $_ =~ s{/}{_}g; $_ } 240 File::Spec->splitdir($directories); 241 242 if ( @dirs > 0 ) { pop (@dirs) if $dirs[-1] eq '' } # remove empty component 243 push @dirs, defined($file) ? $file : '' ; 244 245 my $normalised_path = join '/', @dirs; 246 247 # Leading directory separators should not be stored in zip archives. 248 # Example: 249 # C:\a\b\c\ a/b/c 250 # C:\a\b\c.txt a/b/c.txt 251 # /a/b/c/ a/b/c 252 # /a/b/c.txt a/b/c.txt 253 $normalised_path =~ s{^/}{}; # remove leading separator 254 255 return $normalised_path; 256} 257 258 259sub mkHeader 260{ 261 my $self = shift; 262 my $param = shift ; 263 264 *$self->{ZipData}{LocalHdrOffset} = U64::clone(*$self->{ZipData}{Offset}); 265 266 my $comment = ''; 267 $comment = $param->valueOrDefault('comment') ; 268 269 my $filename = ''; 270 $filename = $param->valueOrDefault('name') ; 271 272 $filename = canonicalName($filename) 273 if length $filename && $param->getValue('canonicalname') ; 274 275 if (defined *$self->{ZipData}{FilterName} ) { 276 local *_ = \$filename ; 277 &{ *$self->{ZipData}{FilterName} }() ; 278 } 279 280 if ( $param->getValue('efs') && $] >= 5.008004) { 281 if (length $filename) { 282 utf8::downgrade($filename, 1) 283 or Carp::croak "Wide character in zip filename"; 284 } 285 286 if (length $comment) { 287 utf8::downgrade($comment, 1) 288 or Carp::croak "Wide character in zip comment"; 289 } 290 } 291 292 my $hdr = ''; 293 294 my $time = _unixToDosTime($param->getValue('time')); 295 296 my $extra = ''; 297 my $ctlExtra = ''; 298 my $empty = 0; 299 my $osCode = $param->getValue('os_code') ; 300 my $extFileAttr = 0 ; 301 302 # This code assumes Unix. 303 # TODO - revisit this 304 $extFileAttr = 0100644 << 16 305 if $osCode == ZIP_OS_CODE_UNIX ; 306 307 if (*$self->{ZipData}{Zip64}) { 308 $empty = IO::Compress::Base::Common::MAX32; 309 310 my $x = ''; 311 $x .= pack "V V", 0, 0 ; # uncompressedLength 312 $x .= pack "V V", 0, 0 ; # compressedLength 313 314 # Zip64 needs to be first in extra field to workaround a Windows Explorer Bug 315 # See http://www.info-zip.org/phpBB3/viewtopic.php?f=3&t=440 for details 316 $extra .= IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_ZIP64, $x); 317 } 318 319 if (! $param->getValue('minimal')) { 320 if ($param->parsed('mtime')) 321 { 322 $extra .= mkExtendedTime($param->getValue('mtime'), 323 $param->getValue('atime'), 324 $param->getValue('ctime')); 325 326 $ctlExtra .= mkExtendedTime($param->getValue('mtime')); 327 } 328 329 if ( $osCode == ZIP_OS_CODE_UNIX ) 330 { 331 if ( $param->getValue('want_exunixn') ) 332 { 333 my $ux3 = mkUnixNExtra( @{ $param->getValue('want_exunixn') }); 334 $extra .= $ux3; 335 $ctlExtra .= $ux3; 336 } 337 338 if ( $param->getValue('exunix2') ) 339 { 340 $extra .= mkUnix2Extra( @{ $param->getValue('exunix2') }); 341 $ctlExtra .= mkUnix2Extra(); 342 } 343 } 344 345 $extFileAttr = $param->getValue('extattr') 346 if defined $param->getValue('extattr') ; 347 348 $extra .= $param->getValue('extrafieldlocal') 349 if defined $param->getValue('extrafieldlocal'); 350 351 $ctlExtra .= $param->getValue('extrafieldcentral') 352 if defined $param->getValue('extrafieldcentral'); 353 } 354 355 my $method = *$self->{ZipData}{Method} ; 356 my $gpFlag = 0 ; 357 $gpFlag |= ZIP_GP_FLAG_STREAMING_MASK 358 if *$self->{ZipData}{Stream} ; 359 360 $gpFlag |= ZIP_GP_FLAG_LZMA_EOS_PRESENT 361 if $method == ZIP_CM_LZMA ; 362 363 $gpFlag |= ZIP_GP_FLAG_LANGUAGE_ENCODING 364 if $param->getValue('efs') && (length($filename) || length($comment)); 365 366 my $version = $ZIP_CM_MIN_VERSIONS{$method}; 367 $version = ZIP64_MIN_VERSION 368 if ZIP64_MIN_VERSION > $version && *$self->{ZipData}{Zip64}; 369 370 my $madeBy = ($param->getValue('os_code') << 8) + $version; 371 my $extract = $version; 372 373 *$self->{ZipData}{Version} = $version; 374 *$self->{ZipData}{MadeBy} = $madeBy; 375 376 my $ifa = 0; 377 $ifa |= ZIP_IFA_TEXT_MASK 378 if $param->getValue('textflag'); 379 380 $hdr .= pack "V", ZIP_LOCAL_HDR_SIG ; # signature 381 $hdr .= pack 'v', $extract ; # extract Version & OS 382 $hdr .= pack 'v', $gpFlag ; # general purpose flag (set streaming mode) 383 $hdr .= pack 'v', $method ; # compression method (deflate) 384 $hdr .= pack 'V', $time ; # last mod date/time 385 $hdr .= pack 'V', 0 ; # crc32 - 0 when streaming 386 $hdr .= pack 'V', $empty ; # compressed length - 0 when streaming 387 $hdr .= pack 'V', $empty ; # uncompressed length - 0 when streaming 388 $hdr .= pack 'v', length $filename ; # filename length 389 $hdr .= pack 'v', length $extra ; # extra length 390 391 $hdr .= $filename ; 392 393 # Remember the offset for the compressed & uncompressed lengths in the 394 # local header. 395 if (*$self->{ZipData}{Zip64}) { 396 *$self->{ZipData}{SizesOffset} = *$self->{ZipData}{Offset}->get64bit() 397 + length($hdr) + 4 ; 398 } 399 else { 400 *$self->{ZipData}{SizesOffset} = *$self->{ZipData}{Offset}->get64bit() 401 + 18; 402 } 403 404 $hdr .= $extra ; 405 406 407 my $ctl = ''; 408 409 $ctl .= pack "V", ZIP_CENTRAL_HDR_SIG ; # signature 410 $ctl .= pack 'v', $madeBy ; # version made by 411 $ctl .= pack 'v', $extract ; # extract Version 412 $ctl .= pack 'v', $gpFlag ; # general purpose flag (streaming mode) 413 $ctl .= pack 'v', $method ; # compression method (deflate) 414 $ctl .= pack 'V', $time ; # last mod date/time 415 $ctl .= pack 'V', 0 ; # crc32 416 $ctl .= pack 'V', $empty ; # compressed length 417 $ctl .= pack 'V', $empty ; # uncompressed length 418 $ctl .= pack 'v', length $filename ; # filename length 419 420 *$self->{ZipData}{ExtraOffset} = length $ctl; 421 *$self->{ZipData}{ExtraSize} = length $ctlExtra ; 422 423 $ctl .= pack 'v', length $ctlExtra ; # extra length 424 $ctl .= pack 'v', length $comment ; # file comment length 425 $ctl .= pack 'v', 0 ; # disk number start 426 $ctl .= pack 'v', $ifa ; # internal file attributes 427 $ctl .= pack 'V', $extFileAttr ; # external file attributes 428 429 # offset to local hdr 430 if (*$self->{ZipData}{LocalHdrOffset}->is64bit() ) { 431 $ctl .= pack 'V', IO::Compress::Base::Common::MAX32 ; 432 } 433 else { 434 $ctl .= *$self->{ZipData}{LocalHdrOffset}->getPacked_V32() ; 435 } 436 437 $ctl .= $filename ; 438 439 *$self->{ZipData}{Offset}->add32(length $hdr) ; 440 441 *$self->{ZipData}{CentralHeader} = [ $ctl, $ctlExtra, $comment]; 442 443 return $hdr; 444} 445 446sub mkTrailer 447{ 448 my $self = shift ; 449 450 my $crc32 ; 451 if (*$self->{ZipData}{Method} == ZIP_CM_DEFLATE) { 452 $crc32 = pack "V", *$self->{Compress}->crc32(); 453 } 454 else { 455 $crc32 = pack "V", *$self->{ZipData}{CRC32}; 456 } 457 458 my ($ctl, $ctlExtra, $comment) = @{ *$self->{ZipData}{CentralHeader} }; 459 460 my $sizes ; 461 if (! *$self->{ZipData}{Zip64}) { 462 $sizes .= *$self->{CompSize}->getPacked_V32() ; # Compressed size 463 $sizes .= *$self->{UnCompSize}->getPacked_V32() ; # Uncompressed size 464 } 465 else { 466 $sizes .= *$self->{CompSize}->getPacked_V64() ; # Compressed size 467 $sizes .= *$self->{UnCompSize}->getPacked_V64() ; # Uncompressed size 468 } 469 470 my $data = $crc32 . $sizes ; 471 472 my $xtrasize = *$self->{UnCompSize}->getPacked_V64() ; # Uncompressed size 473 $xtrasize .= *$self->{CompSize}->getPacked_V64() ; # Compressed size 474 475 my $hdr = ''; 476 477 if (*$self->{ZipData}{Stream}) { 478 $hdr = pack "V", ZIP_DATA_HDR_SIG ; # signature 479 $hdr .= $data ; 480 } 481 else { 482 $self->writeAt(*$self->{ZipData}{LocalHdrOffset}->get64bit() + 14, $crc32) 483 or return undef; 484 $self->writeAt(*$self->{ZipData}{SizesOffset}, 485 *$self->{ZipData}{Zip64} ? $xtrasize : $sizes) 486 or return undef; 487 } 488 489 # Central Header Record/Zip64 extended field 490 491 substr($ctl, 16, length $crc32) = $crc32 ; 492 493 my $zip64Payload = ''; 494 495 # uncompressed length - only set zip64 if needed 496 if (*$self->{UnCompSize}->isAlmost64bit()) { # || *$self->{ZipData}{Zip64}) { 497 $zip64Payload .= *$self->{UnCompSize}->getPacked_V64() ; 498 } else { 499 substr($ctl, 24, 4) = *$self->{UnCompSize}->getPacked_V32() ; 500 } 501 502 # compressed length - only set zip64 if needed 503 if (*$self->{CompSize}->isAlmost64bit()) { # || *$self->{ZipData}{Zip64}) { 504 $zip64Payload .= *$self->{CompSize}->getPacked_V64() ; 505 } else { 506 substr($ctl, 20, 4) = *$self->{CompSize}->getPacked_V32() ; 507 } 508 509 # Local Header offset 510 $zip64Payload .= *$self->{ZipData}{LocalHdrOffset}->getPacked_V64() 511 if *$self->{ZipData}{LocalHdrOffset}->is64bit() ; 512 513 # disk no - always zero, so don't need to include it. 514 #$zip64Payload .= pack "V", 0 ; 515 516 my $zip64Xtra = ''; 517 518 if (length $zip64Payload) { 519 $zip64Xtra = IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_ZIP64, $zip64Payload); 520 521 substr($ctl, *$self->{ZipData}{ExtraOffset}, 2) = 522 pack 'v', *$self->{ZipData}{ExtraSize} + length $zip64Xtra; 523 524 *$self->{ZipData}{AnyZip64} = 1; 525 } 526 527 # Zip64 needs to be first in extra field to workaround a Windows Explorer Bug 528 # See http://www.info-zip.org/phpBB3/viewtopic.php?f=3&t=440 for details 529 $ctl .= $zip64Xtra . $ctlExtra . $comment; 530 531 *$self->{ZipData}{Offset}->add32(length($hdr)); 532 *$self->{ZipData}{Offset}->add( *$self->{CompSize} ); 533 push @{ *$self->{ZipData}{CentralDir} }, $ctl ; 534 535 return $hdr; 536} 537 538sub mkFinalTrailer 539{ 540 my $self = shift ; 541 542 my $comment = ''; 543 $comment = *$self->{ZipData}{ZipComment} ; 544 545 my $cd_offset = *$self->{ZipData}{Offset}->get32bit() ; # offset to start central dir 546 547 my $entries = @{ *$self->{ZipData}{CentralDir} }; 548 549 *$self->{ZipData}{AnyZip64} = 1 550 if *$self->{ZipData}{Offset}->is64bit || $entries >= 0xFFFF ; 551 552 my $cd = join '', @{ *$self->{ZipData}{CentralDir} }; 553 my $cd_len = length $cd ; 554 555 my $z64e = ''; 556 557 if ( *$self->{ZipData}{AnyZip64} ) { 558 559 my $v = *$self->{ZipData}{Version} ; 560 my $mb = *$self->{ZipData}{MadeBy} ; 561 $z64e .= pack 'v', $mb ; # Version made by 562 $z64e .= pack 'v', $v ; # Version to extract 563 $z64e .= pack 'V', 0 ; # number of disk 564 $z64e .= pack 'V', 0 ; # number of disk with central dir 565 $z64e .= U64::pack_V64 $entries ; # entries in central dir on this disk 566 $z64e .= U64::pack_V64 $entries ; # entries in central dir 567 $z64e .= U64::pack_V64 $cd_len ; # size of central dir 568 $z64e .= *$self->{ZipData}{Offset}->getPacked_V64() ; # offset to start central dir 569 570 $z64e = pack("V", ZIP64_END_CENTRAL_REC_HDR_SIG) # signature 571 . U64::pack_V64(length $z64e) 572 . $z64e ; 573 574 *$self->{ZipData}{Offset}->add32(length $cd) ; 575 576 $z64e .= pack "V", ZIP64_END_CENTRAL_LOC_HDR_SIG; # signature 577 $z64e .= pack 'V', 0 ; # number of disk with central dir 578 $z64e .= *$self->{ZipData}{Offset}->getPacked_V64() ; # offset to end zip64 central dir 579 $z64e .= pack 'V', 1 ; # Total number of disks 580 581 $cd_offset = IO::Compress::Base::Common::MAX32 ; 582 $cd_len = IO::Compress::Base::Common::MAX32 if IO::Compress::Base::Common::isGeMax32 $cd_len ; 583 $entries = 0xFFFF if $entries >= 0xFFFF ; 584 } 585 586 my $ecd = ''; 587 $ecd .= pack "V", ZIP_END_CENTRAL_HDR_SIG ; # signature 588 $ecd .= pack 'v', 0 ; # number of disk 589 $ecd .= pack 'v', 0 ; # number of disk with central dir 590 $ecd .= pack 'v', $entries ; # entries in central dir on this disk 591 $ecd .= pack 'v', $entries ; # entries in central dir 592 $ecd .= pack 'V', $cd_len ; # size of central dir 593 $ecd .= pack 'V', $cd_offset ; # offset to start central dir 594 $ecd .= pack 'v', length $comment ; # zipfile comment length 595 $ecd .= $comment; 596 597 return $cd . $z64e . $ecd ; 598} 599 600sub ckParams 601{ 602 my $self = shift ; 603 my $got = shift; 604 605 $got->setValue('crc32' => 1); 606 607 if (! $got->parsed('time') ) { 608 # Modification time defaults to now. 609 $got->setValue('time' => time) ; 610 } 611 612 if ($got->parsed('extime') ) { 613 my $timeRef = $got->getValue('extime'); 614 if ( defined $timeRef) { 615 return $self->saveErrorString(undef, "exTime not a 3-element array ref") 616 if ref $timeRef ne 'ARRAY' || @$timeRef != 3; 617 } 618 619 $got->setValue("mtime", $timeRef->[1]); 620 $got->setValue("atime", $timeRef->[0]); 621 $got->setValue("ctime", $timeRef->[2]); 622 } 623 624 # Unix2/3 Extended Attribute 625 for my $name (qw(exunix2 exunixn)) 626 { 627 if ($got->parsed($name) ) { 628 my $idRef = $got->getValue($name); 629 if ( defined $idRef) { 630 return $self->saveErrorString(undef, "$name not a 2-element array ref") 631 if ref $idRef ne 'ARRAY' || @$idRef != 2; 632 } 633 634 $got->setValue("uid", $idRef->[0]); 635 $got->setValue("gid", $idRef->[1]); 636 $got->setValue("want_$name", $idRef); 637 } 638 } 639 640 *$self->{ZipData}{AnyZip64} = 1 641 if $got->getValue('zip64'); 642 *$self->{ZipData}{Zip64} = $got->getValue('zip64'); 643 *$self->{ZipData}{Stream} = $got->getValue('stream'); 644 645 my $method = $got->getValue('method'); 646 return $self->saveErrorString(undef, "Unknown Method '$method'") 647 if ! defined $ZIP_CM_MIN_VERSIONS{$method}; 648 649 return $self->saveErrorString(undef, "Bzip2 not available") 650 if $method == ZIP_CM_BZIP2 and 651 ! defined $IO::Compress::Adapter::Bzip2::VERSION; 652 653 return $self->saveErrorString(undef, "Lzma not available") 654 if $method == ZIP_CM_LZMA 655 and ! defined $IO::Compress::Adapter::Lzma::VERSION; 656 657 *$self->{ZipData}{Method} = $method; 658 659 *$self->{ZipData}{ZipComment} = $got->getValue('zipcomment') ; 660 661 for my $name (qw( extrafieldlocal extrafieldcentral )) 662 { 663 my $data = $got->getValue($name) ; 664 if (defined $data) { 665 my $bad = IO::Compress::Zlib::Extra::parseExtraField($data, 1, 0) ; 666 return $self->saveErrorString(undef, "Error with $name Parameter: $bad") 667 if $bad ; 668 669 $got->setValue($name, $data) ; 670 } 671 } 672 673 return undef 674 if defined $IO::Compress::Bzip2::VERSION 675 and ! IO::Compress::Bzip2::ckParams($self, $got); 676 677 if ($got->parsed('sparse') ) { 678 *$self->{ZipData}{Sparse} = $got->getValue('sparse') ; 679 *$self->{ZipData}{Method} = ZIP_CM_STORE; 680 } 681 682 if ($got->parsed('filtername')) { 683 my $v = $got->getValue('filtername') ; 684 *$self->{ZipData}{FilterName} = $v 685 if ref $v eq 'CODE' ; 686 } 687 688 return 1 ; 689} 690 691sub outputPayload 692{ 693 my $self = shift ; 694 return 1 if *$self->{ZipData}{Sparse} ; 695 return $self->output(@_); 696} 697 698 699#sub newHeader 700#{ 701# my $self = shift ; 702# 703# return $self->mkHeader(*$self->{Got}); 704#} 705 706 707our %PARAMS = ( 708 'stream' => [IO::Compress::Base::Common::Parse_boolean, 1], 709 #'store' => [IO::Compress::Base::Common::Parse_boolean, 0], 710 'method' => [IO::Compress::Base::Common::Parse_unsigned, ZIP_CM_DEFLATE], 711 712# # Zip header fields 713 'minimal' => [IO::Compress::Base::Common::Parse_boolean, 0], 714 'zip64' => [IO::Compress::Base::Common::Parse_boolean, 0], 715 'comment' => [IO::Compress::Base::Common::Parse_any, ''], 716 'zipcomment'=> [IO::Compress::Base::Common::Parse_any, ''], 717 'name' => [IO::Compress::Base::Common::Parse_any, ''], 718 'filtername'=> [IO::Compress::Base::Common::Parse_code, undef], 719 'canonicalname'=> [IO::Compress::Base::Common::Parse_boolean, 0], 720 'efs' => [IO::Compress::Base::Common::Parse_boolean, 0], 721 'time' => [IO::Compress::Base::Common::Parse_any, undef], 722 'extime' => [IO::Compress::Base::Common::Parse_any, undef], 723 'exunix2' => [IO::Compress::Base::Common::Parse_any, undef], 724 'exunixn' => [IO::Compress::Base::Common::Parse_any, undef], 725 'extattr' => [IO::Compress::Base::Common::Parse_any, 726 $Compress::Raw::Zlib::gzip_os_code == 3 727 ? 0100644 << 16 728 : 0], 729 'os_code' => [IO::Compress::Base::Common::Parse_unsigned, $Compress::Raw::Zlib::gzip_os_code], 730 731 'textflag' => [IO::Compress::Base::Common::Parse_boolean, 0], 732 'extrafieldlocal' => [IO::Compress::Base::Common::Parse_any, undef], 733 'extrafieldcentral'=> [IO::Compress::Base::Common::Parse_any, undef], 734 735 # Lzma 736 'preset' => [IO::Compress::Base::Common::Parse_unsigned, 6], 737 'extreme' => [IO::Compress::Base::Common::Parse_boolean, 0], 738 739 # For internal use only 740 'sparse' => [IO::Compress::Base::Common::Parse_unsigned, 0], 741 742 IO::Compress::RawDeflate::getZlibParams(), 743 defined $IO::Compress::Bzip2::VERSION 744 ? IO::Compress::Bzip2::getExtraParams() 745 : () 746 747 748 ); 749 750sub getExtraParams 751{ 752 return %PARAMS ; 753} 754 755sub getInverseClass 756{ 757 no warnings 'once'; 758 return ('IO::Uncompress::Unzip', 759 \$IO::Uncompress::Unzip::UnzipError); 760} 761 762sub getFileInfo 763{ 764 my $self = shift ; 765 my $params = shift; 766 my $filename = shift ; 767 768 if (IO::Compress::Base::Common::isaScalar($filename)) 769 { 770 $params->setValue(zip64 => 1) 771 if IO::Compress::Base::Common::isGeMax32 length (${ $filename }) ; 772 773 return ; 774 } 775 776 my ($mode, $uid, $gid, $size, $atime, $mtime, $ctime) ; 777 if ( $params->parsed('storelinks') ) 778 { 779 ($mode, $uid, $gid, $size, $atime, $mtime, $ctime) 780 = (lstat($filename))[2, 4,5,7, 8,9,10] ; 781 } 782 else 783 { 784 ($mode, $uid, $gid, $size, $atime, $mtime, $ctime) 785 = (stat($filename))[2, 4,5,7, 8,9,10] ; 786 } 787 788 $params->setValue(textflag => -T $filename ) 789 if ! $params->parsed('textflag'); 790 791 $params->setValue(zip64 => 1) 792 if IO::Compress::Base::Common::isGeMax32 $size ; 793 794 $params->setValue('name' => $filename) 795 if ! $params->parsed('name') ; 796 797 $params->setValue('time' => $mtime) 798 if ! $params->parsed('time') ; 799 800 if ( ! $params->parsed('extime')) 801 { 802 $params->setValue('mtime' => $mtime) ; 803 $params->setValue('atime' => $atime) ; 804 $params->setValue('ctime' => undef) ; # No Creation time 805 # TODO - see if can fillout creation time on non-Unix 806 } 807 808 # NOTE - Unix specific code alert 809 if (! $params->parsed('extattr')) 810 { 811 use Fcntl qw(:mode) ; 812 my $attr = $mode << 16; 813 $attr |= ZIP_A_RONLY if ($mode & S_IWRITE) == 0 ; 814 $attr |= ZIP_A_DIR if ($mode & S_IFMT ) == S_IFDIR ; 815 816 $params->setValue('extattr' => $attr); 817 } 818 819 $params->setValue('want_exunixn', [$uid, $gid]); 820 $params->setValue('uid' => $uid) ; 821 $params->setValue('gid' => $gid) ; 822 823} 824 825sub mkExtendedTime 826{ 827 # order expected is m, a, c 828 829 my $times = ''; 830 my $bit = 1 ; 831 my $flags = 0; 832 833 for my $time (@_) 834 { 835 if (defined $time) 836 { 837 $flags |= $bit; 838 $times .= pack("V", $time); 839 } 840 841 $bit <<= 1 ; 842 } 843 844 return IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_EXT_TIMESTAMP, 845 pack("C", $flags) . $times); 846} 847 848sub mkUnix2Extra 849{ 850 my $ids = ''; 851 for my $id (@_) 852 { 853 $ids .= pack("v", $id); 854 } 855 856 return IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_INFO_ZIP_UNIX2, 857 $ids); 858} 859 860sub mkUnixNExtra 861{ 862 my $uid = shift; 863 my $gid = shift; 864 865 # Assumes UID/GID are 32-bit 866 my $ids ; 867 $ids .= pack "C", 1; # version 868 $ids .= pack "C", $Config{uidsize}; 869 $ids .= pack "V", $uid; 870 $ids .= pack "C", $Config{gidsize}; 871 $ids .= pack "V", $gid; 872 873 return IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_INFO_ZIP_UNIXN, 874 $ids); 875} 876 877 878# from Archive::Zip 879sub _unixToDosTime # Archive::Zip::Member 880{ 881 my $time_t = shift; 882 883 # TODO - add something to cope with unix time < 1980 884 my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime($time_t); 885 my $dt = 0; 886 $dt += ( $sec >> 1 ); 887 $dt += ( $min << 5 ); 888 $dt += ( $hour << 11 ); 889 $dt += ( $mday << 16 ); 890 $dt += ( ( $mon + 1 ) << 21 ); 891 $dt += ( ( $year - 80 ) << 25 ); 892 return $dt; 893} 894 8951; 896 897__END__ 898 899=head1 NAME 900 901IO::Compress::Zip - Write zip files/buffers 902 903=head1 SYNOPSIS 904 905 use IO::Compress::Zip qw(zip $ZipError) ; 906 907 my $status = zip $input => $output [,OPTS] 908 or die "zip failed: $ZipError\n"; 909 910 my $z = IO::Compress::Zip->new( $output [,OPTS] ) 911 or die "zip failed: $ZipError\n"; 912 913 $z->print($string); 914 $z->printf($format, $string); 915 $z->write($string); 916 $z->syswrite($string [, $length, $offset]); 917 $z->flush(); 918 $z->tell(); 919 $z->eof(); 920 $z->seek($position, $whence); 921 $z->binmode(); 922 $z->fileno(); 923 $z->opened(); 924 $z->autoflush(); 925 $z->input_line_number(); 926 $z->newStream( [OPTS] ); 927 928 $z->deflateParams(); 929 930 $z->close() ; 931 932 $ZipError ; 933 934 # IO::File mode 935 936 print $z $string; 937 printf $z $format, $string; 938 tell $z 939 eof $z 940 seek $z, $position, $whence 941 binmode $z 942 fileno $z 943 close $z ; 944 945=head1 DESCRIPTION 946 947This module provides a Perl interface that allows writing zip 948compressed data to files or buffer. 949 950The primary purpose of this module is to provide streaming write access to 951zip files and buffers. 952 953At present the following compression methods are supported by IO::Compress::Zip 954 955=over 5 956 957=item Store (0) 958 959=item Deflate (8) 960 961=item Bzip2 (12) 962 963To write Bzip2 content, the module C<IO::Uncompress::Bunzip2> must 964be installed. 965 966=item Lzma (14) 967 968To write LZMA content, the module C<IO::Uncompress::UnLzma> must 969be installed. 970 971=item Zstandard (93) 972 973To write Zstandard content, the module C<IO::Compress::Zstd> must 974be installed. 975 976=item Xz (95) 977 978To write Xz content, the module C<IO::Uncompress::UnXz> must 979be installed. 980 981=back 982 983For reading zip files/buffers, see the companion module 984L<IO::Uncompress::Unzip|IO::Uncompress::Unzip>. 985 986=head1 Functional Interface 987 988A top-level function, C<zip>, is provided to carry out 989"one-shot" compression between buffers and/or files. For finer 990control over the compression process, see the L</"OO Interface"> 991section. 992 993 use IO::Compress::Zip qw(zip $ZipError) ; 994 995 zip $input_filename_or_reference => $output_filename_or_reference [,OPTS] 996 or die "zip failed: $ZipError\n"; 997 998The functional interface needs Perl5.005 or better. 999 1000=head2 zip $input_filename_or_reference => $output_filename_or_reference [, OPTS] 1001 1002C<zip> expects at least two parameters, 1003C<$input_filename_or_reference> and C<$output_filename_or_reference> 1004and zero or more optional parameters (see L</Optional Parameters>) 1005 1006=head3 The C<$input_filename_or_reference> parameter 1007 1008The parameter, C<$input_filename_or_reference>, is used to define the 1009source of the uncompressed data. 1010 1011It can take one of the following forms: 1012 1013=over 5 1014 1015=item A filename 1016 1017If the C<$input_filename_or_reference> parameter is a simple scalar, it is 1018assumed to be a filename. This file will be opened for reading and the 1019input data will be read from it. 1020 1021=item A filehandle 1022 1023If the C<$input_filename_or_reference> parameter is a filehandle, the input 1024data will be read from it. The string '-' can be used as an alias for 1025standard input. 1026 1027=item A scalar reference 1028 1029If C<$input_filename_or_reference> is a scalar reference, the input data 1030will be read from C<$$input_filename_or_reference>. 1031 1032=item An array reference 1033 1034If C<$input_filename_or_reference> is an array reference, each element in 1035the array must be a filename. 1036 1037The input data will be read from each file in turn. 1038 1039The complete array will be walked to ensure that it only 1040contains valid filenames before any data is compressed. 1041 1042=item An Input FileGlob string 1043 1044If C<$input_filename_or_reference> is a string that is delimited by the 1045characters "<" and ">" C<zip> will assume that it is an 1046I<input fileglob string>. The input is the list of files that match the 1047fileglob. 1048 1049See L<File::GlobMapper|File::GlobMapper> for more details. 1050 1051=back 1052 1053If the C<$input_filename_or_reference> parameter is any other type, 1054C<undef> will be returned. 1055 1056In addition, if C<$input_filename_or_reference> is a simple filename, 1057the default values for 1058the C<Name>, C<Time>, C<TextFlag>, C<ExtAttr>, C<exUnixN> and C<exTime> options will be sourced from that file. 1059 1060If you do not want to use these defaults they can be overridden by 1061explicitly setting the C<Name>, C<Time>, C<TextFlag>, C<ExtAttr>, C<exUnixN> and C<exTime> options or by setting the 1062C<Minimal> parameter. 1063 1064=head3 The C<$output_filename_or_reference> parameter 1065 1066The parameter C<$output_filename_or_reference> is used to control the 1067destination of the compressed data. This parameter can take one of 1068these forms. 1069 1070=over 5 1071 1072=item A filename 1073 1074If the C<$output_filename_or_reference> parameter is a simple scalar, it is 1075assumed to be a filename. This file will be opened for writing and the 1076compressed data will be written to it. 1077 1078=item A filehandle 1079 1080If the C<$output_filename_or_reference> parameter is a filehandle, the 1081compressed data will be written to it. The string '-' can be used as 1082an alias for standard output. 1083 1084=item A scalar reference 1085 1086If C<$output_filename_or_reference> is a scalar reference, the 1087compressed data will be stored in C<$$output_filename_or_reference>. 1088 1089=item An Array Reference 1090 1091If C<$output_filename_or_reference> is an array reference, 1092the compressed data will be pushed onto the array. 1093 1094=item An Output FileGlob 1095 1096If C<$output_filename_or_reference> is a string that is delimited by the 1097characters "<" and ">" C<zip> will assume that it is an 1098I<output fileglob string>. The output is the list of files that match the 1099fileglob. 1100 1101When C<$output_filename_or_reference> is an fileglob string, 1102C<$input_filename_or_reference> must also be a fileglob string. Anything 1103else is an error. 1104 1105See L<File::GlobMapper|File::GlobMapper> for more details. 1106 1107=back 1108 1109If the C<$output_filename_or_reference> parameter is any other type, 1110C<undef> will be returned. 1111 1112=head2 Notes 1113 1114When C<$input_filename_or_reference> maps to multiple files/buffers and 1115C<$output_filename_or_reference> is a single 1116file/buffer the input files/buffers will each be stored 1117in C<$output_filename_or_reference> as a distinct entry. 1118 1119=head2 Optional Parameters 1120 1121The optional parameters for the one-shot function C<zip> 1122are (for the most part) identical to those used with the OO interface defined in the 1123L</"Constructor Options"> section. The exceptions are listed below 1124 1125=over 5 1126 1127=item C<< AutoClose => 0|1 >> 1128 1129This option applies to any input or output data streams to 1130C<zip> that are filehandles. 1131 1132If C<AutoClose> is specified, and the value is true, it will result in all 1133input and/or output filehandles being closed once C<zip> has 1134completed. 1135 1136This parameter defaults to 0. 1137 1138=item C<< BinModeIn => 0|1 >> 1139 1140This option is now a no-op. All files will be read in binmode. 1141 1142=item C<< Append => 0|1 >> 1143 1144The behaviour of this option is dependent on the type of output data 1145stream. 1146 1147=over 5 1148 1149=item * A Buffer 1150 1151If C<Append> is enabled, all compressed data will be append to the end of 1152the output buffer. Otherwise the output buffer will be cleared before any 1153compressed data is written to it. 1154 1155=item * A Filename 1156 1157If C<Append> is enabled, the file will be opened in append mode. Otherwise 1158the contents of the file, if any, will be truncated before any compressed 1159data is written to it. 1160 1161=item * A Filehandle 1162 1163If C<Append> is enabled, the filehandle will be positioned to the end of 1164the file via a call to C<seek> before any compressed data is 1165written to it. Otherwise the file pointer will not be moved. 1166 1167=back 1168 1169When C<Append> is specified, and set to true, it will I<append> all compressed 1170data to the output data stream. 1171 1172So when the output is a filehandle it will carry out a seek to the eof 1173before writing any compressed data. If the output is a filename, it will be opened for 1174appending. If the output is a buffer, all compressed data will be 1175appended to the existing buffer. 1176 1177Conversely when C<Append> is not specified, or it is present and is set to 1178false, it will operate as follows. 1179 1180When the output is a filename, it will truncate the contents of the file 1181before writing any compressed data. If the output is a filehandle 1182its position will not be changed. If the output is a buffer, it will be 1183wiped before any compressed data is output. 1184 1185Defaults to 0. 1186 1187=back 1188 1189=head2 Examples 1190 1191Here are a few example that show the capabilities of the module. 1192 1193=head3 Streaming 1194 1195This very simple command line example demonstrates the streaming capabilities of the module. 1196The code reads data from STDIN, compresses it, and writes the compressed data to STDOUT. 1197 1198 $ echo hello world | perl -MIO::Compress::Zip=zip -e 'zip \*STDIN => \*STDOUT' >output.zip 1199 1200The special filename "-" can be used as a standin for both C<\*STDIN> and C<\*STDOUT>, 1201so the above can be rewritten as 1202 1203 $ echo hello world | perl -MIO::Compress::Zip=zip -e 'zip "-" => "-"' >output.zip 1204 1205One problem with creating a zip archive directly from STDIN can be demonstrated by looking at 1206the contents of the zip file, output.zip, that we have just created. 1207 1208 $ unzip -l output.zip 1209 Archive: output.zip 1210 Length Date Time Name 1211 --------- ---------- ----- ---- 1212 12 2019-08-16 22:21 1213 --------- ------- 1214 12 1 file 1215 1216The archive member (filename) used is the empty string. 1217 1218If that doesn't suit your needs, you can explicitly set the filename used 1219in the zip archive by specifying the L<Name|"File Naming Options"> option, like so 1220 1221 echo hello world | perl -MIO::Compress::Zip=zip -e 'zip "-" => "-", Name => "hello.txt"' >output.zip 1222 1223Now the contents of the zip file looks like this 1224 1225 $ unzip -l output.zip 1226 Archive: output.zip 1227 Length Date Time Name 1228 --------- ---------- ----- ---- 1229 12 2019-08-16 22:22 hello.txt 1230 --------- ------- 1231 12 1 file 1232 1233=head3 Compressing a file from the filesystem 1234 1235To read the contents of the file C<file1.txt> and write the compressed 1236data to the file C<file1.txt.zip>. 1237 1238 use strict ; 1239 use warnings ; 1240 use IO::Compress::Zip qw(zip $ZipError) ; 1241 1242 my $input = "file1.txt"; 1243 zip $input => "$input.zip" 1244 or die "zip failed: $ZipError\n"; 1245 1246=head3 Reading from a Filehandle and writing to an in-memory buffer 1247 1248To read from an existing Perl filehandle, C<$input>, and write the 1249compressed data to a buffer, C<$buffer>. 1250 1251 use strict ; 1252 use warnings ; 1253 use IO::Compress::Zip qw(zip $ZipError) ; 1254 use IO::File ; 1255 1256 my $input = IO::File->new( "<file1.txt" ) 1257 or die "Cannot open 'file1.txt': $!\n" ; 1258 my $buffer ; 1259 zip $input => \$buffer 1260 or die "zip failed: $ZipError\n"; 1261 1262=head3 Compressing multiple files 1263 1264To create a zip file, C<output.zip>, that contains the compressed contents 1265of the files C<alpha.txt> and C<beta.txt> 1266 1267 use strict ; 1268 use warnings ; 1269 use IO::Compress::Zip qw(zip $ZipError) ; 1270 1271 zip [ 'alpha.txt', 'beta.txt' ] => 'output.zip' 1272 or die "zip failed: $ZipError\n"; 1273 1274Alternatively, rather than having to explicitly name each of the files that 1275you want to compress, you could use a fileglob to select all the C<txt> 1276files in the current directory, as follows 1277 1278 use strict ; 1279 use warnings ; 1280 use IO::Compress::Zip qw(zip $ZipError) ; 1281 1282 my @files = <*.txt>; 1283 zip \@files => 'output.zip' 1284 or die "zip failed: $ZipError\n"; 1285 1286or more succinctly 1287 1288 zip [ <*.txt> ] => 'output.zip' 1289 or die "zip failed: $ZipError\n"; 1290 1291=head1 OO Interface 1292 1293=head2 Constructor 1294 1295The format of the constructor for C<IO::Compress::Zip> is shown below 1296 1297 my $z = IO::Compress::Zip->new( $output [,OPTS] ) 1298 or die "IO::Compress::Zip failed: $ZipError\n"; 1299 1300It returns an C<IO::Compress::Zip> object on success and undef on failure. 1301The variable C<$ZipError> will contain an error message on failure. 1302 1303If you are running Perl 5.005 or better the object, C<$z>, returned from 1304IO::Compress::Zip can be used exactly like an L<IO::File|IO::File> filehandle. 1305This means that all normal output file operations can be carried out 1306with C<$z>. 1307For example, to write to a compressed file/buffer you can use either of 1308these forms 1309 1310 $z->print("hello world\n"); 1311 print $z "hello world\n"; 1312 1313The mandatory parameter C<$output> is used to control the destination 1314of the compressed data. This parameter can take one of these forms. 1315 1316=over 5 1317 1318=item A filename 1319 1320If the C<$output> parameter is a simple scalar, it is assumed to be a 1321filename. This file will be opened for writing and the compressed data 1322will be written to it. 1323 1324=item A filehandle 1325 1326If the C<$output> parameter is a filehandle, the compressed data will be 1327written to it. 1328The string '-' can be used as an alias for standard output. 1329 1330=item A scalar reference 1331 1332If C<$output> is a scalar reference, the compressed data will be stored 1333in C<$$output>. 1334 1335=back 1336 1337If the C<$output> parameter is any other type, C<IO::Compress::Zip>::new will 1338return undef. 1339 1340=head2 Constructor Options 1341 1342C<OPTS> is any combination of zero or more the following options: 1343 1344=over 5 1345 1346=item C<< AutoClose => 0|1 >> 1347 1348This option is only valid when the C<$output> parameter is a filehandle. If 1349specified, and the value is true, it will result in the C<$output> being 1350closed once either the C<close> method is called or the C<IO::Compress::Zip> 1351object is destroyed. 1352 1353This parameter defaults to 0. 1354 1355=item C<< Append => 0|1 >> 1356 1357Opens C<$output> in append mode. 1358 1359The behaviour of this option is dependent on the type of C<$output>. 1360 1361=over 5 1362 1363=item * A Buffer 1364 1365If C<$output> is a buffer and C<Append> is enabled, all compressed data 1366will be append to the end of C<$output>. Otherwise C<$output> will be 1367cleared before any data is written to it. 1368 1369=item * A Filename 1370 1371If C<$output> is a filename and C<Append> is enabled, the file will be 1372opened in append mode. Otherwise the contents of the file, if any, will be 1373truncated before any compressed data is written to it. 1374 1375=item * A Filehandle 1376 1377If C<$output> is a filehandle, the file pointer will be positioned to the 1378end of the file via a call to C<seek> before any compressed data is written 1379to it. Otherwise the file pointer will not be moved. 1380 1381=back 1382 1383This parameter defaults to 0. 1384 1385=back 1386 1387=head3 File Naming Options 1388 1389A quick bit of zip file terminology -- A zip archive consists of one or more I<archive members>, where each member has an associated 1390filename, known as the I<archive member name>. 1391 1392The options listed in this section control how the I<archive member name> (or filename) is stored the zip archive. 1393 1394=over 5 1395 1396=item C<< Name => $string >> 1397 1398This option is used to explicitly set the I<archive member name> in 1399the zip archive to C<$string>. 1400Most of the time you don't need to make use of this option. 1401By default when adding a filename to the zip archive, the I<archive member name> will match the filename. 1402 1403You should only need to use this option if you want the I<archive member name> 1404to be different from the uncompressed filename or when the input is a filehandle or a buffer. 1405 1406The default behaviour for what I<archive member name> is used when the C<Name> option 1407is I<not> specified depends on the form of the C<$input> parameter: 1408 1409=over 5 1410 1411=item * 1412 1413If the C<$input> parameter is a filename, the 1414value of C<$input> will be used for the I<archive member name> . 1415 1416=item * 1417If the C<$input> parameter is not a filename, 1418the I<archive member name> will be an empty string. 1419 1420=back 1421 1422Note that both the C<CanonicalName> and C<FilterName> options 1423can modify the value used for the I<archive member name>. 1424 1425Also note that you should set the C<Efs> option to true if you are working 1426with UTF8 filenames. 1427 1428=item C<< CanonicalName => 0|1 >> 1429 1430This option controls whether the I<archive member name> is 1431I<normalized> into Unix format before being written to the zip file. 1432 1433It is recommended that you enable this option unless you really need 1434to create a non-standard Zip file. 1435 1436This is what APPNOTE.TXT has to say on what should be stored in the zip 1437filename header field. 1438 1439 The name of the file, with optional relative path. 1440 The path stored should not contain a drive or 1441 device letter, or a leading slash. All slashes 1442 should be forward slashes '/' as opposed to 1443 backwards slashes '\' for compatibility with Amiga 1444 and UNIX file systems etc. 1445 1446This option defaults to B<false>. 1447 1448=item C<< FilterName => sub { ... } >> 1449 1450This option allow the I<archive member> name to be modified 1451before it is written to the zip file. 1452 1453This option takes a parameter that must be a reference to a sub. On entry 1454to the sub the C<$_> variable will contain the name to be filtered. If no 1455filename is available C<$_> will contain an empty string. 1456 1457The value of C<$_> when the sub returns will be used as the I<archive member name>. 1458 1459Note that if C<CanonicalName> is enabled, a 1460normalized filename will be passed to the sub. 1461 1462If you use C<FilterName> to modify the filename, it is your responsibility 1463to keep the filename in Unix format. 1464 1465Although this option can be used with the OO interface, it is of most use 1466with the one-shot interface. For example, the code below shows how 1467C<FilterName> can be used to remove the path component from a series of 1468filenames before they are stored in C<$zipfile>. 1469 1470 sub compressTxtFiles 1471 { 1472 my $zipfile = shift ; 1473 my $dir = shift ; 1474 1475 zip [ <$dir/*.txt> ] => $zipfile, 1476 FilterName => sub { s[^$dir/][] } ; 1477 } 1478 1479=item C<< Efs => 0|1 >> 1480 1481This option controls setting of the "Language Encoding Flag" (EFS) in the zip 1482archive. When set, the filename and comment fields for the zip archive MUST 1483be valid UTF-8. 1484 1485If the string used for the filename and/or comment is not valid UTF-8 when this option 1486is true, the script will die with a "wide character" error. 1487 1488Note that this option only works with Perl 5.8.4 or better. 1489 1490This option defaults to B<false>. 1491 1492=back 1493 1494=head3 Overall Zip Archive Structure 1495 1496=over 5 1497 1498=item C<< Minimal => 1|0 >> 1499 1500If specified, this option will disable the creation of all extra fields 1501in the zip local and central headers. So the C<exTime>, C<exUnix2>, 1502C<exUnixN>, C<ExtraFieldLocal> and C<ExtraFieldCentral> options will 1503be ignored. 1504 1505This parameter defaults to 0. 1506 1507=item C<< Stream => 0|1 >> 1508 1509This option controls whether the zip file/buffer output is created in 1510streaming mode. 1511 1512Note that when outputting to a file with streaming mode disabled (C<Stream> 1513is 0), the output file must be seekable. 1514 1515The default is 1. 1516 1517=item C<< Zip64 => 0|1 >> 1518 1519Create a Zip64 zip file/buffer. This option is used if you want 1520to store files larger than 4 Gig or store more than 64K files in a single 1521zip archive. 1522 1523C<Zip64> will be automatically set, as needed, if working with the one-shot 1524interface when the input is either a filename or a scalar reference. 1525 1526If you intend to manipulate the Zip64 zip files created with this module 1527using an external zip/unzip, make sure that it supports Zip64. 1528 1529In particular, if you are using Info-Zip you need to have zip version 3.x 1530or better to update a Zip64 archive and unzip version 6.x to read a zip64 1531archive. 1532 1533The default is 0. 1534 1535=back 1536 1537=head3 Deflate Compression Options 1538 1539=over 5 1540 1541=item -Level 1542 1543Defines the compression level used by zlib. The value should either be 1544a number between 0 and 9 (0 means no compression and 9 is maximum 1545compression), or one of the symbolic constants defined below. 1546 1547 Z_NO_COMPRESSION 1548 Z_BEST_SPEED 1549 Z_BEST_COMPRESSION 1550 Z_DEFAULT_COMPRESSION 1551 1552The default is Z_DEFAULT_COMPRESSION. 1553 1554Note, these constants are not imported by C<IO::Compress::Zip> by default. 1555 1556 use IO::Compress::Zip qw(:strategy); 1557 use IO::Compress::Zip qw(:constants); 1558 use IO::Compress::Zip qw(:all); 1559 1560=item -Strategy 1561 1562Defines the strategy used to tune the compression. Use one of the symbolic 1563constants defined below. 1564 1565 Z_FILTERED 1566 Z_HUFFMAN_ONLY 1567 Z_RLE 1568 Z_FIXED 1569 Z_DEFAULT_STRATEGY 1570 1571The default is Z_DEFAULT_STRATEGY. 1572 1573=back 1574 1575=head3 Bzip2 Compression Options 1576 1577=over 5 1578 1579=item C<< BlockSize100K => number >> 1580 1581Specify the number of 100K blocks bzip2 uses during compression. 1582 1583Valid values are from 1 to 9, where 9 is best compression. 1584 1585This option is only valid if the C<Method> is ZIP_CM_BZIP2. It is ignored 1586otherwise. 1587 1588The default is 1. 1589 1590=item C<< WorkFactor => number >> 1591 1592Specifies how much effort bzip2 should take before resorting to a slower 1593fallback compression algorithm. 1594 1595Valid values range from 0 to 250, where 0 means use the default value 30. 1596 1597This option is only valid if the C<Method> is ZIP_CM_BZIP2. It is ignored 1598otherwise. 1599 1600The default is 0. 1601 1602=back 1603 1604=head3 Lzma and Xz Compression Options 1605 1606=over 5 1607 1608=item C<< Preset => number >> 1609 1610Used to choose the LZMA compression preset. 1611 1612Valid values are 0-9 and C<LZMA_PRESET_DEFAULT>. 1613 16140 is the fastest compression with the lowest memory usage and the lowest 1615compression. 1616 16179 is the slowest compression with the highest memory usage but with the best 1618compression. 1619 1620This option is only valid if the C<Method> is ZIP_CM_LZMA. It is ignored 1621otherwise. 1622 1623Defaults to C<LZMA_PRESET_DEFAULT> (6). 1624 1625=item C<< Extreme => 0|1 >> 1626 1627Makes LZMA compression a lot slower, but a small compression gain. 1628 1629This option is only valid if the C<Method> is ZIP_CM_LZMA. It is ignored 1630otherwise. 1631 1632Defaults to 0. 1633 1634=back 1635 1636=head3 Other Options 1637 1638=over 5 1639 1640=item C<< Time => $number >> 1641 1642Sets the last modified time field in the zip header to $number. 1643 1644This field defaults to the time the C<IO::Compress::Zip> object was created 1645if this option is not specified and the C<$input> parameter is not a 1646filename. 1647 1648=item C<< ExtAttr => $attr >> 1649 1650This option controls the "external file attributes" field in the central 1651header of the zip file. This is a 4 byte field. 1652 1653If you are running a Unix derivative this value defaults to 1654 1655 0100644 << 16 1656 1657This should allow read/write access to any files that are extracted from 1658the zip file/buffer`. 1659 1660For all other systems it defaults to 0. 1661 1662=item C<< exTime => [$atime, $mtime, $ctime] >> 1663 1664This option expects an array reference with exactly three elements: 1665C<$atime>, C<mtime> and C<$ctime>. These correspond to the last access 1666time, last modification time and creation time respectively. 1667 1668It uses these values to set the extended timestamp field (ID is "UT") in 1669the local zip header using the three values, $atime, $mtime, $ctime. In 1670addition it sets the extended timestamp field in the central zip header 1671using C<$mtime>. 1672 1673If any of the three values is C<undef> that time value will not be used. 1674So, for example, to set only the C<$mtime> you would use this 1675 1676 exTime => [undef, $mtime, undef] 1677 1678If the C<Minimal> option is set to true, this option will be ignored. 1679 1680By default no extended time field is created. 1681 1682=item C<< exUnix2 => [$uid, $gid] >> 1683 1684This option expects an array reference with exactly two elements: C<$uid> 1685and C<$gid>. These values correspond to the numeric User ID (UID) and Group ID 1686(GID) of the owner of the files respectively. 1687 1688When the C<exUnix2> option is present it will trigger the creation of a 1689Unix2 extra field (ID is "Ux") in the local zip header. This will be populated 1690with C<$uid> and C<$gid>. An empty Unix2 extra field will also 1691be created in the central zip header. 1692 1693Note - The UID & GID are stored as 16-bit 1694integers in the "Ux" field. Use C<< exUnixN >> if your UID or GID are 169532-bit. 1696 1697If the C<Minimal> option is set to true, this option will be ignored. 1698 1699By default no Unix2 extra field is created. 1700 1701=item C<< exUnixN => [$uid, $gid] >> 1702 1703This option expects an array reference with exactly two elements: C<$uid> 1704and C<$gid>. These values correspond to the numeric User ID (UID) and Group ID 1705(GID) of the owner of the files respectively. 1706 1707When the C<exUnixN> option is present it will trigger the creation of a 1708UnixN extra field (ID is "ux") in both the local and central zip headers. 1709This will be populated with C<$uid> and C<$gid>. 1710The UID & GID are stored as 32-bit integers. 1711 1712If the C<Minimal> option is set to true, this option will be ignored. 1713 1714By default no UnixN extra field is created. 1715 1716=item C<< Comment => $comment >> 1717 1718Stores the contents of C<$comment> in the Central File Header of 1719the zip file. 1720 1721Set the C<Efs> option to true if you want to store a UTF8 comment. 1722 1723By default, no comment field is written to the zip file. 1724 1725=item C<< ZipComment => $comment >> 1726 1727Stores the contents of C<$comment> in the End of Central Directory record 1728of the zip file. 1729 1730By default, no comment field is written to the zip file. 1731 1732=item C<< Method => $method >> 1733 1734Controls which compression method is used. At present the compression 1735methods supported are: Store (no compression at all), Deflate, 1736Bzip2, Zstd, Xz and Lzma. 1737 1738The symbols ZIP_CM_STORE, ZIP_CM_DEFLATE, ZIP_CM_BZIP2, ZIP_CM_ZSTD, ZIP_CM_XZ and ZIP_CM_LZMA 1739are used to select the compression method. 1740 1741These constants are not imported by C<IO::Compress::Zip> by default. 1742 1743 use IO::Compress::Zip qw(:zip_method); 1744 use IO::Compress::Zip qw(:constants); 1745 use IO::Compress::Zip qw(:all); 1746 1747Note that to create Bzip2 content, the module C<IO::Compress::Bzip2> must 1748be installed. A fatal error will be thrown if you attempt to create Bzip2 1749content when C<IO::Compress::Bzip2> is not available. 1750 1751Note that to create Lzma content, the module C<IO::Compress::Lzma> must 1752be installed. A fatal error will be thrown if you attempt to create Lzma 1753content when C<IO::Compress::Lzma> is not available. 1754 1755Note that to create Xz content, the module C<IO::Compress::Xz> must 1756be installed. A fatal error will be thrown if you attempt to create Xz 1757content when C<IO::Compress::Xz> is not available. 1758 1759Note that to create Zstd content, the module C<IO::Compress::Zstd> must 1760be installed. A fatal error will be thrown if you attempt to create Zstd 1761content when C<IO::Compress::Zstd> is not available. 1762 1763The default method is ZIP_CM_DEFLATE. 1764 1765=item C<< TextFlag => 0|1 >> 1766 1767This parameter controls the setting of a bit in the zip central header. It 1768is used to signal that the data stored in the zip file/buffer is probably 1769text. 1770 1771In one-shot mode this flag will be set to true if the Perl C<-T> operator thinks 1772the file contains text. 1773 1774The default is 0. 1775 1776=item C<< ExtraFieldLocal => $data >> 1777 1778=item C<< ExtraFieldCentral => $data >> 1779 1780The C<ExtraFieldLocal> option is used to store additional metadata in the 1781local header for the zip file/buffer. The C<ExtraFieldCentral> does the 1782same for the matching central header. 1783 1784An extra field consists of zero or more subfields. Each subfield consists 1785of a two byte header followed by the subfield data. 1786 1787The list of subfields can be supplied in any of the following formats 1788 1789 ExtraFieldLocal => [$id1, $data1, 1790 $id2, $data2, 1791 ... 1792 ] 1793 1794 ExtraFieldLocal => [ [$id1 => $data1], 1795 [$id2 => $data2], 1796 ... 1797 ] 1798 1799 ExtraFieldLocal => { $id1 => $data1, 1800 $id2 => $data2, 1801 ... 1802 } 1803 1804Where C<$id1>, C<$id2> are two byte subfield ID's. 1805 1806If you use the hash syntax, you have no control over the order in which 1807the ExtraSubFields are stored, plus you cannot have SubFields with 1808duplicate ID. 1809 1810Alternatively the list of subfields can by supplied as a scalar, thus 1811 1812 ExtraField => $rawdata 1813 1814In this case C<IO::Compress::Zip> will check that C<$rawdata> consists of 1815zero or more conformant sub-fields. 1816 1817The Extended Time field (ID "UT"), set using the C<exTime> option, and the 1818Unix2 extra field (ID "Ux), set using the C<exUnix2> option, are examples 1819of extra fields. 1820 1821If the C<Minimal> option is set to true, this option will be ignored. 1822 1823The maximum size of an extra field 65535 bytes. 1824 1825=item C<< Strict => 0|1 >> 1826 1827This is a placeholder option. 1828 1829=back 1830 1831=head2 Examples 1832 1833TODO 1834 1835=head1 Methods 1836 1837=head2 print 1838 1839Usage is 1840 1841 $z->print($data) 1842 print $z $data 1843 1844Compresses and outputs the contents of the C<$data> parameter. This 1845has the same behaviour as the C<print> built-in. 1846 1847Returns true if successful. 1848 1849=head2 printf 1850 1851Usage is 1852 1853 $z->printf($format, $data) 1854 printf $z $format, $data 1855 1856Compresses and outputs the contents of the C<$data> parameter. 1857 1858Returns true if successful. 1859 1860=head2 syswrite 1861 1862Usage is 1863 1864 $z->syswrite $data 1865 $z->syswrite $data, $length 1866 $z->syswrite $data, $length, $offset 1867 1868Compresses and outputs the contents of the C<$data> parameter. 1869 1870Returns the number of uncompressed bytes written, or C<undef> if 1871unsuccessful. 1872 1873=head2 write 1874 1875Usage is 1876 1877 $z->write $data 1878 $z->write $data, $length 1879 $z->write $data, $length, $offset 1880 1881Compresses and outputs the contents of the C<$data> parameter. 1882 1883Returns the number of uncompressed bytes written, or C<undef> if 1884unsuccessful. 1885 1886=head2 flush 1887 1888Usage is 1889 1890 $z->flush; 1891 $z->flush($flush_type); 1892 1893Flushes any pending compressed data to the output file/buffer. 1894 1895This method takes an optional parameter, C<$flush_type>, that controls 1896how the flushing will be carried out. By default the C<$flush_type> 1897used is C<Z_FINISH>. Other valid values for C<$flush_type> are 1898C<Z_NO_FLUSH>, C<Z_SYNC_FLUSH>, C<Z_FULL_FLUSH> and C<Z_BLOCK>. It is 1899strongly recommended that you only set the C<flush_type> parameter if 1900you fully understand the implications of what it does - overuse of C<flush> 1901can seriously degrade the level of compression achieved. See the C<zlib> 1902documentation for details. 1903 1904Returns true on success. 1905 1906=head2 tell 1907 1908Usage is 1909 1910 $z->tell() 1911 tell $z 1912 1913Returns the uncompressed file offset. 1914 1915=head2 eof 1916 1917Usage is 1918 1919 $z->eof(); 1920 eof($z); 1921 1922Returns true if the C<close> method has been called. 1923 1924=head2 seek 1925 1926 $z->seek($position, $whence); 1927 seek($z, $position, $whence); 1928 1929Provides a sub-set of the C<seek> functionality, with the restriction 1930that it is only legal to seek forward in the output file/buffer. 1931It is a fatal error to attempt to seek backward. 1932 1933Empty parts of the file/buffer will have NULL (0x00) bytes written to them. 1934 1935The C<$whence> parameter takes one the usual values, namely SEEK_SET, 1936SEEK_CUR or SEEK_END. 1937 1938Returns 1 on success, 0 on failure. 1939 1940=head2 binmode 1941 1942Usage is 1943 1944 $z->binmode 1945 binmode $z ; 1946 1947This is a noop provided for completeness. 1948 1949=head2 opened 1950 1951 $z->opened() 1952 1953Returns true if the object currently refers to a opened file/buffer. 1954 1955=head2 autoflush 1956 1957 my $prev = $z->autoflush() 1958 my $prev = $z->autoflush(EXPR) 1959 1960If the C<$z> object is associated with a file or a filehandle, this method 1961returns the current autoflush setting for the underlying filehandle. If 1962C<EXPR> is present, and is non-zero, it will enable flushing after every 1963write/print operation. 1964 1965If C<$z> is associated with a buffer, this method has no effect and always 1966returns C<undef>. 1967 1968B<Note> that the special variable C<$|> B<cannot> be used to set or 1969retrieve the autoflush setting. 1970 1971=head2 input_line_number 1972 1973 $z->input_line_number() 1974 $z->input_line_number(EXPR) 1975 1976This method always returns C<undef> when compressing. 1977 1978=head2 fileno 1979 1980 $z->fileno() 1981 fileno($z) 1982 1983If the C<$z> object is associated with a file or a filehandle, C<fileno> 1984will return the underlying file descriptor. Once the C<close> method is 1985called C<fileno> will return C<undef>. 1986 1987If the C<$z> object is associated with a buffer, this method will return 1988C<undef>. 1989 1990=head2 close 1991 1992 $z->close() ; 1993 close $z ; 1994 1995Flushes any pending compressed data and then closes the output file/buffer. 1996 1997For most versions of Perl this method will be automatically invoked if 1998the IO::Compress::Zip object is destroyed (either explicitly or by the 1999variable with the reference to the object going out of scope). The 2000exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In 2001these cases, the C<close> method will be called automatically, but 2002not until global destruction of all live objects when the program is 2003terminating. 2004 2005Therefore, if you want your scripts to be able to run on all versions 2006of Perl, you should call C<close> explicitly and not rely on automatic 2007closing. 2008 2009Returns true on success, otherwise 0. 2010 2011If the C<AutoClose> option has been enabled when the IO::Compress::Zip 2012object was created, and the object is associated with a file, the 2013underlying file will also be closed. 2014 2015=head2 newStream([OPTS]) 2016 2017Usage is 2018 2019 $z->newStream( [OPTS] ) 2020 2021Closes the current compressed data stream and starts a new one. 2022 2023OPTS consists of any of the options that are available when creating 2024the C<$z> object. 2025 2026See the L</"Constructor Options"> section for more details. 2027 2028=head2 deflateParams 2029 2030Usage is 2031 2032 $z->deflateParams 2033 2034TODO 2035 2036=head1 Importing 2037 2038A number of symbolic constants are required by some methods in 2039C<IO::Compress::Zip>. None are imported by default. 2040 2041=over 5 2042 2043=item :all 2044 2045Imports C<zip>, C<$ZipError> and all symbolic 2046constants that can be used by C<IO::Compress::Zip>. Same as doing this 2047 2048 use IO::Compress::Zip qw(zip $ZipError :constants) ; 2049 2050=item :constants 2051 2052Import all symbolic constants. Same as doing this 2053 2054 use IO::Compress::Zip qw(:flush :level :strategy :zip_method) ; 2055 2056=item :flush 2057 2058These symbolic constants are used by the C<flush> method. 2059 2060 Z_NO_FLUSH 2061 Z_PARTIAL_FLUSH 2062 Z_SYNC_FLUSH 2063 Z_FULL_FLUSH 2064 Z_FINISH 2065 Z_BLOCK 2066 2067=item :level 2068 2069These symbolic constants are used by the C<Level> option in the constructor. 2070 2071 Z_NO_COMPRESSION 2072 Z_BEST_SPEED 2073 Z_BEST_COMPRESSION 2074 Z_DEFAULT_COMPRESSION 2075 2076=item :strategy 2077 2078These symbolic constants are used by the C<Strategy> option in the constructor. 2079 2080 Z_FILTERED 2081 Z_HUFFMAN_ONLY 2082 Z_RLE 2083 Z_FIXED 2084 Z_DEFAULT_STRATEGY 2085 2086=item :zip_method 2087 2088These symbolic constants are used by the C<Method> option in the 2089constructor. 2090 2091 ZIP_CM_STORE 2092 ZIP_CM_DEFLATE 2093 ZIP_CM_BZIP2 2094 2095=back 2096 2097=head1 EXAMPLES 2098 2099=head2 Apache::GZip Revisited 2100 2101See L<IO::Compress::FAQ|IO::Compress::FAQ/"Apache::GZip Revisited"> 2102 2103=head2 Working with Net::FTP 2104 2105See L<IO::Compress::FAQ|IO::Compress::FAQ/"Compressed files and Net::FTP"> 2106 2107=head1 SUPPORT 2108 2109General feedback/questions/bug reports should be sent to 2110L<https://github.com/pmqs/IO-Compress/issues> (preferred) or 2111L<https://rt.cpan.org/Public/Dist/Display.html?Name=IO-Compress>. 2112 2113=head1 SEE ALSO 2114 2115L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzip>, L<IO::Uncompress::UnLzip>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Compress::Zstd>, L<IO::Uncompress::UnZstd>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress> 2116 2117L<IO::Compress::FAQ|IO::Compress::FAQ> 2118 2119L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>, 2120L<Archive::Tar|Archive::Tar>, 2121L<IO::Zlib|IO::Zlib> 2122 2123For RFC 1950, 1951 and 1952 see 2124L<https://datatracker.ietf.org/doc/html/rfc1950>, 2125L<https://datatracker.ietf.org/doc/html/rfc1951> and 2126L<https://datatracker.ietf.org/doc/html/rfc1952> 2127 2128The I<zlib> compression library was written by Jean-loup Gailly 2129C<gzip@prep.ai.mit.edu> and Mark Adler C<madler@alumni.caltech.edu>. 2130 2131The primary site for the I<zlib> compression library is 2132L<http://www.zlib.org>. 2133 2134The primary site for gzip is L<http://www.gzip.org>. 2135 2136=head1 AUTHOR 2137 2138This module was written by Paul Marquess, C<pmqs@cpan.org>. 2139 2140=head1 MODIFICATION HISTORY 2141 2142See the Changes file. 2143 2144=head1 COPYRIGHT AND LICENSE 2145 2146Copyright (c) 2005-2022 Paul Marquess. All rights reserved. 2147 2148This program is free software; you can redistribute it and/or 2149modify it under the same terms as Perl itself. 2150