Author: bodewig
Date: Wed Aug 3 09:55:53 2011
New Revision: 1153415
URL: http://svn.apache.org/viewvc?rev=1153415&view=rev
Log:
don't rely on archives to implement ZIP64 correctly when reading the data
descriptor. Works around a bug in java.util.ZipArchiveOutputStream of Java7,
may be useful for other implementations as well. COMPRESS-148
Modified:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/Zip64SupportTest.java
Modified:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java?rev=1153415&r1=1153414&r2=1153415&view=diff
==============================================================================
---
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
(original)
+++
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
Wed Aug 3 09:55:53 2011
@@ -457,9 +457,7 @@ public class ZipArchiveInputStream exten
// Pushback any required bytes
if (diff > 0) {
- ((PushbackInputStream) in).unread(
- buf, lengthOfLastRead - diff, diff);
- pushedBackBytes(diff);
+ pushback(buf, lengthOfLastRead - diff, diff);
}
}
@@ -506,17 +504,29 @@ public class ZipArchiveInputStream exten
val = new ZipLong(b);
}
current.setCrc(val.getValue());
- if (!usesZip64) {
- readFully(b);
+
+ // if there is a ZIP64 extra field, sizes are eight bytes
+ // each, otherwise four bytes each. Unfortunately some
+ // implementations - namely Java7 - use eight bytes without
+ // using a ZIP64 extra field -
+ // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7073588
+
+ // just read 16 bytes and check whether bytes nine to twelve
+ // look like one of the signatures of what could follow a data
+ // descriptor (ignoring archive decryption headers for now).
+ // If so, push back eight bytes and assume sizes are four
+ // bytes, otherwise sizes are eight bytes each.
+ b = new byte[2 * DWORD];
+ readFully(b);
+ ZipLong potentialSig = new ZipLong(b, DWORD);
+ if (potentialSig.equals(ZipLong.CFH_SIG)
+ || potentialSig.equals(ZipLong.LFH_SIG)) {
+ pushback(b, DWORD, DWORD);
current.setCompressedSize(ZipLong.getValue(b));
- readFully(b);
- current.setSize(ZipLong.getValue(b));
+ current.setSize(ZipLong.getValue(b, WORD));
} else {
- byte[] b8 = new byte[DWORD];
- readFully(b8);
- current.setCompressedSize(ZipEightByteInteger.getLongValue(b8));
- readFully(b8);
- current.setSize(ZipEightByteInteger.getLongValue(b8));
+ current.setCompressedSize(ZipEightByteInteger.getLongValue(b));
+ current.setSize(ZipEightByteInteger.getLongValue(b, DWORD));
}
}
@@ -593,7 +603,7 @@ public class ZipArchiveInputStream exten
// descriptor
// * copy the remaining bytes to cache
// * read data descriptor
- ((PushbackInputStream) in).unread(buf, off + r -
readTooMuch, readTooMuch);
+ pushback(buf, off + r - readTooMuch, readTooMuch);
bos.write(buf, 0, i);
readDataDescriptor();
}
@@ -619,4 +629,10 @@ public class ZipArchiveInputStream exten
byte[] b = bos.toByteArray();
lastStoredEntry = new ByteArrayInputStream(b);
}
+
+ private void pushback(byte[] buf, int offset, int length)
+ throws IOException {
+ ((PushbackInputStream) in).unread(buf, offset, length);
+ pushedBackBytes(length);
+ }
}
Modified:
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/Zip64SupportTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/Zip64SupportTest.java?rev=1153415&r1=1153414&r2=1153415&view=diff
==============================================================================
---
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/Zip64SupportTest.java
(original)
+++
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/Zip64SupportTest.java
Wed Aug 3 09:55:53 2011
@@ -53,11 +53,7 @@ public class Zip64SupportTest {
@Test public void read5GBOfZerosGeneratedByJava7JarUsingInputStream()
throws Throwable {
- // don't check the size in jar case as jar uses 8-Byte values
- // inside the data descriptor without adding a ZIP64 extra
- // field, violating the "spec".
- read5GBOfZerosImpl(get5GBZerosFileGeneratedByJava7Jar(),
"5GB_of_Zeros",
- false);
+ read5GBOfZerosImpl(get5GBZerosFileGeneratedByJava7Jar(),
"5GB_of_Zeros");
}
@Test public void read100KFilesUsingInputStream() throws Throwable {
@@ -1340,12 +1336,6 @@ public class Zip64SupportTest {
private static void read5GBOfZerosImpl(File f, String expectedName)
throws IOException {
- read5GBOfZerosImpl(f, expectedName, true);
- }
-
- private static void read5GBOfZerosImpl(File f, String expectedName,
- boolean checkSize)
- throws IOException {
FileInputStream fin = new FileInputStream(f);
ZipArchiveInputStream zin = null;
try {
@@ -1367,9 +1357,7 @@ public class Zip64SupportTest {
}
assertEquals(FIVE_BILLION, read);
assertNull(zin.getNextZipEntry());
- if (checkSize) {
- assertEquals(FIVE_BILLION, zae.getSize());
- }
+ assertEquals(FIVE_BILLION, zae.getSize());
} finally {
if (zin != null) {
zin.close();