Author: bodewig
Date: Thu Feb 19 17:19:23 2009
New Revision: 745930

URL: http://svn.apache.org/viewvc?rev=745930&view=rev
Log:
Support more modern encoding flag where archives signal filenames as UTF-8.  
Based on submissions by Wolfgang Glas to commons-compress and TAMURA Kent to 
Ant.  PR 45548.

Modified:
    ant/core/trunk/CONTRIBUTORS
    ant/core/trunk/WHATSNEW
    ant/core/trunk/contributors.xml
    ant/core/trunk/src/main/org/apache/tools/zip/ZipFile.java   (contents, 
props changed)
    ant/core/trunk/src/main/org/apache/tools/zip/ZipOutputStream.java   
(contents, props changed)

Modified: ant/core/trunk/CONTRIBUTORS
URL: 
http://svn.apache.org/viewvc/ant/core/trunk/CONTRIBUTORS?rev=745930&r1=745929&r2=745930&view=diff
==============================================================================
Binary files - no diff available.

Modified: ant/core/trunk/WHATSNEW
URL: 
http://svn.apache.org/viewvc/ant/core/trunk/WHATSNEW?rev=745930&r1=745929&r2=745930&view=diff
==============================================================================
--- ant/core/trunk/WHATSNEW (original)
+++ ant/core/trunk/WHATSNEW Thu Feb 19 17:19:23 2009
@@ -351,6 +351,11 @@
  * The zip package now supports the extra fields invented by InfoZIP
    in order to store Unicode file names and comments.
 
+ * The zip package detects the encoding bit set by more modern
+   archivers when they write UTF-8 filenames and optionally sets it
+   when writing zips or jars.
+   Bugzilla Report 45548
+
 Other changes:
 --------------
  * A HostInfo task was added performing information on hosts, including info 
on 

Modified: ant/core/trunk/contributors.xml
URL: 
http://svn.apache.org/viewvc/ant/core/trunk/contributors.xml?rev=745930&r1=745929&r2=745930&view=diff
==============================================================================
--- ant/core/trunk/contributors.xml (original)
+++ ant/core/trunk/contributors.xml Thu Feb 19 17:19:23 2009
@@ -1147,6 +1147,10 @@
     <last>Okamoto</last>
   </name>
   <name>
+    <first>TAMURA</first>
+    <last>Kent</last>
+  </name>
+  <name>
     <first>Taoufik</first>
     <last>Romdhane</last>
   </name>

Modified: ant/core/trunk/src/main/org/apache/tools/zip/ZipFile.java
URL: 
http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/zip/ZipFile.java?rev=745930&r1=745929&r2=745930&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/zip/ZipFile.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/zip/ZipFile.java Thu Feb 19 
17:19:23 2009
@@ -294,7 +294,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 & ZipOutputStream.EFS_FLAG) != 0
+                ? ZipOutputStream.UTF8
+                : encoding;
+
+            off += SHORT;
 
             ze.setMethod(ZipShort.getValue(cfh, off));
             off += SHORT;
@@ -334,8 +342,7 @@
 
             byte[] fileName = new byte[fileNameLen];
             archive.readFully(fileName);
-            ze.setName(getString(fileName));
-
+            ze.setName(getString(fileName, entryEncoding));
 
             // LFH offset,
             OffsetEntry offset = new OffsetEntry();
@@ -357,7 +364,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);
@@ -527,11 +534,24 @@
      * @throws ZipException if the encoding cannot be recognized.
      */
     protected String getString(byte[] bytes) throws ZipException {
-        if (encoding == null) {
+        return getString(bytes, encoding);
+    }
+
+    /**
+     * Retrieve a String from the given bytes using the encoding set
+     * for this ZipFile.
+     *
+     * @param bytes the byte array to transform
+     * @return String obtained by using the given encoding
+     * @throws ZipException if the encoding cannot be recognized.
+     */
+    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());
             }

Propchange: ant/core/trunk/src/main/org/apache/tools/zip/ZipFile.java
------------------------------------------------------------------------------
--- svn:mergeinfo (added)
+++ svn:mergeinfo Thu Feb 19 17:19:23 2009
@@ -0,0 +1 @@
+/commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java:745920

Modified: ant/core/trunk/src/main/org/apache/tools/zip/ZipOutputStream.java
URL: 
http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/zip/ZipOutputStream.java?rev=745930&r1=745929&r2=745930&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/zip/ZipOutputStream.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/zip/ZipOutputStream.java Thu Feb 
19 17:19:23 2009
@@ -92,6 +92,17 @@
     public static final int STORED = java.util.zip.ZipEntry.STORED;
 
     /**
+     * name of the encoding UTF-8
+     */
+    static final String UTF8 = "UTF8";
+
+     /**
+     * General purpose flag, which indicates that filenames are
+     * written in utf-8.
+     */
+    public static final int EFS_FLAG = 1 << 11;
+
+    /**
      * Current entry.
      *
      * @since 1.1
@@ -245,6 +256,11 @@
     private RandomAccessFile raf = null;
 
     /**
+     * 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
@@ -302,8 +318,9 @@
      * @param encoding the encoding value
      * @since 1.3
      */
-    public void setEncoding(String encoding) {
+    public void setEncoding(final String encoding) {
         this.encoding = encoding;
+        useEFS &= isUTF8(encoding);
     }
 
     /**
@@ -318,6 +335,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.
      *
@@ -620,21 +646,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
@@ -719,24 +731,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
@@ -887,10 +887,16 @@
             return name.getBytes();
         } else {
             try {
+                return ZipEncodingHelper.encodeName(name, encoding);
+            } catch (java.nio.charset.UnsupportedCharsetException ex) {
+            // Java 1.4's NIO doesn't recognize a few names that
+            // String.getBytes does
+            try {
                 return name.getBytes(encoding);
             } catch (UnsupportedEncodingException uee) {
                 throw new ZipException(uee.getMessage());
             }
+            }
         }
     }
 
@@ -944,4 +950,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));
+    }
 }

Propchange: ant/core/trunk/src/main/org/apache/tools/zip/ZipOutputStream.java
------------------------------------------------------------------------------
--- svn:mergeinfo (added)
+++ svn:mergeinfo Thu Feb 19 17:19:23 2009
@@ -0,0 +1 @@
+/commons/sandbox/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java:745920


Reply via email to