]> source.dussan.org Git - poi.git/commitdiff
add support for encrypting temp files
authorPJ Fanning <fanningpj@apache.org>
Sun, 19 Sep 2021 10:59:52 +0000 (10:59 +0000)
committerPJ Fanning <fanningpj@apache.org>
Sun, 19 Sep 2021 10:59:52 +0000 (10:59 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1893435 13f79535-47bb-0310-9956-ffa450edef68

poi-ooxml/build.gradle
poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipArchiveFakeEntry.java
poi-ooxml/src/main/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java
poi-ooxml/src/main/java/org/apache/poi/poifs/crypt/temp/EncryptedTempData.java
poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java

index f8ac5a93ae48852a52a10087557c18ffc4385bbf..87cf391d539b3a832cd45238da2d70e1cb6ab11a 100644 (file)
@@ -64,6 +64,7 @@ java {
 
 dependencies {
     api project(':poi')
+    //implementation files('/Users/pj.fanning/Downloads/poi-bin-5.1.1-SNAPSHOT/poi-ooxml-lite-5.1.1-SNAPSHOT.jar')
     api project(':poi-ooxml-full')
     api project(path: ':poi-ooxml-full', configuration: 'archives')
 
index 6c62e5c74db295bc83e494a69f05ea305a710686..36dc170be0be153c1692df8dbdd2d0098892c87a 100644 (file)
 
 package org.apache.poi.openxml4j.util;
 
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.io.IOException;
+import java.io.*;
 
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
+import org.apache.poi.poifs.crypt.temp.EncryptedTempData;
 import org.apache.poi.util.IOUtils;
 import org.apache.poi.util.TempFile;
 
@@ -42,6 +38,7 @@ import org.apache.poi.util.TempFile;
     private static Logger LOG = LogManager.getLogger(ZipArchiveFakeEntry.class);
     private byte[] data;
     private File tempFile;
+    private EncryptedTempData encryptedTempData;
 
     ZipArchiveFakeEntry(ZipArchiveEntry entry, InputStream inp) throws IOException {
         super(entry.getName());
@@ -50,10 +47,17 @@ import org.apache.poi.util.TempFile;
 
         final int threshold = ZipInputStreamZipEntrySource.getThresholdBytesForTempFiles();
         if (threshold >= 0 && entrySize >= threshold) {
-            tempFile = TempFile.createTempFile("poi-zip-entry", ".tmp");
-            LOG.atInfo().log("created for temp file {} for zip entry {} of size {} bytes",
-                    () -> tempFile.getAbsolutePath(), () -> entry.getName(), () -> entrySize);
-            IOUtils.copy(inp, tempFile);
+            if (ZipInputStreamZipEntrySource.shouldEncryptTempFiles()) {
+                encryptedTempData = new EncryptedTempData();
+                try (OutputStream os = encryptedTempData.getOutputStream()) {
+                    IOUtils.copy(inp, os);
+                }
+            } else {
+                tempFile = TempFile.createTempFile("poi-zip-entry", ".tmp");
+                LOG.atInfo().log("created for temp file {} for zip entry {} of size {} bytes",
+                        () -> tempFile.getAbsolutePath(), () -> entry.getName(), () -> entrySize);
+                IOUtils.copy(inp, tempFile);
+            }
         } else {
             if (entrySize < -1 || entrySize >= Integer.MAX_VALUE) {
                 throw new IOException("ZIP entry size is too large or invalid");
@@ -72,7 +76,13 @@ import org.apache.poi.util.TempFile;
      * @see ZipInputStreamZipEntrySource#setThresholdBytesForTempFiles(int)
      */
     public InputStream getInputStream() {
-        if (tempFile != null) {
+        if (encryptedTempData != null) {
+            try {
+                return encryptedTempData.getInputStream();
+            } catch (IOException e) {
+                throw new RuntimeException("failed to read from encryped temp data", e);
+            }
+        } else if (tempFile != null) {
             try {
                 return new FileInputStream(tempFile);
             } catch (FileNotFoundException e) {
@@ -91,6 +101,9 @@ import org.apache.poi.util.TempFile;
     @Override
     public void close() throws IOException {
         data = null;
+        if (encryptedTempData != null) {
+            encryptedTempData.dispose();
+        }
         if (tempFile != null) {
             tempFile.delete();
         }
index fedaff19908e13e21248fc26c9f9c3ff96038d11..cea12db5fd04a287ae984c52b6651b0f6ff3fe27 100644 (file)
@@ -35,6 +35,7 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
  */
 public class ZipInputStreamZipEntrySource implements ZipEntrySource {
     private static int thresholdForTempFiles = -1;
+    private static boolean encryptTempFiles = false;
     private final Map<String, ZipArchiveFakeEntry> zipEntries = new HashMap<>();
 
     private InputStream streamToClose;
@@ -47,6 +48,7 @@ public class ZipInputStreamZipEntrySource implements ZipEntrySource {
      *                       and that zip entries with more than 2GB of data after decompressing will fail, 0 means all
      *                       zip entries are stored in temp files. A threshold like 50000000 (approx 50Mb is recommended)
      * @since POI 5.1.0
+     * @see #setEncryptTempFiles(boolean)
      */
     public static void setThresholdBytesForTempFiles(int thresholdBytes) {
         thresholdForTempFiles = thresholdBytes;
@@ -62,6 +64,24 @@ public class ZipInputStreamZipEntrySource implements ZipEntrySource {
         return thresholdForTempFiles;
     }
 
+    /**
+     * Encrypt temp files when they are used. Only affects temp files related to zip entries.
+     * @param encrypt whether temp files should be encrypted
+     * @since POI 5.1.0
+     * @see #setThresholdBytesForTempFiles(int)
+     */
+    public static void setEncryptTempFiles(boolean encrypt) {
+        encryptTempFiles = encrypt;
+    }
+
+    /**
+     * Whether temp files should be encrypted. Only affects temp files related to zip entries.
+     * @since POI 5.1.0
+     */
+    public static boolean shouldEncryptTempFiles() {
+        return encryptTempFiles;
+    }
+
     /**
      * Reads all the entries from the ZipInputStream 
      *  into memory, and don't close (since POI 4.0.1) the source stream.
index e1ea120e090cd36c1652c008d1f65ced014d0bf7..9f219f1a803629b13f16bff237cba1620c8e6f86 100644 (file)
@@ -91,7 +91,7 @@ public class EncryptedTempData {
      */
     public void dispose() {
         if (!tempFile.delete()) {
-            LOG.atWarn().log("{} can't be removed (or was already removed).", tempFile.getAbsolutePath());
+            LOG.atWarn().log("{} can't be removed (or was already removed).", () -> tempFile.getAbsolutePath());
         }
     }
 }
index 9845af910db692b8e67bed56678036e242a13c63..04ecbbfb6e0f1521706a3002a2bb72b9b8eaa840 100644 (file)
@@ -188,6 +188,29 @@ public final class TestXSSFWorkbook extends BaseTestXWorkbook {
         }
     }
 
+    @Test
+    void existingWithZipEntryEncryptedTempFiles() throws Exception {
+        int defaultThreshold = ZipInputStreamZipEntrySource.getThresholdBytesForTempFiles();
+        boolean defaultEncryptFlag = ZipInputStreamZipEntrySource.shouldEncryptTempFiles();
+        ZipInputStreamZipEntrySource.setEncryptTempFiles(true);
+        ZipInputStreamZipEntrySource.setThresholdBytesForTempFiles(100);
+        try (XSSFWorkbook workbook = openSampleWorkbook("Formatting.xlsx");
+             OPCPackage pkg = OPCPackage.open(openSampleFileStream("Formatting.xlsx"))) {
+            assertNotNull(workbook.getSharedStringSource());
+            assertNotNull(workbook.getStylesSource());
+
+            // And check a few low level bits too
+            PackagePart wbPart = pkg.getPart(PackagingURIHelper.createPartName("/xl/workbook.xml"));
+
+            // Links to the three sheets, shared, styles and themes
+            assertTrue(wbPart.hasRelationships());
+            assertEquals(6, wbPart.getRelationships().size());
+        } finally {
+            ZipInputStreamZipEntrySource.setThresholdBytesForTempFiles(defaultThreshold);
+            ZipInputStreamZipEntrySource.setEncryptTempFiles(defaultEncryptFlag);
+        }
+    }
+
     @Test
     void getCellStyleAt() throws IOException{
         try (XSSFWorkbook workbook = new XSSFWorkbook()) {