You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by bo...@apache.org on 2009/02/19 17:42:17 UTC

svn commit: r745920 - in /commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip: ZipArchiveOutputStream.java ZipFile.java

Author: bodewig
Date: Thu Feb 19 16:42:16 2009
New Revision: 745920

URL: http://svn.apache.org/viewvc?rev=745920&view=rev
Log:
SANDBOX-176 - use and detect the EFS flag.  Based on submissions made by Wolfgang Glas to commons-compress and TAMURA Kent to Ant.

Modified:
    commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
    commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java

Modified: commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
URL: http://svn.apache.org/viewvc/commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java?rev=745920&r1=745919&r2=745920&view=diff
==============================================================================
--- commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java (original)
+++ commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java Thu Feb 19 16:42:16 2009
@@ -94,9 +94,20 @@
     public static final int STORED = java.util.zip.ZipEntry.STORED;
 
     /**
+     * name of the encoding UTF-8
+     */
+    static final String UTF8 = "UTF8";
+
+    /**
      * default encoding for file names and comment.
      */
-    static final String DEFAULT_ENCODING = "UTF8";
+    static final String DEFAULT_ENCODING = UTF8;
+
+     /**
+     * General purpose flag, which indicates that filenames are
+     * written in utf-8.
+     */
+    public static final int EFS_FLAG = 1 << 11;
 
     /**
      * Current entry.
@@ -254,6 +265,11 @@
     private final OutputStream out;
 
     /**
+     * whether to use the EFS flag when writing UTF-8 filenames or not.
+     */
+    private boolean useEFS = true; 
+
+    /**
      * Creates a new ZIP OutputStream filtering the underlying stream.
      * @param out the outputstream to zip
      * @since 1.1
@@ -312,8 +328,9 @@
      * for the platform's default encoding
      * @since 1.3
      */
-    public void setEncoding(String encoding) {
+    public void setEncoding(final String encoding) {
         this.encoding = encoding;
+        useEFS &= isUTF8(encoding);
     }
 
     /**
@@ -328,6 +345,15 @@
     }
 
     /**
+     * Whether to set the EFS flag if the file name encoding is UTF-8.
+     *
+     * <p>Defaults to true.</p>
+     */
+    public void setUseEFS(boolean b) {
+        useEFS = b && isUTF8(encoding);
+    }
+
+    /**
      * Finishs writing the contents and closes this as well as the
      * underlying stream.
      *
@@ -646,21 +672,7 @@
         //store method in local variable to prevent multiple method calls
         final int zipMethod = ze.getMethod();
 
-        // version needed to extract
-        // general purpose bit flag
-        // CheckStyle:MagicNumber OFF
-        if (zipMethod == DEFLATED && raf == null) {
-            // requires version 2 as we are going to store length info
-            // in the data descriptor
-            writeOut(ZipShort.getBytes(20));
-
-            // bit3 set to signal, we use a data descriptor
-            writeOut(ZipShort.getBytes(8));
-        } else {
-            writeOut(ZipShort.getBytes(10));
-            writeOut(ZERO);
-        }
-        // CheckStyle:MagicNumber ON
+        writeVersionNeededToExtractAndGeneralPurposeBits(zipMethod);
         written += WORD;
 
         // compression method
@@ -745,24 +757,12 @@
         writeOut(ZipShort.getBytes((ze.getPlatform() << 8) | 20));
         written += SHORT;
 
-        // version needed to extract
-        // general purpose bit flag
-        if (ze.getMethod() == DEFLATED && raf == null) {
-            // requires version 2 as we are going to store length info
-            // in the data descriptor
-            writeOut(ZipShort.getBytes(20));
-
-            // bit3 set to signal, we use a data descriptor
-            writeOut(ZipShort.getBytes(8));
-        } else {
-            writeOut(ZipShort.getBytes(10));
-            writeOut(ZERO);
-        }
-        // CheckStyle:MagicNumber ON
+        final int zipMethod = ze.getMethod();
+        writeVersionNeededToExtractAndGeneralPurposeBits(zipMethod);
         written += WORD;
 
         // compression method
-        writeOut(ZipShort.getBytes(ze.getMethod()));
+        writeOut(ZipShort.getBytes(zipMethod));
         written += SHORT;
 
         // last mod. time and date
@@ -904,19 +904,14 @@
      * this Stream.
      * @param name the string to get bytes from
      * @return the bytes as a byte array
-     * @throws ZipException on error
      *
      * @since 1.3
      */
-    protected byte[] getBytes(String name) throws ZipException {
+    protected byte[] getBytes(String name) {
         if (encoding == null) {
             return name.getBytes();
         } else {
-            try {
-                return name.getBytes(encoding);
-            } catch (UnsupportedEncodingException uee) {
-                throw new ZipException(uee.getMessage());
-            }
+            return ZipEncodingHelper.encodeName(name, encoding);
         }
     }
 
@@ -970,4 +965,38 @@
         }
     }
 
