From 7d174c342609636a70ce2f26fb50d8ea8077fd7e Mon Sep 17 00:00:00 2001
From: Stefan Bodewig
Date: Fri, 18 Jul 2008 10:13:28 +0000
Subject: [PATCH] Made up my mind on the fix for PR 35000. Empty != broken, so
make it two separate use cases.
git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@677870 13f79535-47bb-0310-9956-ffa450edef68
---
WHATSNEW | 9 +-
docs/manual/CoreTasks/unzip.html | 2 +-
.../org/apache/tools/ant/taskdefs/Expand.java | 10 +-
.../org/apache/tools/ant/taskdefs/Untar.java | 2 +-
src/main/org/apache/tools/zip/ZipFile.java | 92 ++++---------------
src/tests/antunit/taskdefs/unzip-test.xml | 2 +-
6 files changed, 36 insertions(+), 81 deletions(-)
diff --git a/WHATSNEW b/WHATSNEW
index e9447d2a8..b2f0f7b7d 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -58,9 +58,8 @@ Changes that could break older environments:
passed in a null or empty InputStream to read from.
Bugzilla Report 32200
- * and will now fail on empty archives (or ZIP
- archives with an empty central directory).
- set failOnEmptyArchive to false to restore the old behavior.
+ * will now fail when trying to extract certain broken
+ archives that would have been silently ignored in earlier version.
Bugzilla report 35000.
* Ant's family of tasks tries to preserve the existing Unix
@@ -226,6 +225,10 @@ Other changes:
authentication.
Bugzilla report 33718.
+ * a new failOnEmptyArchive attribute on and can now
+ make the task fail the build if it tries to extract an empty
+ archive.
+
Changes from Ant 1.7.0 TO Ant 1.7.1
=============================================
diff --git a/docs/manual/CoreTasks/unzip.html b/docs/manual/CoreTasks/unzip.html
index 323d9072d..b0d056b0e 100644
--- a/docs/manual/CoreTasks/unzip.html
+++ b/docs/manual/CoreTasks/unzip.html
@@ -114,7 +114,7 @@ archive.
failOnEmptyArchive |
whether trying to extract an empty archive is an
error. since Ant 1.8.0 |
- No, defaults to true |
+ No, defaults to false |
Examples
diff --git a/src/main/org/apache/tools/ant/taskdefs/Expand.java b/src/main/org/apache/tools/ant/taskdefs/Expand.java
index 124ba46b6..2e73d1cbe 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Expand.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Expand.java
@@ -66,7 +66,7 @@ public class Expand extends Task {
private Vector patternsets = new Vector();
private Union resources = new Union();
private boolean resourcesSpecified = false;
- private boolean failOnEmptyArchive = true;
+ private boolean failOnEmptyArchive = false;
private static final String NATIVE_ENCODING = "native-encoding";
@@ -164,15 +164,19 @@ public class Expand extends Task {
getLocation());
}
try {
- zf = new ZipFile(srcF, encoding, failOnEmptyArchive);
+ zf = new ZipFile(srcF, encoding);
+ boolean empty = true;
Enumeration e = zf.getEntries();
while (e.hasMoreElements()) {
+ empty = false;
ZipEntry ze = (ZipEntry) e.nextElement();
extractFile(fileUtils, srcF, dir, zf.getInputStream(ze),
ze.getName(), new Date(ze.getTime()),
ze.isDirectory(), mapper);
}
-
+ if (empty && getFailOnEmptyArchive()) {
+ throw new BuildException("archive '" + srcF + "' is empty");
+ }
log("expand complete", Project.MSG_VERBOSE);
} catch (IOException ioe) {
throw new BuildException(
diff --git a/src/main/org/apache/tools/ant/taskdefs/Untar.java b/src/main/org/apache/tools/ant/taskdefs/Untar.java
index 967b473f8..b07caf768 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Untar.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Untar.java
@@ -158,7 +158,7 @@ public class Untar extends Expand {
te.isDirectory(), mapper);
}
if (empty && getFailOnEmptyArchive()) {
- throw new BuildException("archive is empty");
+ throw new BuildException("archive '" + name + "' is empty");
}
log("expand complete", Project.MSG_VERBOSE);
} finally {
diff --git a/src/main/org/apache/tools/zip/ZipFile.java b/src/main/org/apache/tools/zip/ZipFile.java
index a74b7fe0c..82a218e0c 100644
--- a/src/main/org/apache/tools/zip/ZipFile.java
+++ b/src/main/org/apache/tools/zip/ZipFile.java
@@ -146,78 +146,10 @@ public class ZipFile {
* @throws IOException if an error occurs while reading the file.
*/
public ZipFile(File f, String encoding) throws IOException {
- this(f, encoding, false);
- }
-
- /**
- * Opens the given file for reading, assuming the platform's
- * native encoding for file names.
- *
- * @param f the archive.
- * @param mustNotBeEmpty whether an empty central directory should
- * case an error
- *
- * @throws IOException if an error occurs while reading the file.
- *
- * @since Ant 1.8.0
- */
- public ZipFile(File f, boolean mustNotBeEmpty) throws IOException {
- this(f, null, mustNotBeEmpty);
- }
-
- /**
- * Opens the given file for reading, assuming the platform's
- * native encoding for file names.
- *
- * @param name name of the archive.
- * @param mustNotBeEmpty whether an empty central directory should
- * case an error
- *
- * @throws IOException if an error occurs while reading the file.
- *
- * @since Ant 1.8.0
- */
- public ZipFile(String name, boolean mustNotBeEmpty) throws IOException {
- this(new File(name), null, mustNotBeEmpty);
- }
-
- /**
- * Opens the given file for reading, assuming the specified
- * encoding for file names.
- *
- * @param name name of the archive.
- * @param encoding the encoding to use for file names
- * @param mustNotBeEmpty whether an empty central directory should
- * case an error
- *
- * @throws IOException if an error occurs while reading the file.
- *
- * @since Ant 1.8.0
- */
- public ZipFile(String name, String encoding,
- boolean mustNotBeEmpty) throws IOException {
- this(new File(name), encoding, mustNotBeEmpty);
- }
-
- /**
- * Opens the given file for reading, assuming the specified
- * encoding for file names.
- *
- * @param f the archive.
- * @param encoding the encoding to use for file names
- * @param mustNotBeEmpty whether an empty central directory should
- * case an error
- *
- * @throws IOException if an error occurs while reading the file.
- *
- * @since Ant 1.8.0
- */
- public ZipFile(File f, String encoding,
- boolean mustNotBeEmpty) throws IOException {
this.encoding = encoding;
archive = new RandomAccessFile(f, "r");
try {
- populateFromCentralDirectory(mustNotBeEmpty);
+ populateFromCentralDirectory();
resolveLocalFileHeaderData();
} catch (IOException e) {
try {
@@ -334,7 +266,7 @@ public class ZipFile {
* the central directory alone, but not the data that requires the
* local file header or additional data to be read.
*/
- private void populateFromCentralDirectory(boolean mustNotBeEmpty)
+ private void populateFromCentralDirectory()
throws IOException {
positionAtCentralDirectory();
@@ -344,9 +276,9 @@ public class ZipFile {
archive.readFully(signatureBytes);
long sig = ZipLong.getValue(signatureBytes);
final long cfhSig = ZipLong.getValue(ZipOutputStream.CFH_SIG);
- if (mustNotBeEmpty && sig != cfhSig) {
+ if (sig != cfhSig && startsWithLocalFileHeader()) {
throw new IOException("central directory is empty, can't expand"
- + " archive.");
+ + " corrupt archive.");
}
while (sig == cfhSig) {
archive.readFully(cfh);
@@ -581,6 +513,22 @@ public class ZipFile {
}
}
+ /**
+ * Checks whether the archive starts with a LFH. If it doesn't,
+ * it may be an empty archive.
+ */
+ private boolean startsWithLocalFileHeader() throws IOException {
+ archive.seek(0);
+ final byte[] start = new byte[WORD];
+ archive.readFully(start);
+ for (int i = 0; i < start.length; i++) {
+ if (start[i] != ZipOutputStream.LFH_SIG[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
/**
* InputStream that delegates requests to the underlying
* RandomAccessFile, making sure that only bytes from a certain
diff --git a/src/tests/antunit/taskdefs/unzip-test.xml b/src/tests/antunit/taskdefs/unzip-test.xml
index 80fcf3fdd..f295038b7 100644
--- a/src/tests/antunit/taskdefs/unzip-test.xml
+++ b/src/tests/antunit/taskdefs/unzip-test.xml
@@ -32,7 +32,7 @@
+ expectedmessage="central directory is empty, can't expand corrupt archive.">