Author: bodewig
Date: Mon Jul 25 20:14:59 2011
New Revision: 1150878

URL: http://svn.apache.org/viewvc?rev=1150878&view=rev
Log:
first cut at reading Zip64 without any real tests, yet.  At least the existing 
test still pass.  COMPRESS-148

Modified:
    
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/Zip64ExtendedInformationExtraField.java
    
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
    
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipConstants.java

Modified: 
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/Zip64ExtendedInformationExtraField.java
URL: 
http://svn.apache.org/viewvc/commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/Zip64ExtendedInformationExtraField.java?rev=1150878&r1=1150877&r2=1150878&view=diff
==============================================================================
--- 
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/Zip64ExtendedInformationExtraField.java
 (original)
+++ 
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/Zip64ExtendedInformationExtraField.java
 Mon Jul 25 20:14:59 2011
@@ -77,7 +77,7 @@ public class Zip64ExtendedInformationExt
     // to see whether they do have a problem with the extraneous
     // information inside the LFH
 
-    private static final ZipShort HEADER_ID = new ZipShort(0x0001);
+    static final ZipShort HEADER_ID = new ZipShort(0x0001);
 
     private static final int WORD = 4, DWORD = 8;
 

Modified: 
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
URL: 
http://svn.apache.org/viewvc/commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java?rev=1150878&r1=1150877&r2=1150878&view=diff
==============================================================================
--- 
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
 (original)
+++ 
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
 Mon Jul 25 20:14:59 2011
@@ -32,8 +32,11 @@ import java.util.zip.ZipException;
 import org.apache.commons.compress.archivers.ArchiveEntry;
 import org.apache.commons.compress.archivers.ArchiveInputStream;
 
+import static org.apache.commons.compress.archivers.zip.ZipConstants.BYTE_MASK;
+import static org.apache.commons.compress.archivers.zip.ZipConstants.DWORD;
 import static org.apache.commons.compress.archivers.zip.ZipConstants.SHORT;
 import static org.apache.commons.compress.archivers.zip.ZipConstants.WORD;
