http://www.perlmonks.org?node_id=632286

sblanton has asked for the wisdom of the Perl Monks concerning the following question:

Hi All,
I'm having trouble using Archive::Zip to write a file that is then readable by the jar program (Sun JDK 1.5.0_10).

I want to take a JAR created elsewhere and modify a file inside it with perl an write it back out. However, after modification and writing out with Archive::Zip, the jar program gives an error when reading the contents. Here are the stripped down steps:

  1. Create foo.jar: 'jar cf foo.jar hello.txt'
  2. Run the following code:
  3. use Archive::Zip qw( :ERROR_CODES :CONSTANTS ); my $az_foo = Archive::Zip->new('foo.jar'); unless ($az_foo->writeToFileNamed('bar.jar') == AZ_OK ) { die 'write error'; } my $az_bar = Archive::Zip->new(); unless ( $az_bar->read('bar.jar') == AZ_OK ) { die 'bad bar bad!' }
    ** This gives no errors or warnings.**
  4. Now run 'jar tf bar.jar'. This gives the error:
    java.util.zip.ZipException: only DEFLATED entries can have EXT descrip +tor at java.util.zip.ZipInputStream.readLOC(ZipInputStream.java:250) at java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:7 +3) at sun.tools.jar.Main.list(Main.java:735) at sun.tools.jar.Main.run(Main.java:191) at sun.tools.jar.Main.main(Main.java:903)
I've done a lot of research and investigation without many fruits. Using 'zipinfo.pl' from the Archive::Zip examples/ did get me some clues:
  1. bar.jar is 2 bytes smaller than foo.jar
  2. The directory member for META-INF/ has a few different parameters between the two JAR's:
    • compressionMethod: foo.jar=8, bar.jar=0
    • desiredCompressionMethod: foo.jar=8, bar.jar=0
    • desiredCompressionLevel: foo.jar=-1, bar.jar=0
  3. I've tried manually setting these parameters on the member before writing out, but the values remain the same.

It seems to me the 'META-INF/' directory member is actually expected to be deflated by the jar program - doesn't make sense. I thought I'd ask those wiser than myself before contacting the owner on this one...maybe there is something simple I can do. Cheers and beers.

20070813 Janitored by Corion: Changed PRE tags to P tags, as per Writeup Formatting Tips

Replies are listed 'Best First'.
Re: Archive::Zip Problem: Zip versus Jar file formats
by Joost (Canon) on Aug 13, 2007 at 18:59 UTC
    this page suggests the problem is due to (parts of) the zip not being compressed.

    Did you set the desiredCompressionMethod to COMPRESSION_DEFLATED?

    If that doesn't help, (short) working code that exhibits the problem may shed some light. Alternatively, you could try using an external command-line driven zip program instead of Archive::Zip.

    update: I did some experimenting, and I've got nothing. I note that jar can be very picky about its input format, and that although I've used Info-ZIP on linux to create/modify some working jars, I've also run into problems with it (anecdotal - I's been a few years since I tried any of that). Conservative advice would be to unpack the jar however you like it, modify whatever you need, and use the jar program to create a new jar, since that at least should work.

Re: Archive::Zip Problem: Zip versus Jar file formats
by jimbojones (Friar) on Aug 15, 2007 at 15:50 UTC
    Hi

    The Archive::Zip module will not compress members if the uncompressed size is 0. However, the jar command seems to add an additional "external local header" to the data.

    So, when A::Z writes out the data, since it thinks it's 0 bytes, it writes out uncompressed, but also writes ou the external header(?), giving you the "only DEFLATED entries can have EXT descriptor" error.

    This link seems to show something similar in python that might have some insights:

    http://mail.python.org/pipermail/python-bugs-list/2007-June/038900.html

    I tested this with A::Z v1.20, and I think it's a bug with A::Z. I was poking around in A::Z::Member::rewindData to see what it does with 0 byte compressed data.

    Also, running zip against the file gives:

    >zip bar.jar zip warning: extended local header not found for META-INF/ zip error: Zip file structure invalid (bar.jar)
    Hope this helps, Jim

      Thanks Jimbo and Joost. I wanted a second opinion before I opened an issue and these insights will help me more effectively communicate the issue to the author. Cheers
        Yeah, I was able to reproduce this purely with the zip
        program, so I know it is not a subtle oddity of format for JAR's.