From 68cfff53b4e45d6516a29a0741972c107068f4eb Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Thu, 5 Mar 2026 09:59:02 +0100 Subject: [PATCH 1/4] add password --- .../extractor/EventBasedExcelExtractor.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/poi/src/main/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java b/poi/src/main/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java index a3bb7fb633f..f567be82d84 100644 --- a/poi/src/main/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java +++ b/poi/src/main/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java @@ -63,18 +63,35 @@ Licensed to the Apache Software Foundation (ASF) under one or more public class EventBasedExcelExtractor implements POIOLE2TextExtractor, org.apache.poi.ss.extractor.ExcelExtractor { private final POIFSFileSystem poifs; private final DirectoryNode _dir; + private final char[] _password; private boolean doCloseFilesystem = true; boolean _includeSheetNames = true; boolean _formulasNotResults; public EventBasedExcelExtractor(DirectoryNode dir) { + this(dir, null); + } + + /** + * @since 6.0.0 + */ + public EventBasedExcelExtractor(DirectoryNode dir, char[] password) { poifs = null; _dir = dir; + _password = password; } public EventBasedExcelExtractor(POIFSFileSystem fs) { + this(fs, null); + } + + /** + * @since 6.0.0 + */ + public EventBasedExcelExtractor(POIFSFileSystem fs, char[] password) { poifs = fs; _dir = fs.getRoot(); + _password = password; } /** @@ -95,7 +112,6 @@ public SummaryInformation getSummaryInformation() { throw new IllegalStateException("Metadata extraction not supported in streaming mode, please use ExcelExtractor"); } - /** * Would control the inclusion of cell comments from the document, * if we supported it From b40f254771f701029b2495e789c94e4048ff7315 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Thu, 5 Mar 2026 10:14:03 +0100 Subject: [PATCH 2/4] more changes --- .../poi/extractor/MainExtractorFactory.java | 31 +++++++++++-------- .../extractor/EventBasedExcelExtractor.java | 2 +- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/poi/src/main/java/org/apache/poi/extractor/MainExtractorFactory.java b/poi/src/main/java/org/apache/poi/extractor/MainExtractorFactory.java index eba21972d9f..a75a02d5b34 100644 --- a/poi/src/main/java/org/apache/poi/extractor/MainExtractorFactory.java +++ b/poi/src/main/java/org/apache/poi/extractor/MainExtractorFactory.java @@ -44,34 +44,39 @@ public boolean accepts(FileMagic fm) { @SuppressWarnings({"java:S2095"}) @Override public POITextExtractor create(File file, String password) throws IOException { - return create(new POIFSFileSystem(file, true).getRoot(), password); + try (POIFSFileSystem fs = new POIFSFileSystem(file)) { + return create(fs.getRoot(), password); + } } @Override public POITextExtractor create(InputStream inputStream, String password) throws IOException { - return create(new POIFSFileSystem(inputStream).getRoot(), password); + try (POIFSFileSystem fs = new POIFSFileSystem(inputStream)) { + return create(fs.getRoot(), password); + } } @SuppressWarnings("java:S2093") @Override public POITextExtractor create(DirectoryNode poifsDir, String password) throws IOException { final String oldPW = Biff8EncryptionKey.getCurrentUserPassword(); - try { - Biff8EncryptionKey.setCurrentUserPassword(password); - if (poifsDir.hasEntry(InternalWorkbook.OLD_WORKBOOK_DIR_ENTRY_NAME)) { + if (poifsDir.hasEntry(InternalWorkbook.OLD_WORKBOOK_DIR_ENTRY_NAME)) { + Biff8EncryptionKey.setCurrentUserPassword(password); + try { return new OldExcelExtractor(poifsDir); + } finally { + Biff8EncryptionKey.setCurrentUserPassword(oldPW); } + } - // Look for certain entries in the stream, to figure it out from - for (String workbookName : WORKBOOK_DIR_ENTRY_NAMES_CASE_INSENSITIVE) { - if (poifsDir.hasEntryCaseInsensitive(workbookName)) { - return ExtractorFactory.getPreferEventExtractor() ? new EventBasedExcelExtractor(poifsDir) : new ExcelExtractor(poifsDir); - } + // Look for certain entries in the stream, to figure it out from + for (String workbookName : WORKBOOK_DIR_ENTRY_NAMES_CASE_INSENSITIVE) { + if (poifsDir.hasEntryCaseInsensitive(workbookName)) { + return ExtractorFactory.getPreferEventExtractor() ? + new EventBasedExcelExtractor(poifsDir, password.toCharArray()) : + new ExcelExtractor(poifsDir, password.toCharArray()); } - - } finally { - Biff8EncryptionKey.setCurrentUserPassword(oldPW); } return null; diff --git a/poi/src/main/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java b/poi/src/main/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java index f567be82d84..3f5144a04a0 100644 --- a/poi/src/main/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java +++ b/poi/src/main/java/org/apache/poi/hssf/extractor/EventBasedExcelExtractor.java @@ -174,7 +174,7 @@ private TextListener triggerExtraction() throws IOException { HSSFRequest request = new HSSFRequest(); request.addListenerForAllRecords(ft); - factory.processWorkbookEvents(request, _dir); + factory.processWorkbookEvents(request, _dir, _password); return tl; } From a7116636b4c2e64518d094ca74a6527f6274f5ba Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Thu, 5 Mar 2026 10:41:25 +0100 Subject: [PATCH 3/4] Update MainExtractorFactory.java --- .../java/org/apache/poi/extractor/MainExtractorFactory.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/poi/src/main/java/org/apache/poi/extractor/MainExtractorFactory.java b/poi/src/main/java/org/apache/poi/extractor/MainExtractorFactory.java index a75a02d5b34..2cd40e8e7aa 100644 --- a/poi/src/main/java/org/apache/poi/extractor/MainExtractorFactory.java +++ b/poi/src/main/java/org/apache/poi/extractor/MainExtractorFactory.java @@ -73,9 +73,10 @@ public POITextExtractor create(DirectoryNode poifsDir, String password) throws I // Look for certain entries in the stream, to figure it out from for (String workbookName : WORKBOOK_DIR_ENTRY_NAMES_CASE_INSENSITIVE) { if (poifsDir.hasEntryCaseInsensitive(workbookName)) { + final char[] passArray = password == null ? null : password.toCharArray(); return ExtractorFactory.getPreferEventExtractor() ? - new EventBasedExcelExtractor(poifsDir, password.toCharArray()) : - new ExcelExtractor(poifsDir, password.toCharArray()); + new EventBasedExcelExtractor(poifsDir, passArray) : + new ExcelExtractor(poifsDir, passArray); } } From 1dc015e90a49cf9b7d3667748f751643938f2bea Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Thu, 5 Mar 2026 11:47:51 +0100 Subject: [PATCH 4/4] Update MainExtractorFactory.java --- .../poi/extractor/MainExtractorFactory.java | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/poi/src/main/java/org/apache/poi/extractor/MainExtractorFactory.java b/poi/src/main/java/org/apache/poi/extractor/MainExtractorFactory.java index 2cd40e8e7aa..8a39bc360a8 100644 --- a/poi/src/main/java/org/apache/poi/extractor/MainExtractorFactory.java +++ b/poi/src/main/java/org/apache/poi/extractor/MainExtractorFactory.java @@ -31,6 +31,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.FileMagic; import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.ExceptionUtil; /** * ExtractorFactory for HSSF and Old Excel format @@ -44,16 +45,38 @@ public boolean accepts(FileMagic fm) { @SuppressWarnings({"java:S2095"}) @Override public POITextExtractor create(File file, String password) throws IOException { - try (POIFSFileSystem fs = new POIFSFileSystem(file)) { - return create(fs.getRoot(), password); + POIFSFileSystem fs = new POIFSFileSystem(file, true); + POITextExtractor extractor = null; + try { + extractor = create(fs.getRoot(), password); + } catch (Throwable t) { + if (!ExceptionUtil.isFatal(t)) { + fs.close(); + throw t; + } + } + if (extractor == null) { + fs.close(); } + return extractor; } @Override public POITextExtractor create(InputStream inputStream, String password) throws IOException { - try (POIFSFileSystem fs = new POIFSFileSystem(inputStream)) { - return create(fs.getRoot(), password); + POIFSFileSystem fs = new POIFSFileSystem(inputStream); + POITextExtractor extractor = null; + try { + extractor = create(fs.getRoot(), password); + } catch (Throwable t) { + if (!ExceptionUtil.isFatal(t)) { + fs.close(); + throw t; + } + } + if (extractor == null) { + fs.close(); } + return extractor; } @SuppressWarnings("java:S2093")