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()); }