diff options
author | Elliott Hughes <enh@google.com> | 2010-02-04 17:44:29 -0800 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2010-02-04 18:16:12 -0800 |
commit | 6bd77683de703a6df640e863b38a73041e8c0c1b (patch) | |
tree | 0eed35051704d64be8cf4f159f01b0dd89c8a2cd /archive | |
parent | d1ad0f9ac67ca845b62a60c868f21a4cff210b78 (diff) | |
download | libcore-6bd77683de703a6df640e863b38a73041e8c0c1b.zip libcore-6bd77683de703a6df640e863b38a73041e8c0c1b.tar.gz libcore-6bd77683de703a6df640e863b38a73041e8c0c1b.tar.bz2 |
Fix decoding of filenames in zip files, when read by ZipFile.
Java always writes UTF-8 filenames in zip files, but harmony cunningly
always reads them back as ISO-8859-1. Fix that, and also set the flag
that says "these filenames are UTF-8" (the RI will do this from Java 7
on).
Note that this patch doesn't actually touch ZipFile because the bug is
in the package-private ZipEntry constructor that's used by
ZipFile.readCentralDirectory.
Bug: http://code.google.com/p/android/issues/detail?id=4690
Diffstat (limited to 'archive')
4 files changed, 40 insertions, 19 deletions
diff --git a/archive/src/main/java/java/util/zip/ZipConstants.java b/archive/src/main/java/java/util/zip/ZipConstants.java index 9fbce06..f0b1f69 100644 --- a/archive/src/main/java/java/util/zip/ZipConstants.java +++ b/archive/src/main/java/java/util/zip/ZipConstants.java @@ -30,4 +30,25 @@ interface ZipConstants { CENNAM = 28, CENEXT = 30, CENCOM = 32, CENDSK = 34, CENATT = 36, CENATX = 38, CENOFF = 42, ENDSUB = 8, ENDTOT = 10, ENDSIZ = 12, ENDOFF = 16, ENDCOM = 20; + + /** + * General Purpose Bit Flags, Bit 3. + * If this bit is set, the fields crc-32, compressed + * size and uncompressed size are set to zero in the + * local header. The correct values are put in the + * data descriptor immediately following the compressed + * data. (Note: PKZIP version 2.04g for DOS only + * recognizes this bit for method 8 compression, newer + * versions of PKZIP recognize this bit for any + * compression method.) + */ + public static final int GPBF_DATA_DESCRIPTOR_FLAG = 1 << 3; // android-added + + /** + * General Purpose Bit Flags, Bit 11. + * Language encoding flag (EFS). If this bit is set, + * the filename and comment fields for this file + * must be encoded using UTF-8. + */ + public static final int GPBF_UTF8_FLAG = 1 << 11; // android-added } diff --git a/archive/src/main/java/java/util/zip/ZipEntry.java b/archive/src/main/java/java/util/zip/ZipEntry.java index 75466ce..d68aa2f 100644 --- a/archive/src/main/java/java/util/zip/ZipEntry.java +++ b/archive/src/main/java/java/util/zip/ZipEntry.java @@ -400,20 +400,16 @@ public class ZipEntry implements ZipConstants, Cloneable { } try { - /* - * The actual character set is "IBM Code Page 437". As of - * Sep 2006, the Zip spec (APPNOTE.TXT) supports UTF-8. When - * bit 11 of the GP flags field is set, the file name and - * comment fields are UTF-8. - * - * TODO: add correct UTF-8 support. - */ - name = new String(nameBytes, "ISO-8859-1"); + // BEGIN android-changed + // The RI has always assumed UTF-8. (If GPBF_UTF8_FLAG isn't set, the encoding is + // actually IBM-437.) + name = new String(nameBytes, "UTF-8"); if (commentBytes != null) { - comment = new String(commentBytes, "ISO-8859-1"); + comment = new String(commentBytes, "UTF-8"); } else { comment = null; } + // END android-changed } catch (UnsupportedEncodingException uee) { throw new InternalError(uee.getMessage()); } diff --git a/archive/src/main/java/java/util/zip/ZipInputStream.java b/archive/src/main/java/java/util/zip/ZipInputStream.java index 554f5d5..ddebd6f 100644 --- a/archive/src/main/java/java/util/zip/ZipInputStream.java +++ b/archive/src/main/java/java/util/zip/ZipInputStream.java @@ -49,8 +49,6 @@ public class ZipInputStream extends InflaterInputStream implements ZipConstants static final int STORED = 0; - static final int ZIPDataDescriptorFlag = 8; - static final int ZIPLocalHeaderVersionNeeded = 20; private boolean entriesEnd = false; @@ -236,7 +234,7 @@ public class ZipInputStream extends InflaterInputStream implements ZipConstants throw new ZipException(Messages.getString("archive.22")); //$NON-NLS-1$ } int flags = getShort(hdrBuf, LOCFLG - LOCVER); - hasDD = ((flags & ZIPDataDescriptorFlag) == ZIPDataDescriptorFlag); + hasDD = ((flags & GPBF_DATA_DESCRIPTOR_FLAG) == GPBF_DATA_DESCRIPTOR_FLAG); int cetime = getShort(hdrBuf, LOCTIM - LOCVER); int cemodDate = getShort(hdrBuf, LOCTIM - LOCVER + 2); int cecompressionMethod = getShort(hdrBuf, LOCHOW - LOCVER); diff --git a/archive/src/main/java/java/util/zip/ZipOutputStream.java b/archive/src/main/java/java/util/zip/ZipOutputStream.java index 21b4221..f85e253 100644 --- a/archive/src/main/java/java/util/zip/ZipOutputStream.java +++ b/archive/src/main/java/java/util/zip/ZipOutputStream.java @@ -54,8 +54,6 @@ public class ZipOutputStream extends DeflaterOutputStream implements */ public static final int STORED = 0; - static final int ZIPDataDescriptorFlag = 8; - static final int ZIPLocalHeaderVersionNeeded = 20; private String comment; @@ -141,11 +139,12 @@ public class ZipOutputStream extends DeflaterOutputStream implements writeLong(out, currentEntry.size = def.getTotalIn()); } // Update the CentralDirectory + // http://www.pkware.com/documents/casestudies/APPNOTE.TXT + int flags = currentEntry.getMethod() == STORED ? 0 : GPBF_DATA_DESCRIPTOR_FLAG; writeLong(cDir, CENSIG); writeShort(cDir, ZIPLocalHeaderVersionNeeded); // Version created writeShort(cDir, ZIPLocalHeaderVersionNeeded); // Version to extract - writeShort(cDir, currentEntry.getMethod() == STORED ? 0 - : ZIPDataDescriptorFlag); + writeShort(cDir, flags); writeShort(cDir, currentEntry.getMethod()); writeShort(cDir, currentEntry.time); writeShort(cDir, currentEntry.modDate); @@ -283,16 +282,23 @@ public class ZipOutputStream extends DeflaterOutputStream implements if (currentEntry.getMethod() == -1) { currentEntry.setMethod(compressMethod); } + // BEGIN android-changed + // Local file header. + // http://www.pkware.com/documents/casestudies/APPNOTE.TXT + int flags = currentEntry.getMethod() == STORED ? 0 : GPBF_DATA_DESCRIPTOR_FLAG; + // Java always outputs UTF-8 filenames. (Before Java 7, the RI didn't set this flag and used + // modified UTF-8. From Java 7, it sets this flag and uses normal UTF-8.) + flags |= GPBF_UTF8_FLAG; writeLong(out, LOCSIG); // Entry header writeShort(out, ZIPLocalHeaderVersionNeeded); // Extraction version - writeShort(out, currentEntry.getMethod() == STORED ? 0 - : ZIPDataDescriptorFlag); + writeShort(out, flags); writeShort(out, currentEntry.getMethod()); if (currentEntry.getTime() == -1) { currentEntry.setTime(System.currentTimeMillis()); } writeShort(out, currentEntry.time); writeShort(out, currentEntry.modDate); + // END android-changed if (currentEntry.getMethod() == STORED) { if (currentEntry.size == -1) { |