redhotpenguin / perl-Archive-Zip

Archive::Zip as seen at https://metacpan.org/pod/Archive::Zip
Other
15 stars 44 forks source link

maximum deflated file is not inflatable with winzip #84

Open tomk3003 opened 3 years ago

tomk3003 commented 3 years ago

I tracked down a strange problem with winzip that couldn't inflate files with compression levels 8 and 9 packed by Achive::Zip. Comparing it with a file created by a command line zip under linux showed an incorrect bitmask in the file member header.

after changing

https://github.com/redhotpenguin/perl-Archive-Zip/blob/340cd7ea81ecd0b55ca4a2bfd2331c2787cc77f7/lib/Archive/Zip/Member.pm#L893

to

$self->bitFlag(),

The bitmask was correct and winzip inflated the file correctly. The accessor sets values and has to be called before data is written to file.

Used example:

use strict;
use warnings;

use Archive::Zip qw( :ERROR_CODES :CONSTANTS );

my $txt = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';

my $zip = Archive::Zip->new();
my $member = $zip->addString($txt, "lorem_ipsum.txt");
$member->desiredCompressionMethod(COMPRESSION_DEFLATED);
$member->desiredCompressionLevel(9);

$zip->writeToFileNamed('ptest.zip');
pmqs commented 3 years ago

@tomk3003 does winzip give any details about why it won't uncompress the zip file?

I can reproduce the issue with the code you supplied. Below is a dump of the ptest.zip file the code creates. Note that the General Purpose Flag for the LOCAL HEADER has a value of 0, while the CENTRAL HEADER has a value of 2. That is a bug -- the values should be identical.

I can confirm that your proposed change does fix the issue.

0000 LOCAL HEADER #1       04034B50
0004 Extract Zip Spec      14 '2.0'
0005 Extract OS            00 'MS-DOS'
0006 General Purpose Flag  0000
     [Bits 1-2]            0 'Normal Compression'
0008 Compression Method    0008 'Deflated'
000A Last Mod Time         52264AB8 'Wed Jan  6 09:21:48 2021'
000E CRC                   98B2C5BD
0012 Compressed Length     00000108
0016 Uncompressed Length   000001BD
001A Filename Length       000F
001C Extra Length          0000
001E Filename              'lorem_ipsum.txt'
002D PAYLOAD

0135 CENTRAL HEADER #1     02014B50
0139 Created Zip Spec      14 '2.0'
013A Created OS            03 'Unix'
013B Extract Zip Spec      14 '2.0'
013C Extract OS            00 'MS-DOS'
013D General Purpose Flag  0002
     [Bits 1-2]            1 'Maximum Compression'
013F Compression Method    0008 'Deflated'
0141 Last Mod Time         52264AB8 'Wed Jan  6 09:21:48 2021'
0145 CRC                   98B2C5BD
0149 Compressed Length     00000108
014D Uncompressed Length   000001BD
0151 Filename Length       000F
0153 Extra Length          0000
0155 Comment Length        0000
0157 Disk Start            0000
0159 Int File Attributes   0000
     [Bit 0]               0 'Binary Data'
015B Ext File Attributes   81B60000
015F Local Header Offset   00000000
0163 Filename              'lorem_ipsum.txt'

0172 END CENTRAL HEADER    06054B50
0176 Number of this disk   0000
0178 Central Dir Disk no   0000
017A Entries in this disk  0001
017C Total Entries         0001
017E Size of Central Dir   0000003D
0182 Offset to Central Dir 00000135
0186 Comment Length        0000
Done
tomk3003 commented 3 years ago

The error message is: Central and local directory mismatch for file "lorem_ipsum.txt", (general purpose flags - local: 0 hex central 2 hex) This matches our analysis.

pmqs commented 3 years ago

created https://github.com/redhotpenguin/perl-Archive-Zip/pull/85 to get the fix included.