Author: bodewig
Date: Thu Jul 28 16:13:13 2011
New Revision: 1151907

URL: http://svn.apache.org/viewvc?rev=1151907&view=rev
Log:
write ZIP64 end of central directory if anything has used ZIP64.  Right now 
this means never.  COMPRESS-150.

Modified:
    
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.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/ZipArchiveOutputStream.java
URL: 
http://svn.apache.org/viewvc/commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java?rev=1151907&r1=1151906&r2=1151907&view=diff
==============================================================================
--- 
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
 (original)
+++ 
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
 Thu Jul 28 16:13:13 2011
@@ -36,8 +36,11 @@ import org.apache.commons.compress.archi
 import org.apache.commons.compress.archivers.ArchiveOutputStream;
 
 import static org.apache.commons.compress.archivers.zip.ZipConstants.BYTE_MASK;
+import static 
org.apache.commons.compress.archivers.zip.ZipConstants.DEFLATE_MIN_VERSION;
+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;
 
 /**
  * Reimplementation of {@link java.util.zip.ZipOutputStream
@@ -178,8 +181,8 @@ public class ZipArchiveOutputStream exte
     /**
      * Holds the offsets of the LFH starts for each entry.
      */
-    private final Map<ZipArchiveEntry, byte[]> offsets =
-        new HashMap<ZipArchiveEntry, byte[]>();
+    private final Map<ZipArchiveEntry, Long> offsets =
+        new HashMap<ZipArchiveEntry, Long>();
 
     /**
      * The encoding to use for filenames and the file comment.
@@ -235,6 +238,13 @@ public class ZipArchiveOutputStream exte
     private UnicodeExtraFieldPolicy createUnicodeExtraFields = 
UnicodeExtraFieldPolicy.NEVER;
 
     /**
+     * Whether anything inside this archive has used a ZIP64 feature.
+     *
+     * @since Apache Commons Compress 1.3
+     */
+    private boolean hasUsedZip64 = false;
+
+    /**
      * Creates a new ZIP OutputStream filtering the underlying stream.
      * @param out the outputstream to zip
      */
@@ -352,6 +362,7 @@ public class ZipArchiveOutputStream exte
             writeCentralFileHeader(ze);
         }
         cdLength = written - cdOffset;
+        writeZip64CentralDirectory();
         writeCentralDirectoryEnd();
         offsets.clear();
         entries.clear();
@@ -614,6 +625,14 @@ public class ZipArchiveOutputStream exte
      * end of central dir signature
      */
     static final byte[] EOCD_SIG = ZipLong.getBytes(0X06054B50L);
+    /**
+     * ZIP64 end of central dir signature
+     */
+    static final byte[] ZIP64_EOCD_SIG = ZipLong.getBytes(0X06064B50L);
+    /**
+     * ZIP64 end of central dir locator signature
+     */
+    static final byte[] ZIP64_EOCD_LOC_SIG = ZipLong.getBytes(0X07064B50L);
 
     /**
      * Writes next block of compressed data to the output stream.
@@ -672,7 +691,7 @@ public class ZipArchiveOutputStream exte
             }
         }
 
-        offsets.put(ze, ZipLong.getBytes(written));
+        offsets.put(ze, Long.valueOf(written));
 
         writeOut(LFH_SIG);
         written += WORD;
@@ -759,7 +778,9 @@ public class ZipArchiveOutputStream exte
 
         // version made by
         // CheckStyle:MagicNumber OFF
-        writeOut(ZipShort.getBytes((ze.getPlatform() << 8) | 20));
+        writeOut(ZipShort.getBytes((ze.getPlatform() << 8) | 
+                                   (!hasUsedZip64 ? DEFLATE_MIN_VERSION
+                                                  : ZIP64_MIN_VERSION)));
         written += SHORT;
 
         final int zipMethod = ze.getMethod();
@@ -830,7 +851,7 @@ public class ZipArchiveOutputStream exte
         written += WORD;
 
         // relative offset of LFH
-        writeOut(offsets.get(ze));
+        writeOut(ZipLong.getBytes(offsets.get(ze).longValue()));
         written += WORD;
 
         // file name
@@ -872,6 +893,64 @@ public class ZipArchiveOutputStream exte
         writeOut(data.array(), data.arrayOffset(), data.limit());
     }
 
+    private static final byte[] ONE = ZipLong.getBytes(1L);
+
+    /**
+     * Writes the &quot;ZIP64 End of central dir record&quot; and &quot;ZIP64 
End of central dir locator&quot;.
+     * @throws IOException on error
+     * @since Apache Commons Compress 1.3
+     */
+    protected void writeZip64CentralDirectory() throws IOException {
+        if (!hasUsedZip64) {
+            return;
+        }
+
+        long offset = written;
+
+        writeOut(ZIP64_EOCD_SIG);
+        // size, we don't have any variable length as we don't support
+        // the extensible data sector, yet
+        writeOut(ZipEightByteInteger
+                 .getBytes(SHORT   /* version made by */
+                           + SHORT /* version needed to extract */
+                           + WORD  /* disk number */
+                           + WORD  /* disk with central directory */
+                           + DWORD /* number of entries in CD on this disk */
+                           + DWORD /* total number of entries */
+                           + DWORD /* size of CD */
+                           + DWORD /* offset of CD */
+                           ));
+
+        // version made by and version needed to extract
+        writeOut(ZipShort.getBytes(ZIP64_MIN_VERSION));
+        writeOut(ZipShort.getBytes(ZIP64_MIN_VERSION));
+
+        // disk numbers - four bytes this time
+        writeOut(LZERO);
+        writeOut(LZERO);
+
+        // number of entries
+        byte[] num = ZipEightByteInteger.getBytes(entries.size());
+        writeOut(num);
+        writeOut(num);
+
+        // length and location of CD
+        writeOut(ZipEightByteInteger.getBytes(cdLength));
+        writeOut(ZipEightByteInteger.getBytes(cdOffset));
+
+        // no "zip64 extensible data sector" for now
+
+        // and now the "ZIP64 end of central directory locator"
+        writeOut(ZIP64_EOCD_LOC_SIG);
+
+        // disk number holding the ZIP64 EOCD record
+        writeOut(LZERO);
+        // relative offset of ZIP64 EOCD record
+        writeOut(ZipEightByteInteger.getBytes(offset));
+        // total number of disks
+        writeOut(ONE);
+    }
+
     /**
      * Write bytes to output or random access file.
      * @param data the byte array to write

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=1151907&r1=1151906&r2=1151907&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
 Thu Jul 28 16:13:13 2011
@@ -37,6 +37,9 @@ final class ZipConstants {
     /** length of a ZipEightByteInteger in bytes */
     static final int DWORD = 8;
 
+    /** ZIP specification version that introduced DEFLATE method */
+    static final int DEFLATE_MIN_VERSION = 20;
+
     /** ZIP specification version that introduced ZIP64 */
     static final int ZIP64_MIN_VERSION = 45;
 }


Reply via email to