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 2011/07/29 16:41:26 UTC
svn commit: r1152242 - in
/commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip:
Zip64ExtendedInformationExtraField.java ZipArchiveOutputStream.java
Author: bodewig
Date: Fri Jul 29 14:41:25 2011
New Revision: 1152242
URL: http://svn.apache.org/viewvc?rev=1152242&view=rev
Log:
add ZIP64 extended information to the central directory if needed. COMPRESS-150
Modified:
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/Zip64ExtendedInformationExtraField.java
commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
Modified: commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/Zip64ExtendedInformationExtraField.java
URL: http://svn.apache.org/viewvc/commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/Zip64ExtendedInformationExtraField.java?rev=1152242&r1=1152241&r2=1152242&view=diff
==============================================================================
--- commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/Zip64ExtendedInformationExtraField.java (original)
+++ commons/proper/compress/branches/zip64/src/main/java/org/apache/commons/compress/archivers/zip/Zip64ExtendedInformationExtraField.java Fri Jul 29 14:41:25 2011
@@ -20,6 +20,9 @@ package org.apache.commons.compress.arch
import java.util.zip.ZipException;
+import static org.apache.commons.compress.archivers.zip.ZipConstants.DWORD;
+import static org.apache.commons.compress.archivers.zip.ZipConstants.WORD;
+
/**
* Holds size and other extended information for entries that use Zip64
* features.
@@ -71,15 +74,12 @@ import java.util.zip.ZipException;
* @NotThreadSafe
*/
public class Zip64ExtendedInformationExtraField implements ZipExtraField {
- // TODO: the LFH should probably not contain relativeHeaderOffset
- // and diskStart but then ZipArchivePOutputStream won't write it to
- // the CD either - need to test interop with other implementations
- // to see whether they do have a problem with the extraneous
- // information inside the LFH
static final ZipShort HEADER_ID = new ZipShort(0x0001);
- private static final int WORD = 4, DWORD = 8;
+ private static final String LFH_MUST_HAVE_BOTH_SIZES_MSG =
+ "Zip64 extended information must contain"
+ + " both size values in the local file header.";
private ZipEightByteInteger size, compressedSize, relativeHeaderOffset;
private ZipLong diskStart;
@@ -115,12 +115,6 @@ public class Zip64ExtendedInformationExt
ZipEightByteInteger compressedSize,
ZipEightByteInteger relativeHeaderOffset,
ZipLong diskStart) {
- if (size == null) {
- throw new IllegalArgumentException("size must not be null");
- }
- if (compressedSize == null) {
- throw new IllegalArgumentException("compressedSize must not be null");
- }
this.size = size;
this.compressedSize = compressedSize;
this.relativeHeaderOffset = relativeHeaderOffset;
@@ -134,26 +128,34 @@ public class Zip64ExtendedInformationExt
/** {@inheritDoc} */
public ZipShort getLocalFileDataLength() {
- return getCentralDirectoryLength();
+ return new ZipShort(size != null ? 2 * DWORD : 0);
}
/** {@inheritDoc} */
public ZipShort getCentralDirectoryLength() {
- return new ZipShort(2 * DWORD // both size fields
+ return new ZipShort((size != null ? DWORD : 0)
+ + (compressedSize != null ? DWORD : 0)
+ (relativeHeaderOffset != null ? DWORD : 0)
+ (diskStart != null ? WORD : 0));
}
/** {@inheritDoc} */
public byte[] getLocalFileDataData() {
- return getCentralDirectoryData();
+ if (size != null || compressedSize != null) {
+ if (size == null || compressedSize == null) {
+ throw new IllegalArgumentException(LFH_MUST_HAVE_BOTH_SIZES_MSG);
+ }
+ byte[] data = new byte[2 * DWORD];
+ addSizes(data);
+ return data;
+ }
+ return new byte[0];
}
/** {@inheritDoc} */
public byte[] getCentralDirectoryData() {
byte[] data = new byte[getCentralDirectoryLength().getValue()];
- addSizes(data);
- int off = 2 * DWORD;
+ int off = addSizes(data);
if (relativeHeaderOffset != null) {
System.arraycopy(relativeHeaderOffset.getBytes(), 0, data, off, DWORD);
off += DWORD;
@@ -169,9 +171,7 @@ public class Zip64ExtendedInformationExt
public void parseFromLocalFileData(byte[] buffer, int offset, int length)
throws ZipException {
if (length < 2 * DWORD) {
- throw new ZipException("Zip64 extended information must contain"
- + " both size values in the local file"
- + " header.");
+ throw new ZipException(LFH_MUST_HAVE_BOTH_SIZES_MSG);
}
size = new ZipEightByteInteger(buffer, offset);
offset += DWORD;
@@ -214,6 +214,13 @@ public class Zip64ExtendedInformationExt
}
/**
+ * The uncompressed size stored in this extra field.
+ */
+ public void setSize(ZipEightByteInteger size) {
+ this.size = size;
+ }
+
+ /**
* The compressed size stored in this extra field.
*/
public ZipEightByteInteger getCompressedSize() {
@@ -221,6 +228,13 @@ public class Zip64ExtendedInformationExt
}
/**
+ * The uncompressed size stored in this extra field.
+ */
+ public void setCompressedSize(ZipEightByteInteger compressedSize) {
+ this.compressedSize = compressedSize;
+ }
+
+ /**
* The relative header offset stored in this extra field.
*/
public ZipEightByteInteger getRelativeHeaderOffset() {
@@ -228,14 +242,36 @@ public class Zip64ExtendedInformationExt
}
/**
+ * The relative header offset stored in this extra field.
+ */
+ public void setRelativeHeaderOffset(ZipEightByteInteger rho) {
+ relativeHeaderOffset = rho;
+ }
+
+ /**
* The disk start number stored in this extra field.
*/
public ZipLong getDiskStartNumber() {
return diskStart;
}
- private void addSizes(byte[] data) {
- System.arraycopy(size.getBytes(), 0, data, 0, DWORD);
- System.arraycopy(compressedSize.getBytes(), 0, data, DWORD, DWORD);
+ /**
+ * The disk start number stored in this extra field.
+ */
+ public void setDiskStartNumber(ZipLong ds) {
+ diskStart = ds;
+ }
+
+ private int addSizes(byte[] data) {
+ int off = 0;
+ if (size != null) {
+ System.arraycopy(size.getBytes(), 0, data, 0, DWORD);
+ off += DWORD;
+ }
+ if (compressedSize != null) {
+ System.arraycopy(compressedSize.getBytes(), 0, data, off, DWORD);
+ off += DWORD;
+ }
+ return off;
}
}
\ No newline at end of file
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=1152242&r1=1152241&r2=1152242&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 Fri Jul 29 14:41:25 2011
@@ -702,7 +702,8 @@ public class ZipArchiveOutputStream exte
writeVersionNeededToExtractAndGeneralPurposeBits(zipMethod,
!encodable
- && fallbackToUTF8);
+ && fallbackToUTF8,
+ false);
written += WORD;
// compression method
@@ -786,9 +787,38 @@ public class ZipArchiveOutputStream exte
final int zipMethod = ze.getMethod();
final boolean encodable = zipEncoding.canEncode(ze.getName());
+
+ final long lfhOffset = offsets.get(ze).longValue();
+ final boolean needsZip64Extra = ze.getCompressedSize() >= ZIP64_MAGIC
+ || ze.getSize() >= ZIP64_MAGIC
+ || lfhOffset >= ZIP64_MAGIC;
+
+ if (needsZip64Extra) {
+ hasUsedZip64 = true;
+ Zip64ExtendedInformationExtraField z64 =
+ (Zip64ExtendedInformationExtraField)
+ ze.getExtraField(Zip64ExtendedInformationExtraField
+ .HEADER_ID);
+ if (z64 == null) {
+ z64 = new Zip64ExtendedInformationExtraField();
+ ze.addExtraField(z64);
+ }
+ if (ze.getCompressedSize() >= ZIP64_MAGIC) {
+ z64.setCompressedSize(new ZipEightByteInteger(ze.getCompressedSize()));
+ }
+ if (ze.getSize() >= ZIP64_MAGIC) {
+ z64.setSize(new ZipEightByteInteger(ze.getSize()));
+ }
+ if (lfhOffset >= ZIP64_MAGIC) {
+ z64.setRelativeHeaderOffset(new ZipEightByteInteger(lfhOffset));
+ }
+ ze.setExtra();
+ }
+
writeVersionNeededToExtractAndGeneralPurposeBits(zipMethod,
!encodable
- && fallbackToUTF8);
+ && fallbackToUTF8,
+ needsZip64Extra);
written += WORD;
// compression method
@@ -803,8 +833,8 @@ public class ZipArchiveOutputStream exte
// compressed length
// uncompressed length
writeOut(ZipLong.getBytes(ze.getCrc()));
- writeOut(ZipLong.getBytes(ze.getCompressedSize()));
- writeOut(ZipLong.getBytes(ze.getSize()));
+ writeOut(ZipLong.getBytes(Math.min(ze.getCompressedSize(), ZIP64_MAGIC)));
+ writeOut(ZipLong.getBytes(Math.min(ze.getSize(), ZIP64_MAGIC)));
// CheckStyle:MagicNumber OFF
written += 12;
// CheckStyle:MagicNumber ON
@@ -852,7 +882,7 @@ public class ZipArchiveOutputStream exte
written += WORD;
// relative offset of LFH
- writeOut(ZipLong.getBytes(offsets.get(ze).longValue()));
+ writeOut(ZipLong.getBytes(Math.min(lfhOffset, ZIP64_MAGIC)));
written += WORD;
// file name
@@ -996,7 +1026,9 @@ public class ZipArchiveOutputStream exte
private void writeVersionNeededToExtractAndGeneralPurposeBits(final int
zipMethod,
final boolean
- utfFallback)
+ utfFallback,
+ final boolean
+ zip64)
throws IOException {
// CheckStyle:MagicNumber OFF
@@ -1006,9 +1038,12 @@ public class ZipArchiveOutputStream exte
if (zipMethod == DEFLATED && raf == null) {
// requires version 2 as we are going to store length info
// in the data descriptor
- versionNeededToExtract = 20;
+ versionNeededToExtract = DEFLATE_MIN_VERSION;
b.useDataDescriptor(true);
}
+ if (zip64) {
+ versionNeededToExtract = ZIP64_MIN_VERSION;
+ }
// CheckStyle:MagicNumber ON
// version needed to extract