This is an automated email from the ASF dual-hosted git repository.

pjfanning pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/poi.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 3df1a5a8af improve ZipArchiveFakeEntry getSize (#1150)
3df1a5a8af is described below

commit 3df1a5a8af35216b05c01fac96dfd2fd06ce2f89
Author: PJ Fanning <[email protected]>
AuthorDate: Wed Jun 24 12:53:56 2026 +0100

    improve ZipArchiveFakeEntry getSize (#1150)
    
    * improve ZipArchiveFakeEntry getSize
    
    * add tests
---
 .../poi/openxml4j/util/ZipArchiveFakeEntry.java    |  22 ++++-
 .../util/ZipInputStreamZipEntrySource.java         |   3 +-
 .../openxml4j/util/TestZipArchiveFakeEntry.java    | 101 +++++++++++++++++++++
 3 files changed, 122 insertions(+), 4 deletions(-)

diff --git 
a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipArchiveFakeEntry.java
 
b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipArchiveFakeEntry.java
index f617a8dde9..5ea9394c44 100644
--- 
a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipArchiveFakeEntry.java
+++ 
b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipArchiveFakeEntry.java
@@ -64,6 +64,7 @@ public final class ZipArchiveFakeEntry extends 
ZipArchiveEntry implements Closea
     private byte[] data;
     private File tempFile;
     private EncryptedTempData encryptedTempData;
+    private final long numberOfBytes;
 
     ZipArchiveFakeEntry(ZipArchiveEntry entry, InputStream inp) throws 
IOException {
         super(entry.getName());
@@ -77,13 +78,13 @@ public final class ZipArchiveFakeEntry extends 
ZipArchiveEntry implements Closea
                 if (ZipInputStreamZipEntrySource.shouldEncryptTempFiles()) {
                     encryptedTempData = new EncryptedTempData();
                     try (OutputStream os = 
encryptedTempData.getOutputStream()) {
-                        IOUtils.copy(inp, os);
+                        numberOfBytes = IOUtils.copy(inp, os);
                     }
                 } else {
                     tempFile = TempFile.createTempFile("poi-zip-entry", 
".tmp");
                     LOG.atInfo().log("Creating temp file {} for zip entry {} 
of size {} bytes",
                             tempFile.getAbsolutePath(), entry.getName(), 
entrySize);
-                    IOUtils.copy(inp, tempFile);
+                    numberOfBytes = IOUtils.copy(inp, tempFile);
                 }
                 success = true;
             } finally {
@@ -103,9 +104,15 @@ public final class ZipArchiveFakeEntry extends 
ZipArchiveEntry implements Closea
             // Grab the de-compressed contents for later
             data = (entrySize == -1) ? IOUtils.toByteArrayWithMaxLength(inp, 
getMaxEntrySize()) :
                     IOUtils.toByteArray(inp, entrySize, getMaxEntrySize(), 
"ZipArchiveFakeEntry.setMaxEntrySize()");
+            numberOfBytes = data.length;
         }
     }
 
+    @Override
+    public long getSize() {
+        return numberOfBytes;
+    }
+
     /**
      * Returns zip entry.
      * @return input stream
@@ -150,4 +157,15 @@ public final class ZipArchiveFakeEntry extends 
ZipArchiveEntry implements Closea
             }
         }
     }
+
+    // open for testing
+    boolean isUnencryptedTempFileBacked() {
+        return tempFile != null && tempFile.exists();
+    }
+
+    // open for testing
+    boolean isEncryptedTempFileBacked() {
+        return encryptedTempData != null;
+    }
+
 }
diff --git 
a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java
 
b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java
index 71be7d3868..8c92298057 100644
--- 
a/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java
+++ 
b/poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java
@@ -29,7 +29,6 @@ import java.util.Set;
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.apache.poi.openxml4j.opc.internal.InvalidZipException;
 import org.apache.poi.util.IOUtils;
-import org.apache.poi.util.StringUtil;
 
 /**
  * Provides a way to get at all the ZipEntries
@@ -44,7 +43,7 @@ public class ZipInputStreamZipEntrySource implements 
ZipEntrySource {
     private static boolean encryptTempFiles = false;
     private final Map<String, ZipArchiveFakeEntry> zipEntries = new 
HashMap<>();
 
-    private InputStream streamToClose;
+    private final InputStream streamToClose;
 
     /**
      * Set the threshold at which a zip entry is regarded as too large for 
holding in memory
diff --git 
a/poi-ooxml/src/test/java/org/apache/poi/openxml4j/util/TestZipArchiveFakeEntry.java
 
b/poi-ooxml/src/test/java/org/apache/poi/openxml4j/util/TestZipArchiveFakeEntry.java
new file mode 100644
index 0000000000..366a1d4d19
--- /dev/null
+++ 
b/poi-ooxml/src/test/java/org/apache/poi/openxml4j/util/TestZipArchiveFakeEntry.java
@@ -0,0 +1,101 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.openxml4j.util;
+
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
+import org.apache.poi.util.IOUtils;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.parallel.Isolated;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+@Isolated // changes static values, so other tests should not run at the same 
time
+public class TestZipArchiveFakeEntry {
+    @Test
+    void testSize() throws IOException {
+        runTestSize(false, false);
+    }
+
+    @Test
+    void testSizeTempFileBacked() throws IOException {
+        ZipInputStreamZipEntrySource.setThresholdBytesForTempFiles(0);
+        try {
+            runTestSize(true, false);
+        } finally {
+            ZipInputStreamZipEntrySource.setThresholdBytesForTempFiles(-1);
+        }
+    }
+
+    @Test
+    void testSizeEncryptedTempFileBacked() throws IOException {
+        ZipInputStreamZipEntrySource.setThresholdBytesForTempFiles(0);
+        ZipInputStreamZipEntrySource.setEncryptTempFiles(true);
+        try {
+            runTestSize(false, true);
+        } finally {
+            ZipInputStreamZipEntrySource.setThresholdBytesForTempFiles(-1);
+            ZipInputStreamZipEntrySource.setEncryptTempFiles(false);
+        }
+    }
+
+    @Test
+    void testInvalidEntrySize() throws IOException {
+        final long fakeLen = 123;
+        final String fakeValue = "fakeValue";
+        ZipArchiveEntry entry = new ZipArchiveEntry("hack123") {
+            @Override
+            public long getSize() {
+                return fakeLen;
+            }
+        };
+        UnsynchronizedByteArrayOutputStream baos = 
UnsynchronizedByteArrayOutputStream.builder().get();
+        final byte[] data = fakeValue.getBytes(StandardCharsets.UTF_8);
+        baos.write(data);
+        // the data in the stream is less than the fakeLen in the entry
+        // this is a regression test for the existing internal behaviour - if 
we choose to change the
+        // behaviour in the future, this test can be updated
+        assertThrows(EOFException.class, () -> new ZipArchiveFakeEntry(entry, 
baos.toInputStream()));
+    }
+
+    static void runTestSize(boolean unencryptedTempFileExpected,
+                            boolean encryptedTempFileExpected) throws 
IOException {
+        final String fakeEntryName = "hack123";
+        final String fakeValue = "fakeValue";
+        ZipArchiveEntry entry = new ZipArchiveEntry(fakeEntryName);
+        UnsynchronizedByteArrayOutputStream baos = 
UnsynchronizedByteArrayOutputStream.builder().get();
+        final byte[] data = fakeValue.getBytes(StandardCharsets.UTF_8);
+        baos.write(data);
+        try (ZipArchiveFakeEntry zipArchiveFakeEntry = new 
ZipArchiveFakeEntry(entry, baos.toInputStream())) {
+            assertEquals(fakeEntryName, zipArchiveFakeEntry.getName());
+            UnsynchronizedByteArrayOutputStream baos2 = 
UnsynchronizedByteArrayOutputStream.builder().get();
+            assertEquals(data.length, 
IOUtils.copy(zipArchiveFakeEntry.getInputStream(), baos2));
+            assertEquals(fakeValue, 
baos2.toString(StandardCharsets.UTF_8.name()));
+            assertEquals(data.length, zipArchiveFakeEntry.getSize());
+            assertEquals(unencryptedTempFileExpected, 
zipArchiveFakeEntry.isUnencryptedTempFileBacked());
+            assertEquals(encryptedTempFileExpected, 
zipArchiveFakeEntry.isEncryptedTempFileBacked());
+        }
+    }
+
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to