use strict; use warnings; use IO::File; use IO::Uncompress::RawInflate qw(rawinflate $RawInflateError); die "Usage: zipcat file" if @ARGV != 1 ; my $file = $ARGV[0] ; my $fh = new IO::File "<$file" or die "Cannot open '$file': $!\n"; while () { my $FIXED_HEADER_LENGTH = 30 ; my $sig; my $buffer; my $x ; ($x = $fh->read($buffer, $FIXED_HEADER_LENGTH)) == $FIXED_HEADER_LENGTH or die "Truncated file top: $x $!\n"; my $signature = unpack ("V", substr($buffer, 0, 4)); last unless $signature == 0x04034b50; my $compressedMethod = unpack ("v", substr($buffer, 8, 2)); my $compressedLength = unpack ("V", substr($buffer, 18, 4)); #my $uncompressedLength = unpack ("V", substr($buffer, 22, 4)); my $filename_length = unpack ("v", substr($buffer, 26, 2)); my $extra_length = unpack ("v", substr($buffer, 28, 2)); warn "Compressed Length $compressedLength\n"; my $filename ; $fh->read($filename, $filename_length) == $filename_length or die "Truncated file\n"; $fh->read($buffer, $extra_length) == $extra_length or die "Truncated file\n"; if ($compressedMethod != 8 && $compressedMethod != 0) { warn "Skipping file '$filename' - not deflated $compressedMethod\n"; $fh->read($buffer, $compressedLength) == $compressedLength or die "Truncated file\n"; next; } next if $compressedLength == 0; warn "Writing file '$filename' $compressedMethod\n"; mkpath basename $filename; rawinflate $fh => $filename, Transparent => 1, InputLength => $compressedLength or die "Error uncompressing $file [$filename]: $RawInflateError\n" ; } sub decodeLocalFileHeader { my $buffer = shift ; }