diff options
author | Andreas Beeker <kiwiwings@apache.org> | 2018-06-03 22:09:11 +0000 |
---|---|---|
committer | Andreas Beeker <kiwiwings@apache.org> | 2018-06-03 22:09:11 +0000 |
commit | 8cabdb476cf5256e7bb5c240eff29f7823461b3b (patch) | |
tree | e44f3b76ad5415a48577ce49dc8b541183aca529 | |
parent | bfe3e6a976305870a5df17b86bb16c9c66b15526 (diff) | |
download | poi-8cabdb476cf5256e7bb5c240eff29f7823461b3b.tar.gz poi-8cabdb476cf5256e7bb5c240eff29f7823461b3b.zip |
#62187 - Compiling with Java 10 fails with ClassCastException / use commons-compress for zipbomb detection
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1832789 13f79535-47bb-0310-9956-ffa450edef68
30 files changed, 245 insertions, 311 deletions
diff --git a/build.gradle b/build.gradle index 1ec30a7441..0a81e905de 100644 --- a/build.gradle +++ b/build.gradle @@ -192,6 +192,7 @@ project('ooxml') { compile 'org.apache.xmlbeans:xmlbeans:2.6.0' compile 'org.apache.commons:commons-collections4:4.1' compile 'org.apache.commons:commons-math3:3.6.1' + compile 'org.apache.commons:commons-compress:1.17' compile 'org.apache.santuario:xmlsec:2.1.0' compile 'org.bouncycastle:bcpkix-jdk15on:1.59' compile 'com.github.virtuald:curvesapi:1.05' @@ -202,6 +202,9 @@ under the License. <property name="ooxml.xmlbeans26.jar" location="${ooxml.lib}/xmlbeans-2.6.0.jar"/> <property name="ooxml.xmlbeans26.url" value="${repository.m2}/maven2/org/apache/xmlbeans/xmlbeans/2.6.0/xmlbeans-2.6.0.jar"/> + <property name="ooxml.commons-compress.jar" location="${main.lib}/commons-compress-1.17.jar"/> + <property name="ooxml.commons-compress.url" + value="${repository.m2}/maven2/org/apache/commons/commons-compress/1.17/commons-compress-1.17.jar"/> <!-- coverage libs --> <property name="jacoco.zip" location="${main.lib}/jacoco-0.8.1.zip"/> @@ -354,6 +357,7 @@ under the License. <path id="ooxml.classpath"> <pathelement location="${ooxml.curvesapi.jar}"/> <pathelement location="${ooxml.xmlbeans26.jar}"/> + <pathelement location="${ooxml.commons-compress.jar}"/> <pathelement location="${ooxml.xsds.jar}"/> <path refid="main.classpath"/> <pathelement location="${main.output.dir}"/> @@ -403,6 +407,7 @@ under the License. <path id="ooxml-lite.classpath"> <pathelement location="${ooxml.curvesapi.jar}"/> <pathelement location="${ooxml.xmlbeans26.jar}"/> + <pathelement location="${ooxml.commons-compress.jar}"/> <pathelement location="${ooxml.lite.output.dir}"/> <!-- instead of ooxml-xsds.jar use the filtered classes--> <path refid="main.classpath"/> <pathelement location="${main.output.dir}"/> @@ -714,6 +719,7 @@ under the License. <and> <available file="${ooxml.curvesapi.jar}"/> <available file="${ooxml.xmlbeans26.jar}"/> + <available file="${ooxml.commons-compress.jar}"/> </and> <isset property="disconnected"/> </or> @@ -723,6 +729,7 @@ under the License. <mkdir dir="${ooxml.lib}"/> <downloadfile src="${ooxml.curvesapi.url}" dest="${ooxml.curvesapi.jar}"/> <downloadfile src="${ooxml.xmlbeans26.url}" dest="${ooxml.xmlbeans26.jar}.orig"/> + <downloadfile src="${ooxml.commons-compress.url}" dest="${ooxml.commons-compress.jar}"/> <!-- remove piccolo parser, so we don't use unsafe calls to it instead of using jaxp --> <zip destfile="${ooxml.xmlbeans26.jar}"> <zipfileset src="${ooxml.xmlbeans26.jar}.orig" excludes="org/apache/xmlbeans/impl/piccolo/**"/> @@ -2203,6 +2210,7 @@ under the License. <auxClasspath path="${ooxml.security.jar}" /> <auxClasspath path="${ooxml.curvesapi.jar}" /> <auxClasspath path="${ooxml.xmlbeans26.jar}" /> + <auxClasspath path="${ooxml.commons-compress.jar}" /> <auxClasspath path="${main.commons-collections4.jar}" /> <auxClasspath path="${main.commons-math3.jar}" /> <auxClasspath path="${main.commons-codec.jar}" /> diff --git a/maven/poi-ooxml.pom b/maven/poi-ooxml.pom index 0f3cdb1d51..caadc95527 100644 --- a/maven/poi-ooxml.pom +++ b/maven/poi-ooxml.pom @@ -70,9 +70,14 @@ <version>@VERSION@</version> </dependency> <dependency> - <groupId>com.github.virtuald</groupId> - <artifactId>curvesapi</artifactId> - <version>1.04</version> + <groupId>org.apache.commons</groupId> + <artifactId>commons-compress</artifactId> + <version>1.17</version> + </dependency> + <dependency> + <groupId>com.github.virtuald</groupId> + <artifactId>curvesapi</artifactId> + <version>1.04</version> </dependency> </dependencies> </project> diff --git a/sonar/ooxml/pom.xml b/sonar/ooxml/pom.xml index 651e546f67..e2a38e7ad2 100644 --- a/sonar/ooxml/pom.xml +++ b/sonar/ooxml/pom.xml @@ -150,6 +150,11 @@ <version>2.1.0</version> </dependency> <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-compress</artifactId> + <version>1.17</version> + </dependency> + <dependency> <groupId>com.github.virtuald</groupId> <artifactId>curvesapi</artifactId> <version>1.05</version> diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/BigGridDemo.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/BigGridDemo.java index 75e116a589..8803175997 100644 --- a/src/examples/src/org/apache/poi/xssf/usermodel/examples/BigGridDemo.java +++ b/src/examples/src/org/apache/poi/xssf/usermodel/examples/BigGridDemo.java @@ -30,10 +30,10 @@ import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Random; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipOutputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; +import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.poi.openxml4j.opc.internal.ZipHelper; import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.FillPatternType; @@ -193,21 +193,23 @@ public final class BigGridDemo { */ private static void substitute(File zipfile, File tmpfile, String entry, OutputStream out) throws IOException { try (ZipFile zip = ZipHelper.openZipFile(zipfile)) { - try (ZipOutputStream zos = new ZipOutputStream(out)) { - Enumeration<? extends ZipEntry> en = zip.entries(); + try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(out)) { + Enumeration<? extends ZipArchiveEntry> en = zip.getEntries(); while (en.hasMoreElements()) { - ZipEntry ze = en.nextElement(); + ZipArchiveEntry ze = en.nextElement(); if (!ze.getName().equals(entry)) { - zos.putNextEntry(new ZipEntry(ze.getName())); + zos.putArchiveEntry(new ZipArchiveEntry(ze.getName())); try (InputStream is = zip.getInputStream(ze)) { copyStream(is, zos); } + zos.closeArchiveEntry(); } } - zos.putNextEntry(new ZipEntry(entry)); + zos.putArchiveEntry(new ZipArchiveEntry(entry)); try (InputStream is = new FileInputStream(tmpfile)) { copyStream(is, zos); } + zos.closeArchiveEntry(); } } } diff --git a/src/ooxml/java/org/apache/poi/ooxml/dev/OOXMLPrettyPrint.java b/src/ooxml/java/org/apache/poi/ooxml/dev/OOXMLPrettyPrint.java index 47ec47055e..247d37c24d 100644 --- a/src/ooxml/java/org/apache/poi/ooxml/dev/OOXMLPrettyPrint.java +++ b/src/ooxml/java/org/apache/poi/ooxml/dev/OOXMLPrettyPrint.java @@ -22,10 +22,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Enumeration; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipFile; -import java.util.zip.ZipOutputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -39,6 +35,9 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; +import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.poi.openxml4j.opc.internal.ZipHelper; import org.apache.poi.openxml4j.util.ZipSecureFile; import org.apache.poi.util.IOUtils; @@ -83,12 +82,12 @@ public class OOXMLPrettyPrint { System.out.println("Done."); } - private static void handleFile(File file, File outFile) throws ZipException, - IOException, ParserConfigurationException { + private static void handleFile(File file, File outFile) throws + IOException, TransformerException, ParserConfigurationException { System.out.println("Reading zip-file " + file + " and writing pretty-printed XML to " + outFile); - try (ZipFile zipFile = ZipHelper.openZipFile(file)) { - try (ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(outFile)))) { + try (ZipSecureFile zipFile = ZipHelper.openZipFile(file)) { + try (ZipArchiveOutputStream out = new ZipArchiveOutputStream(new BufferedOutputStream(new FileOutputStream(outFile)))) { new OOXMLPrettyPrint().handle(zipFile, out); } } finally { @@ -96,13 +95,13 @@ public class OOXMLPrettyPrint { } } - private void handle(ZipFile file, ZipOutputStream out) throws IOException { - Enumeration<? extends ZipEntry> entries = file.entries(); + private void handle(ZipFile file, ZipArchiveOutputStream out) throws IOException, TransformerException { + Enumeration<? extends ZipArchiveEntry> entries = file.getEntries(); while(entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); + ZipArchiveEntry entry = entries.nextElement(); String name = entry.getName(); - out.putNextEntry(new ZipEntry(name)); + out.putArchiveEntry(new ZipArchiveEntry(name)); try { if(name.endsWith(".xml") || name.endsWith(".rels")) { Document document = documentBuilder.parse(new InputSource(file.getInputStream(entry))); @@ -115,7 +114,7 @@ public class OOXMLPrettyPrint { } catch (Exception e) { throw new IOException("While handling entry " + name, e); } finally { - out.closeEntry(); + out.closeArchiveEntry(); } System.out.print("."); } diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackage.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackage.java index 2b2b3f7826..40fc2139f5 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackage.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackage.java @@ -29,10 +29,10 @@ import java.io.OutputStream; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipOutputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; +import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.poi.UnsupportedFileFormatException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.InvalidOperationException; @@ -247,7 +247,7 @@ public final class ZipPackage extends OPCPackage { } // First we need to parse the content type part - final ZipEntry contentTypeEntry = + final ZipArchiveEntry contentTypeEntry = zipArchive.getEntry(CONTENT_TYPES_PART_NAME); if (contentTypeEntry != null) { try { @@ -294,11 +294,11 @@ public final class ZipPackage extends OPCPackage { } private class EntryTriple implements Comparable<EntryTriple> { - final ZipEntry zipArchiveEntry; + final ZipArchiveEntry zipArchiveEntry; final PackagePartName partName; final String contentType; - EntryTriple(final ZipEntry zipArchiveEntry, final ContentTypeManager contentTypeManager) { + EntryTriple(final ZipArchiveEntry zipArchiveEntry, final ContentTypeManager contentTypeManager) { this.zipArchiveEntry = zipArchiveEntry; final String entryName = zipArchiveEntry.getName(); @@ -483,8 +483,8 @@ public final class ZipPackage extends OPCPackage { // Check that the document was open in write mode throwExceptionIfReadOnly(); - final ZipOutputStream zos = (outputStream instanceof ZipOutputStream) - ? (ZipOutputStream) outputStream : new ZipOutputStream(outputStream); + final ZipArchiveOutputStream zos = (outputStream instanceof ZipArchiveOutputStream) + ? (ZipArchiveOutputStream) outputStream : new ZipArchiveOutputStream(outputStream); try { // If the core properties part does not exist in the part list, diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackagePart.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackagePart.java index 57e649c281..3e1e977f2b 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackagePart.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/ZipPackagePart.java @@ -20,8 +20,8 @@ package org.apache.poi.openxml4j.opc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.zip.ZipEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.InvalidOperationException; import org.apache.poi.openxml4j.exceptions.OpenXML4JException; @@ -41,13 +41,15 @@ public class ZipPackagePart extends PackagePart { /** * The zip entry corresponding to this part. */ - private ZipEntry zipEntry; + private ZipArchiveEntry zipEntry; /** * Constructor. * * @param container * The container package. + * @param zipEntry + * The zip entry corresponding to this part. * @param partName * The part name. * @param contentType @@ -55,9 +57,10 @@ public class ZipPackagePart extends PackagePart { * @throws InvalidFormatException * Throws if the content of this part is invalid. */ - public ZipPackagePart(OPCPackage container, PackagePartName partName, - String contentType) throws InvalidFormatException { - super(container, partName, contentType); + public ZipPackagePart(OPCPackage container, ZipArchiveEntry zipEntry, + PackagePartName partName, String contentType) + throws InvalidFormatException { + this(container, zipEntry, partName, contentType, true); } /** @@ -74,7 +77,7 @@ public class ZipPackagePart extends PackagePart { * @throws InvalidFormatException * Throws if the content of this part is invalid. */ - /* package */ ZipPackagePart(OPCPackage container, ZipEntry zipEntry, + /* package */ ZipPackagePart(OPCPackage container, ZipArchiveEntry zipEntry, PackagePartName partName, String contentType, boolean loadRelationships) throws InvalidFormatException { super(container, partName, new ContentType(contentType), loadRelationships); @@ -86,7 +89,7 @@ public class ZipPackagePart extends PackagePart { * * @return The zip entry in the zip structure coresponding to this part. */ - public ZipEntry getZipArchive() { + public ZipArchiveEntry getZipArchive() { return zipEntry; } diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipContentTypeManager.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipContentTypeManager.java index a51d6353b4..2b2f5e7a89 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipContentTypeManager.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipContentTypeManager.java @@ -20,9 +20,9 @@ package org.apache.poi.openxml4j.opc.internal; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.StreamHelper; @@ -57,18 +57,18 @@ public class ZipContentTypeManager extends ContentTypeManager { @SuppressWarnings("resource") @Override public boolean saveImpl(Document content, OutputStream out) { - final ZipOutputStream zos = (out instanceof ZipOutputStream) - ? (ZipOutputStream) out : new ZipOutputStream(out); + final ZipArchiveOutputStream zos = (out instanceof ZipArchiveOutputStream) + ? (ZipArchiveOutputStream) out : new ZipArchiveOutputStream(out); - ZipEntry partEntry = new ZipEntry(CONTENT_TYPES_PART_NAME); + ZipArchiveEntry partEntry = new ZipArchiveEntry(CONTENT_TYPES_PART_NAME); try { // Referenced in ZIP - zos.putNextEntry(partEntry); + zos.putArchiveEntry(partEntry); try { // Saving data in the ZIP file return StreamHelper.saveXmlInStream(content, zos); } finally { - zos.closeEntry(); + zos.closeArchiveEntry(); } } catch (IOException ioe) { logger.log(POILogger.ERROR, "Cannot write: " + CONTENT_TYPES_PART_NAME diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipHelper.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipHelper.java index cd38adcea7..094e89c6d7 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipHelper.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipHelper.java @@ -24,9 +24,9 @@ import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.apache.poi.openxml4j.exceptions.NotOfficeXmlFileException; import org.apache.poi.openxml4j.exceptions.OLE2NotOfficeXmlFileException; import org.apache.poi.openxml4j.opc.PackageRelationship; @@ -59,7 +59,7 @@ public final class ZipHelper { * core properties cannot be read or an invalid name is * specified in the properties. */ - public static ZipEntry getCorePropertiesZipEntry(ZipPackage pkg) { + public static ZipArchiveEntry getCorePropertiesZipEntry(ZipPackage pkg) { PackageRelationship corePropsRel = pkg.getRelationshipsByType( PackageRelationshipTypes.CORE_PROPERTIES).getRelationship(0); @@ -67,7 +67,7 @@ public final class ZipHelper { return null; } - return new ZipEntry(corePropsRel.getTargetURI().getPath()); + return new ZipArchiveEntry(corePropsRel.getTargetURI().getPath()); } /** @@ -177,8 +177,7 @@ public final class ZipHelper { verifyZipHeader(checkedStream); // Open as a proper zip stream - InputStream zis = new ZipInputStream(checkedStream); - return new ZipArchiveThresholdInputStream(zis); + return new ZipArchiveThresholdInputStream(new ZipArchiveInputStream(checkedStream)); } /** diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/ZipPackagePropertiesMarshaller.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/ZipPackagePropertiesMarshaller.java index 7b50139604..f24a74015c 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/ZipPackagePropertiesMarshaller.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/ZipPackagePropertiesMarshaller.java @@ -19,9 +19,9 @@ package org.apache.poi.openxml4j.opc.internal.marshallers; import java.io.IOException; import java.io.OutputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.StreamHelper; @@ -37,24 +37,24 @@ public final class ZipPackagePropertiesMarshaller extends PackagePropertiesMarsh @Override public boolean marshall(PackagePart part, OutputStream out) throws OpenXML4JException { - if (!(out instanceof ZipOutputStream)) { + if (!(out instanceof ZipArchiveOutputStream)) { throw new IllegalArgumentException("ZipOutputStream expected!"); } - ZipOutputStream zos = (ZipOutputStream) out; + ZipArchiveOutputStream zos = (ZipArchiveOutputStream) out; // Saving the part in the zip file - ZipEntry ctEntry = new ZipEntry(ZipHelper + ZipArchiveEntry ctEntry = new ZipArchiveEntry(ZipHelper .getZipItemNameFromOPCName(part.getPartName().getURI() .toString())); try { // Save in ZIP - zos.putNextEntry(ctEntry); // Add entry in ZIP + zos.putArchiveEntry(ctEntry); // Add entry in ZIP try { super.marshall(part, out); // Marshall the properties inside a XML // Document return StreamHelper.saveXmlInStream(xmlDoc, out); } finally { - zos.closeEntry(); + zos.closeArchiveEntry(); } } catch (IOException e) { throw new OpenXML4JException(e.getLocalizedMessage(), e); diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/ZipPartMarshaller.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/ZipPartMarshaller.java index f39f5b4ae3..a1ba382ff8 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/ZipPartMarshaller.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/marshallers/ZipPartMarshaller.java @@ -21,9 +21,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.openxml4j.opc.PackageNamespaces; import org.apache.poi.openxml4j.opc.PackagePart; @@ -58,7 +58,7 @@ public final class ZipPartMarshaller implements PartMarshaller { @Override public boolean marshall(PackagePart part, OutputStream os) throws OpenXML4JException { - if (!(os instanceof ZipOutputStream)) { + if (!(os instanceof ZipArchiveOutputStream)) { logger.log(POILogger.ERROR,"Unexpected class " + os.getClass().getName()); throw new OpenXML4JException("ZipOutputStream expected !"); // Normally should happen only in developement phase, so just throw @@ -71,19 +71,19 @@ public final class ZipPartMarshaller implements PartMarshaller { return true; } - ZipOutputStream zos = (ZipOutputStream) os; - ZipEntry partEntry = new ZipEntry(ZipHelper + ZipArchiveOutputStream zos = (ZipArchiveOutputStream) os; + ZipArchiveEntry partEntry = new ZipArchiveEntry(ZipHelper .getZipItemNameFromOPCName(part.getPartName().getURI() .getPath())); try { // Create next zip entry - zos.putNextEntry(partEntry); + zos.putArchiveEntry(partEntry); // Saving data in the ZIP file try (final InputStream ins = part.getInputStream()) { IOUtils.copy(ins, zos); } finally { - zos.closeEntry(); + zos.closeArchiveEntry(); } } catch (IOException ioe) { logger.log(POILogger.ERROR,"Cannot write: " + part.getPartName() + ": in ZIP", @@ -116,7 +116,7 @@ public final class ZipPartMarshaller implements PartMarshaller { */ public static boolean marshallRelationshipPart( PackageRelationshipCollection rels, PackagePartName relPartName, - ZipOutputStream zos) { + ZipArchiveOutputStream zos) { // Building xml Document xmlOutDoc = DocumentHelper.createDocument(); // make something like <Relationships @@ -168,14 +168,14 @@ public final class ZipPartMarshaller implements PartMarshaller { // File.separator + "opc-relationships.xsd"; // Save part in zip - ZipEntry ctEntry = new ZipEntry(ZipHelper.getZipURIFromOPCName( + ZipArchiveEntry ctEntry = new ZipArchiveEntry(ZipHelper.getZipURIFromOPCName( relPartName.getURI().toASCIIString()).getPath()); try { - zos.putNextEntry(ctEntry); + zos.putArchiveEntry(ctEntry); try { return StreamHelper.saveXmlInStream(xmlOutDoc, zos); } finally { - zos.closeEntry(); + zos.closeArchiveEntry(); } } catch (IOException e) { logger.log(POILogger.ERROR,"Cannot create zip entry " + relPartName, e); diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/unmarshallers/PackagePropertiesUnmarshaller.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/unmarshallers/PackagePropertiesUnmarshaller.java index 3c2e69d8cc..278bffd9a1 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/unmarshallers/PackagePropertiesUnmarshaller.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/unmarshallers/PackagePropertiesUnmarshaller.java @@ -19,10 +19,10 @@ package org.apache.poi.openxml4j.opc.internal.unmarshallers; import java.io.IOException; import java.io.InputStream; -import java.util.zip.ZipEntry; import javax.xml.XMLConstants; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.opc.PackageNamespaces; import org.apache.poi.openxml4j.opc.PackagePart; @@ -93,7 +93,7 @@ public final class PackagePropertiesUnmarshaller implements PartUnmarshaller { .getInputStream(context.getZipEntry()); } else if (context.getPackage() != null) { // Try to retrieve the part inputstream from the URI - ZipEntry zipEntry = ZipHelper + ZipArchiveEntry zipEntry = ZipHelper .getCorePropertiesZipEntry((ZipPackage) context .getPackage()); in = ((ZipPackage) context.getPackage()).getZipArchive() diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/unmarshallers/UnmarshallContext.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/unmarshallers/UnmarshallContext.java index c4e01ca7a5..d19133f2cb 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/unmarshallers/UnmarshallContext.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/internal/unmarshallers/UnmarshallContext.java @@ -17,8 +17,7 @@ package org.apache.poi.openxml4j.opc.internal.unmarshallers; -import java.util.zip.ZipEntry; - +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackagePartName; @@ -34,7 +33,7 @@ public final class UnmarshallContext { private PackagePartName partName; - private ZipEntry zipEntry; + private ZipArchiveEntry zipEntry; /** * Constructor. @@ -82,7 +81,7 @@ public final class UnmarshallContext { /** * @return the zipEntry */ - ZipEntry getZipEntry() { + ZipArchiveEntry getZipEntry() { return zipEntry; } @@ -90,7 +89,7 @@ public final class UnmarshallContext { * @param zipEntry * the zipEntry to set */ - public void setZipEntry(ZipEntry zipEntry) { + public void setZipEntry(ZipArchiveEntry zipEntry) { this.zipEntry = zipEntry; } } diff --git a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipArchiveFakeEntry.java b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipArchiveFakeEntry.java index 347ea50225..0709fd9021 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipArchiveFakeEntry.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipArchiveFakeEntry.java @@ -20,8 +20,8 @@ package org.apache.poi.openxml4j.util; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.util.zip.ZipEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.poi.util.IOUtils; @@ -31,10 +31,10 @@ import org.apache.poi.util.IOUtils; * Holds the (decompressed!) data in memory, so * close this as soon as you can! */ -/* package */ class ZipArchiveFakeEntry extends ZipEntry { +/* package */ class ZipArchiveFakeEntry extends ZipArchiveEntry { private final byte[] data; - ZipArchiveFakeEntry(ZipEntry entry, InputStream inp) throws IOException { + ZipArchiveFakeEntry(ZipArchiveEntry entry, InputStream inp) throws IOException { super(entry.getName()); final long entrySize = entry.getSize(); diff --git a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipArchiveThresholdInputStream.java b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipArchiveThresholdInputStream.java index 447baa0d06..725c7a4835 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipArchiveThresholdInputStream.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipArchiveThresholdInputStream.java @@ -23,22 +23,17 @@ import static org.apache.poi.openxml4j.util.ZipSecureFile.MIN_INFLATE_RATIO; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; -import java.io.PushbackInputStream; -import java.lang.reflect.Field; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Locale; -import java.util.zip.InflaterInputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; +import java.util.zip.ZipException; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.SuppressForbidden; - -public class ZipArchiveThresholdInputStream extends PushbackInputStream { - private static final POILogger LOG = POILogFactory.getLogger(ZipArchiveThresholdInputStream.class); +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; +import org.apache.commons.compress.utils.InputStreamStatistics; +import org.apache.poi.openxml4j.exceptions.NotOfficeXmlFileException; +import org.apache.poi.util.Internal; +@Internal +public class ZipArchiveThresholdInputStream extends FilterInputStream { // don't alert for expanded sizes smaller than 100k private static final long GRACE_ENTRY_SIZE = 100*1024L; @@ -46,91 +41,54 @@ public class ZipArchiveThresholdInputStream extends PushbackInputStream { "Zip bomb detected! The file would exceed the max size of the expanded data in the zip-file.\n" + "This may indicates that the file is used to inflate memory usage and thus could pose a security risk.\n" + "You can adjust this limit via ZipSecureFile.setMaxEntrySize() if you need to work with files which are very large.\n" + - "Counter: %d, cis.counter: %d\n" + + "Uncompressed size: %d, Raw/compressed size: %d\n" + "Limits: MAX_ENTRY_SIZE: %d, Entry: %s"; private static final String MIN_INFLATE_RATIO_MSG = "Zip bomb detected! The file would exceed the max. ratio of compressed file size to the size of the expanded data.\n" + "This may indicate that the file is used to inflate memory usage and thus could pose a security risk.\n" + "You can adjust this limit via ZipSecureFile.setMinInflateRatio() if you need to work with files which exceed this limit.\n" + - "Counter: %d, cis.counter: %d, ratio: %f\n" + + "Uncompressed size: %d, Raw/compressed size: %d, ratio: %f\n" + "Limits: MIN_INFLATE_RATIO: %f, Entry: %s"; - private static final String SECURITY_BLOCKED = - "SecurityManager doesn't allow manipulation via reflection for zipbomb detection - continue with original input stream"; - /** * the reference to the current entry is only used for a more detailed log message in case of an error */ - private ZipEntry entry; - - private long counter; - private long markPos; - private final ZipArchiveThresholdInputStream cis; + private ZipArchiveEntry entry; private boolean guardState = true; - - public ZipArchiveThresholdInputStream(final InputStream zipIS) throws IOException { - super(zipIS); - if (zipIS instanceof InflaterInputStream) { - cis = AccessController.doPrivileged(inject(zipIS)); - } else { - // the inner stream is a ZipFileInputStream, i.e. the data wasn't compressed - cis = null; - } - } - - private ZipArchiveThresholdInputStream(InputStream is, ZipArchiveThresholdInputStream cis) { + public ZipArchiveThresholdInputStream(InputStream is) { super(is); - this.cis = cis; - } - - @SuppressForbidden - private static PrivilegedAction<ZipArchiveThresholdInputStream> inject(final InputStream zipIS) { - return () -> { - try { - final Field f = FilterInputStream.class.getDeclaredField("in"); - f.setAccessible(true); - final InputStream oldInner = (InputStream)f.get(zipIS); - final ZipArchiveThresholdInputStream inner = new ZipArchiveThresholdInputStream(oldInner, null); - f.set(zipIS, inner); - return inner; - } catch (Exception ex) { - LOG.log(POILogger.WARN, SECURITY_BLOCKED, ex); - } - return null; - }; + if (!(is instanceof InputStreamStatistics)) { + throw new IllegalArgumentException("InputStream of class "+is.getClass()+" is not implementing InputStreamStatistics."); + } } @Override public int read() throws IOException { - int b = in.read(); + int b = super.read(); if (b > -1) { - advance(1); + checkThreshold(); } return b; } @Override public int read(byte b[], int off, int len) throws IOException { - int cnt = in.read(b, off, len); + int cnt = super.read(b, off, len); if (cnt > -1) { - advance(cnt); + checkThreshold(); } return cnt; } @Override public long skip(long n) throws IOException { - long s = in.skip(n); - counter += s; - return s; - } - - @Override - public synchronized void reset() throws IOException { - counter = markPos; - super.reset(); + long cnt = super.skip(n); + if (cnt > 0) { + checkThreshold(); + } + return cnt; } /** @@ -143,101 +101,57 @@ public class ZipArchiveThresholdInputStream extends PushbackInputStream { this.guardState = guardState; } - public void advance(int advance) throws IOException { - counter += advance; - + private void checkThreshold() throws IOException { if (!guardState) { return; } + final InputStreamStatistics stats = (InputStreamStatistics)in; + final long payloadSize = stats.getUncompressedCount(); + final long rawSize = stats.getCompressedCount(); final String entryName = entry == null ? "not set" : entry.getName(); - final long cisCount = (cis == null ? 0 : cis.counter); // check the file size first, in case we are working on uncompressed streams - if(counter > MAX_ENTRY_SIZE) { - throw new IOException(String.format(Locale.ROOT, MAX_ENTRY_SIZE_MSG, counter, cisCount, MAX_ENTRY_SIZE, entryName)); - } - - // no expanded size? - if (cis == null) { - return; + if(payloadSize > MAX_ENTRY_SIZE) { + throw new IOException(String.format(Locale.ROOT, MAX_ENTRY_SIZE_MSG, payloadSize, rawSize, MAX_ENTRY_SIZE, entryName)); } // don't alert for small expanded size - if (counter <= GRACE_ENTRY_SIZE) { + if (payloadSize <= GRACE_ENTRY_SIZE) { return; } - double ratio = (double)cis.counter/(double)counter; + double ratio = rawSize / (double)payloadSize; if (ratio >= MIN_INFLATE_RATIO) { return; } // one of the limits was reached, report it - throw new IOException(String.format(Locale.ROOT, MIN_INFLATE_RATIO_MSG, counter, cisCount, ratio, MIN_INFLATE_RATIO, entryName)); - } - - public ZipEntry getNextEntry() throws IOException { - if (!(in instanceof ZipInputStream)) { - throw new UnsupportedOperationException("underlying stream is not a ZipInputStream"); - } - counter = 0; - return ((ZipInputStream)in).getNextEntry(); - } - - public void closeEntry() throws IOException { - if (!(in instanceof ZipInputStream)) { - throw new UnsupportedOperationException("underlying stream is not a ZipInputStream"); - } - counter = 0; - ((ZipInputStream)in).closeEntry(); + throw new IOException(String.format(Locale.ROOT, MIN_INFLATE_RATIO_MSG, payloadSize, rawSize, ratio, MIN_INFLATE_RATIO, entryName)); } - @Override - public void unread(int b) throws IOException { - if (!(in instanceof PushbackInputStream)) { - throw new UnsupportedOperationException("underlying stream is not a PushbackInputStream"); - } - if (--counter < 0) { - counter = 0; + ZipArchiveEntry getNextEntry() throws IOException { + if (!(in instanceof ZipArchiveInputStream)) { + throw new IllegalStateException("getNextEntry() is only allowed for stream based zip processing."); } - ((PushbackInputStream)in).unread(b); - } - @Override - public void unread(byte[] b, int off, int len) throws IOException { - if (!(in instanceof PushbackInputStream)) { - throw new UnsupportedOperationException("underlying stream is not a PushbackInputStream"); - } - counter -= len; - if (--counter < 0) { - counter = 0; + try { + entry = ((ZipArchiveInputStream) in).getNextZipEntry(); + return entry; + } catch (ZipException ze) { + if (ze.getMessage().startsWith("Unexpected record signature")) { + throw new NotOfficeXmlFileException( + "No valid entries or contents found, this is not a valid OOXML (Office Open XML) file", ze); + } + throw ze; } - ((PushbackInputStream)in).unread(b, off, len); - } - - @Override - @SuppressForbidden("just delegating") - public int available() throws IOException { - return in.available(); - } - - @Override - public boolean markSupported() { - return in.markSupported(); - } - - @Override - public synchronized void mark(int readlimit) { - markPos = counter; - in.mark(readlimit); } /** * Sets the zip entry for a detailed logging * @param entry the entry */ - void setEntry(ZipEntry entry) { + void setEntry(ZipArchiveEntry entry) { this.entry = entry; } }
\ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipEntrySource.java b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipEntrySource.java index 65ba942941..00961dffd4 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipEntrySource.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipEntrySource.java @@ -20,7 +20,8 @@ import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; -import java.util.zip.ZipEntry; + +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; /** * An Interface to make getting the different bits @@ -33,7 +34,7 @@ public interface ZipEntrySource extends Closeable { /** * Returns an Enumeration of all the Entries */ - Enumeration<? extends ZipEntry> getEntries(); + Enumeration<? extends ZipArchiveEntry> getEntries(); /** * Return an entry by its path @@ -42,13 +43,13 @@ public interface ZipEntrySource extends Closeable { * * @since POI 4.0.0 */ - ZipEntry getEntry(String path); + ZipArchiveEntry getEntry(String path); /** * Returns an InputStream of the decompressed * data that makes up the entry */ - InputStream getInputStream(ZipEntry entry) throws IOException; + InputStream getInputStream(ZipArchiveEntry entry) throws IOException; /** * Indicates we are done with reading, and diff --git a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipFileZipEntrySource.java b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipFileZipEntrySource.java index 221db9a9ec..363ba9d5a7 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipFileZipEntrySource.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipFileZipEntrySource.java @@ -22,8 +22,9 @@ import static org.apache.commons.collections4.IteratorUtils.asIterator; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; + +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipFile; /** * A ZipEntrySource wrapper around a ZipFile. @@ -50,15 +51,15 @@ public class ZipFileZipEntrySource implements ZipEntrySource { } @Override - public Enumeration<? extends ZipEntry> getEntries() { + public Enumeration<? extends ZipArchiveEntry> getEntries() { if (zipArchive == null) throw new IllegalStateException("Zip File is closed"); - return zipArchive.entries(); + return zipArchive.getEntries(); } @Override - public InputStream getInputStream(ZipEntry entry) throws IOException { + public InputStream getInputStream(ZipArchiveEntry entry) throws IOException { if (zipArchive == null) throw new IllegalStateException("Zip File is closed"); @@ -66,16 +67,16 @@ public class ZipFileZipEntrySource implements ZipEntrySource { } @Override - public ZipEntry getEntry(final String path) { + public ZipArchiveEntry getEntry(final String path) { String normalizedPath = path.replace('\\', '/'); - final ZipEntry entry = zipArchive.getEntry(normalizedPath); + final ZipArchiveEntry entry = zipArchive.getEntry(normalizedPath); if (entry != null) { return entry; } // the opc spec allows case-insensitive filename matching (see #49609) - for (final ZipEntry ze : asIterable(asIterator(zipArchive.entries()))) { + for (final ZipArchiveEntry ze : asIterable(asIterator(zipArchive.getEntries()))) { if (normalizedPath.equalsIgnoreCase(ze.getName().replace('\\','/'))) { return ze; } diff --git a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java index 9c12431ada..e185239ff1 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java @@ -21,9 +21,9 @@ import java.io.InputStream; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; -import java.util.zip.ZipEntry; import org.apache.commons.collections4.IteratorUtils; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; /** * Provides a way to get at all the ZipEntries @@ -44,7 +44,7 @@ public class ZipInputStreamZipEntrySource implements ZipEntrySource { */ public ZipInputStreamZipEntrySource(ZipArchiveThresholdInputStream inp) throws IOException { for (;;) { - final ZipEntry zipEntry = inp.getNextEntry(); + final ZipArchiveEntry zipEntry = inp.getNextEntry(); if (zipEntry == null) { break; } @@ -54,12 +54,12 @@ public class ZipInputStreamZipEntrySource implements ZipEntrySource { } @Override - public Enumeration<? extends ZipEntry> getEntries() { + public Enumeration<? extends ZipArchiveEntry> getEntries() { return IteratorUtils.asEnumeration(zipEntries.values().iterator()); } @Override - public InputStream getInputStream(ZipEntry zipEntry) { + public InputStream getInputStream(ZipArchiveEntry zipEntry) { assert (zipEntry instanceof ZipArchiveFakeEntry); return ((ZipArchiveFakeEntry)zipEntry).getInputStream(); } @@ -76,9 +76,9 @@ public class ZipInputStreamZipEntrySource implements ZipEntrySource { } @Override - public ZipEntry getEntry(final String path) { + public ZipArchiveEntry getEntry(final String path) { final String normalizedPath = path.replace('\\', '/'); - final ZipEntry ze = zipEntries.get(normalizedPath); + final ZipArchiveEntry ze = zipEntries.get(normalizedPath); if (ze != null) { return ze; } diff --git a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipSecureFile.java b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipSecureFile.java index ae2bc192d4..290b5fbd8c 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/util/ZipSecureFile.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/util/ZipSecureFile.java @@ -19,9 +19,9 @@ package org.apache.poi.openxml4j.util; import java.io.File; import java.io.IOException; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipFile; /** * This class wraps a {@link ZipFile} in order to check the @@ -39,7 +39,7 @@ public class ZipSecureFile extends ZipFile { private static long MAX_TEXT_SIZE = 10*1024*1024L; private final String fileName; - + /** * Sets the ratio between de- and inflated bytes to detect zipbomb. * It defaults to 1% (= 0.01d), i.e. when the compression is better than @@ -143,7 +143,7 @@ public class ZipSecureFile extends ZipFile { */ @Override @SuppressWarnings("resource") - public ZipArchiveThresholdInputStream getInputStream(ZipEntry entry) throws IOException { + public ZipArchiveThresholdInputStream getInputStream(ZipArchiveEntry entry) throws IOException { ZipArchiveThresholdInputStream zatis = new ZipArchiveThresholdInputStream(super.getInputStream(entry)); zatis.setEntry(entry); return zatis; diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/temp/AesZipFileZipEntrySource.java b/src/ooxml/java/org/apache/poi/poifs/crypt/temp/AesZipFileZipEntrySource.java index ea430bad08..8c8523d427 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/temp/AesZipFileZipEntrySource.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/temp/AesZipFileZipEntrySource.java @@ -24,20 +24,18 @@ import java.io.FileOutputStream; import java.io.FilterOutputStream; import java.io.IOException; import java.io.InputStream; -import java.security.GeneralSecurityException; import java.security.SecureRandom; import java.util.Enumeration; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipFile; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; import javax.crypto.Cipher; import javax.crypto.CipherInputStream; import javax.crypto.CipherOutputStream; import javax.crypto.spec.SecretKeySpec; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; +import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.poi.openxml4j.util.ZipEntrySource; import org.apache.poi.poifs.crypt.ChainingMode; import org.apache.poi.poifs.crypt.CipherAlgorithm; @@ -57,7 +55,7 @@ public final class AesZipFileZipEntrySource implements ZipEntrySource { private static final POILogger LOG = POILogFactory.getLogger(AesZipFileZipEntrySource.class); private static final String PADDING = "PKCS5Padding"; - + private final File tmpFile; private final ZipFile zipFile; private final Cipher ci; @@ -75,17 +73,17 @@ public final class AesZipFileZipEntrySource implements ZipEntrySource { * so don't rely on file sizes of these custom encrypted zip file entries! */ @Override - public Enumeration<? extends ZipEntry> getEntries() { - return zipFile.entries(); + public Enumeration<? extends ZipArchiveEntry> getEntries() { + return zipFile.getEntries(); } @Override - public ZipEntry getEntry(String path) { + public ZipArchiveEntry getEntry(String path) { return zipFile.getEntry(path); } @Override - public InputStream getInputStream(ZipEntry entry) throws IOException { + public InputStream getInputStream(ZipArchiveEntry entry) throws IOException { InputStream is = zipFile.getInputStream(entry); return new CipherInputStream(is, ci); } @@ -106,7 +104,7 @@ public final class AesZipFileZipEntrySource implements ZipEntrySource { return closed; } - public static AesZipFileZipEntrySource createZipEntrySource(InputStream is) throws IOException, GeneralSecurityException { + public static AesZipFileZipEntrySource createZipEntrySource(InputStream is) throws IOException { // generate session key SecureRandom sr = new SecureRandom(); byte[] ivBytes = new byte[16], keyBytes = new byte[16]; @@ -118,25 +116,25 @@ public final class AesZipFileZipEntrySource implements ZipEntrySource { return fileToSource(tmpFile, keyBytes, ivBytes); } - private static void copyToFile(InputStream is, File tmpFile, byte keyBytes[], byte ivBytes[]) throws IOException, GeneralSecurityException { + private static void copyToFile(InputStream is, File tmpFile, byte keyBytes[], byte ivBytes[]) throws IOException { SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, CipherAlgorithm.aes128.jceId); Cipher ciEnc = CryptoFunctions.getCipher(skeySpec, CipherAlgorithm.aes128, ChainingMode.cbc, ivBytes, Cipher.ENCRYPT_MODE, PADDING); - ZipInputStream zis = new ZipInputStream(is); + ZipArchiveInputStream zis = new ZipArchiveInputStream(is); FileOutputStream fos = new FileOutputStream(tmpFile); - ZipOutputStream zos = new ZipOutputStream(fos); + ZipArchiveOutputStream zos = new ZipArchiveOutputStream(fos); - ZipEntry ze; - while ((ze = zis.getNextEntry()) != null) { + ZipArchiveEntry ze; + while ((ze = zis.getNextZipEntry()) != null) { // the cipher output stream pads the data, therefore we can't reuse the ZipEntry with set sizes // as those will be validated upon close() - ZipEntry zeNew = new ZipEntry(ze.getName()); + ZipArchiveEntry zeNew = new ZipArchiveEntry(ze.getName()); zeNew.setComment(ze.getComment()); zeNew.setExtra(ze.getExtra()); zeNew.setTime(ze.getTime()); // zeNew.setMethod(ze.getMethod()); - zos.putNextEntry(zeNew); - FilterOutputStream fos2 = new FilterOutputStream(zos){ + zos.putArchiveEntry(zeNew); + FilterOutputStream fos2 = new FilterOutputStream(zos) { // don't close underlying ZipOutputStream @Override public void close() {} @@ -145,15 +143,14 @@ public final class AesZipFileZipEntrySource implements ZipEntrySource { IOUtils.copy(zis, cos); cos.close(); fos2.close(); - zos.closeEntry(); - zis.closeEntry(); + zos.closeArchiveEntry(); } zos.close(); fos.close(); zis.close(); } - private static AesZipFileZipEntrySource fileToSource(File tmpFile, byte keyBytes[], byte ivBytes[]) throws ZipException, IOException { + private static AesZipFileZipEntrySource fileToSource(File tmpFile, byte keyBytes[], byte ivBytes[]) throws IOException { SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, CipherAlgorithm.aes128.jceId); Cipher ciDec = CryptoFunctions.getCipher(skeySpec, CipherAlgorithm.aes128, ChainingMode.cbc, ivBytes, Cipher.DECRYPT_MODE, PADDING); return new AesZipFileZipEntrySource(tmpFile, ciDec); diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/temp/SXSSFWorkbookWithCustomZipEntrySource.java b/src/ooxml/java/org/apache/poi/poifs/crypt/temp/SXSSFWorkbookWithCustomZipEntrySource.java index aeb35154a8..59e4ff5b99 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/temp/SXSSFWorkbookWithCustomZipEntrySource.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/temp/SXSSFWorkbookWithCustomZipEntrySource.java @@ -21,7 +21,6 @@ package org.apache.poi.poifs.crypt.temp; import java.io.IOException; import java.io.OutputStream; -import java.security.GeneralSecurityException; import org.apache.poi.openxml4j.util.ZipEntrySource; import org.apache.poi.util.Beta; @@ -52,8 +51,6 @@ public class SXSSFWorkbookWithCustomZipEntrySource extends SXSSFWorkbook { // provide ZipEntrySource to poi which decrypts on the fly source = AesZipFileZipEntrySource.createZipEntrySource(tempData.getInputStream()); injectData(source, stream); - } catch (GeneralSecurityException e) { - throw new IOException(e); } finally { tempData.dispose(); IOUtils.closeQuietly(source); diff --git a/src/ooxml/java/org/apache/poi/xssf/dev/XSSFDump.java b/src/ooxml/java/org/apache/poi/xssf/dev/XSSFDump.java index 392532b601..cee2380402 100644 --- a/src/ooxml/java/org/apache/poi/xssf/dev/XSSFDump.java +++ b/src/ooxml/java/org/apache/poi/xssf/dev/XSSFDump.java @@ -25,6 +25,7 @@ import java.io.OutputStream; import java.util.Enumeration; import java.util.zip.ZipEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.poi.openxml4j.opc.internal.ZipHelper; import org.apache.poi.openxml4j.util.ZipSecureFile; import org.apache.poi.ooxml.util.DocumentHelper; @@ -78,9 +79,9 @@ public final class XSSFDump { createDirIfMissing(root); System.out.println("Dumping to directory " + root); - Enumeration<? extends ZipEntry> en = zip.entries(); + Enumeration<? extends ZipArchiveEntry> en = zip.getEntries(); while (en.hasMoreElements()) { - ZipEntry entry = en.nextElement(); + ZipArchiveEntry entry = en.nextElement(); String name = entry.getName(); int idx = name.lastIndexOf('/'); if (idx != -1) { diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java index 73141707c9..0ed33d1c0b 100644 --- a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java +++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java @@ -31,14 +31,14 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipOutputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.util.ZipArchiveThresholdInputStream; import org.apache.poi.openxml4j.util.ZipEntrySource; import org.apache.poi.openxml4j.util.ZipFileZipEntrySource; +import org.apache.poi.openxml4j.util.ZipSecureFile; import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.formula.udf.UDFFinder; import org.apache.poi.ss.usermodel.CellStyle; @@ -376,11 +376,11 @@ public class SXSSFWorkbook implements Workbook { } protected void injectData(ZipEntrySource zipEntrySource, OutputStream out) throws IOException { - try (ZipOutputStream zos = new ZipOutputStream(out)) { - Enumeration<? extends ZipEntry> en = zipEntrySource.getEntries(); + try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(out)) { + Enumeration<? extends ZipArchiveEntry> en = zipEntrySource.getEntries(); while (en.hasMoreElements()) { - ZipEntry ze = en.nextElement(); - zos.putNextEntry(new ZipEntry(ze.getName())); + ZipArchiveEntry ze = en.nextElement(); + zos.putArchiveEntry(new ZipArchiveEntry(ze.getName())); try (final InputStream is = zipEntrySource.getInputStream(ze)) { if (is instanceof ZipArchiveThresholdInputStream) { // #59743 - disable Threshold handling for SXSSF copy @@ -397,6 +397,8 @@ public class SXSSFWorkbook implements Workbook { } else { IOUtils.copy(is, zos); } + } finally { + zos.closeArchiveEntry(); } } } finally { @@ -928,7 +930,7 @@ public class SXSSFWorkbook implements Workbook { } //Substitute the template entries with the generated sheet data files - final ZipEntrySource source = new ZipFileZipEntrySource(new ZipFile(tmplFile)); + final ZipEntrySource source = new ZipFileZipEntrySource(new ZipSecureFile(tmplFile)); injectData(source, stream); } finally { deleted = tmplFile.delete(); diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java index 9fe945de3d..a6a9a35295 100644 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackage.java @@ -44,10 +44,10 @@ import java.util.List; import java.util.TreeMap; import java.util.function.BiConsumer; import java.util.regex.Pattern; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipOutputStream; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; +import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.poi.EncryptedDocumentException; import org.apache.poi.POIDataSamples; import org.apache.poi.POITestCase; @@ -783,19 +783,19 @@ public final class TestPackage { ByteArrayOutputStream bos = new ByteArrayOutputStream(2500000); try (ZipFile zipFile = ZipHelper.openZipFile(OpenXML4JTestDataSamples.getSampleFile("sample.xlsx")); - ZipOutputStream append = new ZipOutputStream(bos)) { + ZipArchiveOutputStream append = new ZipArchiveOutputStream(bos)) { assertNotNull(zipFile); // first, copy contents from existing war - Enumeration<? extends ZipEntry> entries = zipFile.entries(); + Enumeration<? extends ZipArchiveEntry> entries = zipFile.getEntries(); while (entries.hasMoreElements()) { - final ZipEntry eIn = entries.nextElement(); - final ZipEntry eOut = new ZipEntry(eIn.getName()); + final ZipArchiveEntry eIn = entries.nextElement(); + final ZipArchiveEntry eOut = new ZipArchiveEntry(eIn.getName()); eOut.setTime(eIn.getTime()); eOut.setComment(eIn.getComment()); eOut.setSize(eIn.getSize()); - append.putNextEntry(eOut); + append.putArchiveEntry(eOut); if (!eOut.isDirectory()) { try (InputStream is = zipFile.getInputStream(eIn)) { if (eOut.getName().equals("[Content_Types].xml")) { @@ -818,7 +818,7 @@ public final class TestPackage { } } } - append.closeEntry(); + append.closeArchiveEntry(); } } @@ -918,9 +918,9 @@ public final class TestPackage { long max_size = 0; try (ZipFile zf = ZipHelper.openZipFile(file)) { assertNotNull(zf); - Enumeration<? extends ZipEntry> entries = zf.entries(); + Enumeration<? extends ZipArchiveEntry> entries = zf.getEntries(); while (entries.hasMoreElements()) { - ZipEntry ze = entries.nextElement(); + ZipArchiveEntry ze = entries.nextElement(); if (ze.getSize() == 0) { continue; } @@ -1093,7 +1093,7 @@ public final class TestPackage { try (final ZipPackage pkg = (useStream) ? new ZipPackage(is, PackageAccess.READ) : new ZipPackage(files.getFile(name), PackageAccess.READ)) { pkgTest = pkg; assertNotNull(pkg.getZipArchive()); -// assertFalse(pkg.getZipArchive().isClosed()); + assertFalse(pkg.getZipArchive().isClosed()); pkg.getParts(); fail("Shouldn't work"); } diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/ZipFileAssert.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/ZipFileAssert.java index 3706085c19..f14052172f 100644 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/ZipFileAssert.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/ZipFileAssert.java @@ -29,10 +29,10 @@ import java.io.FileInputStream; import java.io.IOException; import java.util.Set; import java.util.TreeMap; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; import junit.framework.AssertionFailedError; +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.apache.poi.util.IOUtils; import org.junit.Assert; import org.xmlunit.builder.DiffBuilder; @@ -97,10 +97,10 @@ public final class ZipFileAssert { BufferedInputStream buffi = new BufferedInputStream(file_decompress); /* Open the file with the buffer */ - ZipInputStream zis = new ZipInputStream(buffi); + ZipArchiveInputStream zis = new ZipArchiveInputStream(buffi); /* Processing entries of the zip file */ - ZipEntry entree; + ArchiveEntry entree; while ((entree = zis.getNextEntry()) != null) { /* Create a array for the current entry */ diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/internal/marshallers/TestZipPackagePropertiesMarshaller.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/internal/marshallers/TestZipPackagePropertiesMarshaller.java index f9abb2fe8b..30fabfc1f3 100644 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/internal/marshallers/TestZipPackagePropertiesMarshaller.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/internal/marshallers/TestZipPackagePropertiesMarshaller.java @@ -23,9 +23,9 @@ import static org.junit.Assert.assertTrue; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.openxml4j.opc.PackagingURIHelper; import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart; @@ -44,21 +44,21 @@ public class TestZipPackagePropertiesMarshaller { @Test public void withZipOutputStream() throws Exception { assertTrue(marshaller.marshall(new PackagePropertiesPart(null, PackagingURIHelper.createPartName(PACKAGE_RELATIONSHIPS_ROOT_URI)), - new ZipOutputStream(new ByteArrayOutputStream()))); + new ZipArchiveOutputStream(new ByteArrayOutputStream()))); } @Test public void writingFails() throws Exception { assertTrue(marshaller.marshall(new PackagePropertiesPart(null, PackagingURIHelper.createPartName(PACKAGE_RELATIONSHIPS_ROOT_URI)), - new ZipOutputStream(new ByteArrayOutputStream()))); + new ZipArchiveOutputStream(new ByteArrayOutputStream()))); } @Test(expected=OpenXML4JException.class) public void ioException() throws Exception { marshaller.marshall(new PackagePropertiesPart(null, PackagingURIHelper.createPartName(PACKAGE_RELATIONSHIPS_ROOT_URI)), - new ZipOutputStream(new ByteArrayOutputStream()) { + new ZipArchiveOutputStream(new ByteArrayOutputStream()) { @Override - public void putNextEntry(final ZipEntry archiveEntry) throws IOException { + public void putArchiveEntry(final ArchiveEntry archiveEntry) throws IOException { throw new IOException("TestException"); } }); diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/util/TestZipSecureFile.java b/src/ooxml/testcases/org/apache/poi/openxml4j/util/TestZipSecureFile.java index 89f144c1ac..f2a3d77eef 100644 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/util/TestZipSecureFile.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/util/TestZipSecureFile.java @@ -16,14 +16,14 @@ ==================================================================== */ package org.apache.poi.openxml4j.util; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.poi.util.IOUtils; import org.apache.poi.xssf.XSSFTestDataSamples; import org.junit.Test; import java.io.InputStream; import java.util.Enumeration; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; import static org.junit.Assert.assertTrue; @@ -36,9 +36,9 @@ public class TestZipSecureFile { try (ZipFile thresholdInputStream = new ZipFile(XSSFTestDataSamples.getSampleFile("template.xlsx"))) { try (ZipSecureFile secureFile = new ZipSecureFile(XSSFTestDataSamples.getSampleFile("template.xlsx"))) { - Enumeration<? extends ZipEntry> entries = thresholdInputStream.entries(); + Enumeration<? extends ZipArchiveEntry> entries = thresholdInputStream.getEntries(); while (entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); + ZipArchiveEntry entry = entries.nextElement(); try (InputStream inputStream = secureFile.getInputStream(entry)) { assertTrue(IOUtils.toByteArray(inputStream).length > 0); diff --git a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestDecryptor.java b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestDecryptor.java index 1fb4946e46..e80b350824 100644 --- a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestDecryptor.java +++ b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestDecryptor.java @@ -28,11 +28,11 @@ import java.io.IOException; import java.io.InputStream; import java.security.GeneralSecurityException; import java.util.stream.IntStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; import javax.crypto.Cipher; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.apache.poi.POIDataSamples; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; @@ -78,10 +78,10 @@ public class TestDecryptor { } private void zipOk(DirectoryNode root, Decryptor d) throws IOException, GeneralSecurityException { - try (ZipInputStream zin = new ZipInputStream(d.getDataStream(root))) { + try (ZipArchiveInputStream zin = new ZipArchiveInputStream(d.getDataStream(root))) { while (true) { - ZipEntry entry = zin.getNextEntry(); + ZipArchiveEntry entry = zin.getNextZipEntry(); if (entry == null) { break; } @@ -114,13 +114,13 @@ public class TestDecryptor { byte[] buf = new byte[(int) len]; assertEquals(12810, is.read(buf)); - ZipInputStream zin = new ZipInputStream(new ByteArrayInputStream(buf)); + ZipArchiveInputStream zin = new ZipArchiveInputStream(new ByteArrayInputStream(buf)); - while (true) { - ZipEntry entry = zin.getNextEntry(); - if (entry == null) { - break; - } + while (true) { + ZipArchiveEntry entry = zin.getNextZipEntry(); + if (entry==null) { + break; + } IOUtils.toByteArray(zin); } @@ -140,10 +140,10 @@ public class TestDecryptor { d.verifyPassword("pwd123"); final ByteArrayOutputStream bos = new ByteArrayOutputStream(10000); - try (final ZipInputStream zis = new ZipInputStream(d.getDataStream(fs))) { + try (final ZipArchiveInputStream zis = new ZipArchiveInputStream(d.getDataStream(fs))) { IntStream.of(3711, 1155, 445, 9376, 450, 588, 1337, 2593, 304, 7910).forEach(size -> { try { - final ZipEntry ze = zis.getNextEntry(); + final ZipArchiveEntry ze = zis.getNextZipEntry(); assertNotNull(ze); IOUtils.copy(zis, bos); assertEquals(size, bos.size()); diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/TestXWPFBugs.java b/src/ooxml/testcases/org/apache/poi/xwpf/TestXWPFBugs.java index 7f41870419..766164ce33 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/TestXWPFBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/TestXWPFBugs.java @@ -23,11 +23,11 @@ import static org.junit.Assert.assertTrue; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; import javax.crypto.Cipher; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.compress.archivers.zip.ZipFile; import org.apache.poi.POIDataSamples; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.poifs.crypt.CipherAlgorithm; @@ -118,7 +118,7 @@ public class TestXWPFBugs { String files[] = { "bug57031.docx", "bug59058.docx" }; for (String f : files) { ZipFile zf = new ZipFile(POIDataSamples.getDocumentInstance().getFile(f)); - ZipEntry entry = zf.getEntry("word/document.xml"); + ZipArchiveEntry entry = zf.getEntry("word/document.xml"); DocumentDocument document = DocumentDocument.Factory.parse(zf.getInputStream(entry)); assertNotNull(document); zf.close(); |