git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1893435 13f79535-47bb-0310-9956-ffa450edef68tags/REL_5_2_0
@@ -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') | |||
@@ -17,17 +17,13 @@ | |||
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(); | |||
} |
@@ -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. |
@@ -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()); | |||
} | |||
} | |||
} |
@@ -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()) { |