+    /**
+     * Whether a given encoding - or the platform's default encoding
+     * if the parameter is null - is UTF-8.
+     */
+    static boolean isUTF8(String encoding) {
+        if (encoding == null) {
+            // check platform's default encoding
+            encoding = System.getProperty("file.encoding");
+        }
+        return UTF8.equalsIgnoreCase(encoding)
+            || "utf-8".equalsIgnoreCase(encoding);
+    }
+
+    private void writeVersionNeededToExtractAndGeneralPurposeBits(final int
+                                                                  zipMethod)
+        throws IOException {
+
+        // CheckStyle:MagicNumber OFF
+        int versionNeededToExtract = 10;
+        int generalPurposeFlag = useEFS ? EFS_FLAG : 0;
+        if (zipMethod == DEFLATED && raf == null) {
+            // requires version 2 as we are going to store length info
+            // in the data descriptor
+            versionNeededToExtract =  20;
+            // bit3 set to signal, we use a data descriptor
+            generalPurposeFlag |= 8;
+        }
+        // CheckStyle:MagicNumber ON
+
+        // version needed to extract
+        writeOut(ZipShort.getBytes(versionNeededToExtract));
+        // general purpose bit flag
+        writeOut(ZipShort.getBytes(generalPurposeFlag));
+    }
 }

Modified: commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java
URL: http://svn.apache.org/viewvc/commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java?rev=745920&r1=745919&r2=745920&view=diff
==============================================================================
--- commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java (original)
+++ commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java Thu Feb 19 16:42:16 2009
@@ -108,7 +108,7 @@
      * @throws IOException if an error occurs while reading the file.
      */
     public ZipFile(File f) throws IOException {
-        this(f, ZipArchiveOutputStream.DEFAULT_ENCODING);
+        this(f, ZipArchiveOutputStream.UTF8);
     }
 
     /**
@@ -119,7 +119,7 @@
      * @throws IOException if an error occurs while reading the file.
      */
     public ZipFile(String name) throws IOException {
-        this(new File(name), ZipArchiveOutputStream.DEFAULT_ENCODING);
+        this(new File(name), ZipArchiveOutputStream.UTF8);
     }
 
     /**
@@ -293,7 +293,15 @@
             off += SHORT;
             ze.setPlatform((versionMadeBy >> BYTE_SHIFT) & NIBLET_MASK);
 
-            off += WORD; // skip version info and general purpose byte
+            off += SHORT; // skip version info
+
+            final int generalPurposeFlag = ZipShort.getValue(cfh, off);
+            final String entryEncoding = 
+                (generalPurposeFlag & ZipArchiveOutputStream.EFS_FLAG) != 0
+                ? ZipArchiveOutputStream.UTF8
+                : encoding;
+
+            off += SHORT;
 
             ze.setMethod(ZipShort.getValue(cfh, off));
             off += SHORT;
@@ -333,8 +341,7 @@
 
             byte[] fileName = new byte[fileNameLen];
             archive.readFully(fileName);
-            ze.setName(getString(fileName));
-
+            ze.setName(getString(fileName, entryEncoding));
 
             // LFH offset,
             OffsetEntry offset = new OffsetEntry();
@@ -356,7 +363,7 @@
 
             byte[] comment = new byte[commentLen];
             archive.readFully(comment);
-            ze.setComment(getString(comment));
+            ze.setComment(getString(comment, entryEncoding));
 
             archive.readFully(signatureBytes);
             sig = ZipLong.getValue(signatureBytes);
@@ -525,12 +532,13 @@
      * @return String obtained by using the given encoding
      * @throws ZipException if the encoding cannot be recognized.
      */
-    protected String getString(byte[] bytes) throws ZipException {
-        if (encoding == null) {
+    protected String getString(byte[] bytes, String enc)
+        throws ZipException {
+        if (enc == null) {
             return new String(bytes);
         } else {
             try {
-                return new String(bytes, encoding);
+                return new String(bytes, enc);
             } catch (UnsupportedEncodingException uee) {
                 throw new ZipException(uee.getMessage());
             }