+import static 
org.apache.commons.compress.archivers.zip.ZipConstants.ZIP64_MIN_VERSION;
 
 /**
  * Implements an input stream that can read Zip archives.
@@ -72,6 +75,7 @@ public class ZipArchiveInputStream exten
     private long readBytesOfEntry = 0, bytesReadFromStream = 0;
     private int lengthOfLastRead = 0;
     private boolean hasDataDescriptor = false;
+    private boolean usesZip64 = false;
     private ByteArrayInputStream lastStoredEntry = null;
 
     private boolean allowStoredEntriesWithDataDescriptor = false;
@@ -153,6 +157,7 @@ public class ZipArchiveInputStream exten
         current = new ZipArchiveEntry();
 
         int versionMadeBy = ZipShort.getValue(lfh, off);
+        usesZip64 = (versionMadeBy & BYTE_MASK) >= ZIP64_MIN_VERSION;
         off += SHORT;
         current.setPlatform((versionMadeBy >> ZipFile.BYTE_SHIFT)
                             & ZipFile.NIBLET_MASK);
@@ -173,14 +178,15 @@ public class ZipArchiveInputStream exten
         current.setTime(time);
         off += WORD;
 
+        ZipLong size = null, cSize = null;
         if (!hasDataDescriptor) {
             current.setCrc(ZipLong.getValue(lfh, off));
             off += WORD;
 
-            current.setCompressedSize(ZipLong.getValue(lfh, off));
+            cSize = new ZipLong(lfh, off);
             off += WORD;
 
-            current.setSize(ZipLong.getValue(lfh, off));
+            size = new ZipLong(lfh, off);
             off += WORD;
         } else {
             off += 3 * WORD;
@@ -204,6 +210,25 @@ public class ZipArchiveInputStream exten
         if (!hasUTF8Flag && useUnicodeExtraFields) {
             ZipUtil.setNameAndCommentFromExtraFields(current, fileName, null);
         }
+        if (!hasDataDescriptor) {
+            if (usesZip64 && (cSize.equals(ZipLong.ZIP64_MAGIC)
+                              || size.equals(ZipLong.ZIP64_MAGIC))
+                ) {
+                Zip64ExtendedInformationExtraField z64 =
+                    (Zip64ExtendedInformationExtraField)
+                    current.getExtraField(Zip64ExtendedInformationExtraField
+                                          .HEADER_ID);
+                if (z64 == null) {
+                    throw new ZipException("expected ZIP64 extra field");
+                }
+                current.setCompressedSize(z64.getCompressedSize()
+                                          .getLongValue());
+                current.setSize(z64.getSize().getLongValue());
+            } else {
+                current.setCompressedSize(cSize.getValue());
+                current.setSize(size.getValue());
+            }
+        }
         return current;
     }
 
@@ -485,10 +510,18 @@ public class ZipArchiveInputStream exten
             val = new ZipLong(b);
         }
         current.setCrc(val.getValue());
+        if (!usesZip64) {
         readFully(b);
         current.setCompressedSize(new ZipLong(b).getValue());
         readFully(b);
         current.setSize(new ZipLong(b).getValue());
+        } else {
+            byte[] b8 = new byte[DWORD];
+            readFully(b8);
+            current.setCompressedSize(ZipEightByteInteger.getLongValue(b8));
+            readFully(b8);
+            current.setSize(ZipEightByteInteger.getLongValue(b8));
+        }
     }
 
     /**
@@ -529,6 +562,9 @@ public class ZipArchiveInputStream exten
         int off = 0;
         boolean done = false;
 
+        // length of DD without signature
+        int ddLen = usesZip64 ? WORD + 2 * DWORD : 3 * WORD;
+
         while (!done) {
             int r = in.read(buf, off, ZipArchiveOutputStream.BUFFER_SIZE - 
off);
             if (r <= 0) {
@@ -548,7 +584,7 @@ public class ZipArchiveInputStream exten
                     if ((buf[i + 2] == LFH[2] && buf[i + 3] == LFH[3])
                         || (buf[i] == CFH[2] && buf[i + 3] == CFH[3])) {
                         // found a LFH or CFH:
-                        readTooMuch = off + r - i - 12 /* dd without signature 
*/;
+                        readTooMuch = off + r - i - ddLen;
                         done = true;
                     }
                     else if (buf[i + 2] == DD[2] && buf[i + 3] == DD[3]) {
@@ -569,14 +605,15 @@ public class ZipArchiveInputStream exten
             }
             if (!done) {
                 // worst case we've read a data descriptor without a
-                // signature (12 bytes) plus the first three bytes of
+                // signature (up to 20 bytes) plus the first three bytes of
                 // a LFH or CFH signature
-                // save the last 15 bytes in the buffer, cache
+                // save the last ddLen + 3 bytes in the buffer, cache
                 // anything in front of that, read on
-                if (off + r > 15) {
-                    bos.write(buf, 0, off + r - 15);
-                    System.arraycopy(buf, off + r - 15, buf, 0, 15);
-                    off = 15;
+                if (off + r > ddLen + 3) {
+                    bos.write(buf, 0, off + r - ddLen - 3);
+                    System.arraycopy(buf, off + r - ddLen - 3, buf, 0,
+                                     ddLen + 3);
+                    off = ddLen + 3;
                 } else {
                     off += r;
                 }

Modified: 
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipConstants.java
URL: 
http://svn.apache.org/viewvc/commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipConstants.java?rev=1150878&r1=1150877&r2=1150878&view=diff
==============================================================================
--- 
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipConstants.java
 (original)
+++ 
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipConstants.java
 Mon Jul 25 20:14:59 2011
@@ -33,4 +33,10 @@ final class ZipConstants {
 
     /** length of a ZipLong in bytes */
     static final int WORD = 4;
+
+    /** length of a ZipEightByteInteger in bytes */
+    static final int DWORD = 8;
+
+    /** ZIP specification version that introduced ZIP64 */
+    static final int ZIP64_MIN_VERSION = 45;
 }


Reply via email to