From 99117381e59d9a7f2abe27784009358c672c0ae3 Mon Sep 17 00:00:00 2001 From: Tim Allison Date: Wed, 20 Sep 2023 20:32:59 +0000 Subject: [PATCH] Bug47950 -- make stream/directory name lookup in OLE2 case insensitive git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1912438 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/examples/hpsf/CopyCompare.java | 4 +- .../examples/hpsf/WriteAuthorAndTitle.java | 2 +- .../apache/poi/stress/HPSFFileHandler.java | 2 +- .../poi/stress/POIXMLDocumentHandler.java | 2 +- .../extractor/POIXMLExtractorFactory.java | 4 +- .../poi/poifs/crypt/tests/TestEncryptor.java | 4 +- .../poi/xssf/usermodel/TestXSSFBugs.java | 8 +- .../ole2/OLE2ScratchpadExtractorFactory.java | 12 +- .../org/apache/poi/hpbf/dev/HPBFDumper.java | 6 +- .../org/apache/poi/hpbf/model/HPBFPart.java | 4 +- .../org/apache/poi/hslf/dev/PPTXMLDump.java | 2 +- .../poi/hslf/record/CurrentUserAtom.java | 2 +- .../poi/hslf/usermodel/HSLFSlideShow.java | 2 +- .../poi/hslf/usermodel/HSLFSlideShowImpl.java | 12 +- .../org/apache/poi/hwpf/HWPFDocument.java | 6 +- .../org/apache/poi/hwpf/HWPFDocumentCore.java | 8 +- .../hwpf/converter/WordToTextConverter.java | 2 +- .../poi/hwpf/usermodel/ObjectPoolImpl.java | 2 +- .../java/org/apache/poi/hslf/TestReWrite.java | 10 +- .../poi/hslf/extractor/TestExtractor.java | 4 +- .../poi/hslf/model/TestTextRunReWrite.java | 8 +- .../poi/hslf/record/TestCurrentUserAtom.java | 2 +- .../poi/hslf/record/TestExOleObjStg.java | 2 +- .../hsmf/parsers/TestPOIFSChunkParser.java | 46 ++--- .../org/apache/poi/hwpf/HWPFDocFixture.java | 4 +- .../poi/hwpf/extractor/TestWordExtractor.java | 24 ++- .../main/java/org/apache/poi/POIDocument.java | 10 +- .../poi/extractor/ExtractorFactory.java | 6 +- .../poi/extractor/MainExtractorFactory.java | 13 +- .../java/org/apache/poi/hpsf/PropertySet.java | 4 +- .../hssf/eventusermodel/HSSFEventFactory.java | 14 +- .../poi/hssf/extractor/OldExcelExtractor.java | 5 +- .../poi/hssf/model/InternalWorkbook.java | 15 +- .../poi/hssf/usermodel/HSSFObjectData.java | 3 +- .../poi/hssf/usermodel/HSSFPatriarch.java | 2 +- .../poi/hssf/usermodel/HSSFWorkbook.java | 26 +-- .../poi/poifs/crypt/DataSpaceMapUtils.java | 8 +- .../crypt/cryptoapi/CryptoAPIDecryptor.java | 6 +- .../poi/poifs/filesystem/DirectoryEntry.java | 28 ++- .../poi/poifs/filesystem/DirectoryNode.java | 116 +++++++++--- .../filesystem/DocumentFactoryHelper.java | 2 +- .../filesystem/FilteringDirectoryNode.java | 24 ++- .../poi/poifs/filesystem/Ole10Native.java | 4 +- .../poi/poifs/macros/VBAMacroReader.java | 2 +- .../apache/poi/sl/usermodel/ObjectShape.java | 2 +- .../poi/sl/usermodel/SlideShowFactory.java | 6 +- .../poi/ss/extractor/EmbeddedExtractor.java | 8 +- .../poi/ss/usermodel/WorkbookFactory.java | 6 +- .../poi/hpsf/basic/TestReadAllFiles.java | 2 +- .../org/apache/poi/hpsf/basic/TestWrite.java | 24 +-- .../poi/hpsf/basic/TestWriteWellKnown.java | 2 +- .../hssf/extractor/TestExcelExtractor.java | 10 +- .../apache/poi/hssf/usermodel/TestBugs.java | 2 +- .../poi/hssf/usermodel/TestHSSFWorkbook.java | 2 +- .../TestNonStandardWorkbookStreamNames.java | 3 +- .../hssf/usermodel/TestPOIFSProperties.java | 2 +- .../poi/poifs/filesystem/ReaderWriter.java | 2 +- .../poifs/filesystem/TestDirectoryNode.java | 10 +- .../poi/poifs/filesystem/TestDocument.java | 4 +- .../filesystem/TestDocumentInputStream.java | 12 +- .../poifs/filesystem/TestEmptyDocument.java | 4 +- .../poi/poifs/filesystem/TestEntryUtils.java | 44 ++--- .../TestFilteringDirectoryNode.java | 72 ++++---- .../poifs/filesystem/TestPOIFSFileSystem.java | 2 +- .../poifs/filesystem/TestPOIFSMiniStore.java | 4 +- .../poi/poifs/filesystem/TestPOIFSStream.java | 168 +++++++++--------- .../poifs/filesystem/TestPropertySorter.java | 4 +- test-data/document/47950_lower.doc | Bin 0 -> 27136 bytes test-data/document/47950_normal.doc | Bin 0 -> 27136 bytes test-data/document/47950_upper.doc | Bin 0 -> 27136 bytes 70 files changed, 503 insertions(+), 364 deletions(-) create mode 100644 test-data/document/47950_lower.doc create mode 100644 test-data/document/47950_normal.doc create mode 100644 test-data/document/47950_upper.doc diff --git a/poi-examples/src/main/java/org/apache/poi/examples/hpsf/CopyCompare.java b/poi-examples/src/main/java/org/apache/poi/examples/hpsf/CopyCompare.java index 010504140c..fef6ae5aef 100644 --- a/poi-examples/src/main/java/org/apache/poi/examples/hpsf/CopyCompare.java +++ b/poi-examples/src/main/java/org/apache/poi/examples/hpsf/CopyCompare.java @@ -174,8 +174,8 @@ public final class CopyCompare { for (int i=0; i((HSLFSlideShow)SlideShowFactory.create(poifsDir)); } - if (poifsDir.hasEntry("VisioDocument")) { + if (poifsDir.hasEntryCaseInsensitive("VisioDocument")) { return new VisioTextExtractor(poifsDir); } - if (poifsDir.hasEntry("Quill")) { + if (poifsDir.hasEntryCaseInsensitive("Quill")) { return new PublisherTextExtractor(poifsDir); } for (String entryName : OUTLOOK_ENTRY_NAMES) { - if (poifsDir.hasEntry(entryName)) { + if (poifsDir.hasEntryCaseInsensitive(entryName)) { return new OutlookTextExtractor(poifsDir); } } @@ -168,7 +168,7 @@ public class OLE2ScratchpadExtractorFactory implements ExtractorProvider { } else if (ext instanceof WordExtractor) { // These are in ObjectPool -> _... under the root try { - DirectoryEntry op = (DirectoryEntry) root.getEntry("ObjectPool"); + DirectoryEntry op = (DirectoryEntry) root.getEntryCaseInsensitive("ObjectPool"); StreamSupport.stream(op.spliterator(), false) .filter(entry -> entry.getName().startsWith("_")) .forEach(dirs::add); diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/dev/HPBFDumper.java b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/dev/HPBFDumper.java index 4fccf48565..5154df9849 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/dev/HPBFDumper.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/dev/HPBFDumper.java @@ -103,7 +103,7 @@ public final class HPBFDumper { */ public void dumpEscher() throws IOException { DirectoryNode escherDir = (DirectoryNode) - fs.getRoot().getEntry("Escher"); + fs.getRoot().getEntryCaseInsensitive("Escher"); dumpEscherStm(escherDir); dumpEscherDelayStm(escherDir); @@ -343,9 +343,9 @@ public final class HPBFDumper { public void dumpQuill() throws IOException { DirectoryNode quillDir = (DirectoryNode) - fs.getRoot().getEntry("Quill"); + fs.getRoot().getEntryCaseInsensitive("Quill"); DirectoryNode quillSubDir = (DirectoryNode) - quillDir.getEntry("QuillSub"); + quillDir.getEntryCaseInsensitive("QuillSub"); dump001CompObj(quillSubDir); dumpCONTENTSraw(quillSubDir); diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/HPBFPart.java b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/HPBFPart.java index c3d44099de..8016e9b718 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/HPBFPart.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hpbf/model/HPBFPart.java @@ -44,7 +44,7 @@ public abstract class HPBFPart { DirectoryNode dir = getDir(baseDir, path); String name = path[path.length-1]; - if (!dir.hasEntry(name)) { + if (!dir.hasEntryCaseInsensitive(name)) { throw new IllegalArgumentException("File invalid - failed to find document entry '" + name + "'"); } @@ -78,7 +78,7 @@ public abstract class HPBFPart { DirectoryNode dir = baseDir; for(int i=0; i= 4) { int size = LittleEndian.getInt(_contents); diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShow.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShow.java index 8fd7a1d40a..9b0d96cdfb 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShow.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShow.java @@ -1047,7 +1047,7 @@ public final class HSLFSlideShow extends POIDocument implements SlideShow olemap = getOleMap(); ClassID classID = null; for (Map.Entry entry : olemap.entrySet()) { - if (root.hasEntry(entry.getKey())) { + if (root.hasEntryCaseInsensitive(entry.getKey())) { classID = entry.getValue(); break; } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java index 9f55214ee5..53bf44300b 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java @@ -197,10 +197,10 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable { private static DirectoryNode handleDualStorage(DirectoryNode dir) throws IOException { // when there's a dual storage entry, use it, as the outer document can't be read quite probably ... - if (!dir.hasEntry(PP97_DOCUMENT)) { + if (!dir.hasEntryCaseInsensitive(PP97_DOCUMENT)) { return dir; } - return (DirectoryNode) dir.getEntry(PP97_DOCUMENT); + return (DirectoryNode) dir.getEntryCaseInsensitive(PP97_DOCUMENT); } /** @@ -226,12 +226,12 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable { private void readPowerPointStream() throws IOException { final DirectoryNode dir = getDirectory(); - if (!dir.hasEntry(POWERPOINT_DOCUMENT) && dir.hasEntry(PP95_DOCUMENT)) { + if (!dir.hasEntryCaseInsensitive(POWERPOINT_DOCUMENT) && dir.hasEntryCaseInsensitive(PP95_DOCUMENT)) { throw new OldPowerPointFormatException("You seem to have supplied a PowerPoint95 file, which isn't supported"); } // Get the main document stream - final Entry entry = dir.getEntry(POWERPOINT_DOCUMENT); + final Entry entry = dir.getEntryCaseInsensitive(POWERPOINT_DOCUMENT); if (!(entry instanceof DocumentEntry)) { throw new IllegalArgumentException("Had unexpected type of entry for name: " + POWERPOINT_DOCUMENT + ": " + entry.getClass()); } @@ -399,12 +399,12 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable { private void readPictures() throws IOException { // if the presentation doesn't contain pictures, will use an empty collection instead - if (!getDirectory().hasEntry("Pictures")) { + if (!getDirectory().hasEntryCaseInsensitive("Pictures")) { _pictures = new ArrayList<>(); return; } - final Entry en = getDirectory().getEntry("Pictures"); + final Entry en = getDirectory().getEntryCaseInsensitive("Pictures"); if (!(en instanceof DocumentEntry)) { throw new IllegalArgumentException("Had unexpected type of entry for name: Pictures: " + en.getClass()); } diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/HWPFDocument.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/HWPFDocument.java index 53c37ffe8f..12577ea186 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/HWPFDocument.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/HWPFDocument.java @@ -261,7 +261,7 @@ public final class HWPFDocument extends HWPFDocumentCore { String name = (_fib.getFibBase().isFWhichTblStm()) ? STREAM_TABLE_1 : STREAM_TABLE_0; // Grab the table stream. - if (!directory.hasEntry(name)) { + if (!directory.hasEntryCaseInsensitive(name)) { throw new IllegalStateException("Table Stream '" + name + "' wasn't found - Either the document is corrupt, or is Word95 (or earlier)"); } @@ -271,7 +271,7 @@ public final class HWPFDocument extends HWPFDocumentCore { _fib.fillVariableFields(_mainStream, _tableStream); // read in the data stream. - _dataStream = directory.hasEntry(STREAM_DATA) ? getDocumentEntryBytes(STREAM_DATA, 0, Integer.MAX_VALUE) : new byte[0]; + _dataStream = directory.hasEntryCaseInsensitive(STREAM_DATA) ? getDocumentEntryBytes(STREAM_DATA, 0, Integer.MAX_VALUE) : new byte[0]; // Get the cp of the start of text in the main stream // The latest spec doc says this is always zero! @@ -1033,4 +1033,4 @@ public final class HWPFDocument extends HWPFDocumentCore { Range r = new Range(start, start + length, this); r.delete(); } -} \ No newline at end of file +} diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/HWPFDocumentCore.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/HWPFDocumentCore.java index 22bf28eab7..86f9956824 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/HWPFDocumentCore.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/HWPFDocumentCore.java @@ -185,8 +185,8 @@ public abstract class HWPFDocumentCore extends POIDocument { _fib = new FileInformationBlock(_mainStream); DirectoryEntry objectPoolEntry = null; - if (directory.hasEntry(STREAM_OBJECT_POOL)) { - final Entry entry = directory.getEntry(STREAM_OBJECT_POOL); + if (directory.hasEntryCaseInsensitive(STREAM_OBJECT_POOL)) { + final Entry entry = directory.getEntryCaseInsensitive(STREAM_OBJECT_POOL); if (!(entry instanceof DirectoryEntry)) { throw new IllegalArgumentException("Had unexpected type of entry for name: " + STREAM_OBJECT_POOL + ": " + entry.getClass()); } @@ -341,7 +341,7 @@ public abstract class HWPFDocumentCore extends POIDocument { */ protected byte[] getDocumentEntryBytes(String name, int encryptionOffset, final int len) throws IOException { DirectoryNode dir = getDirectory(); - final Entry entry = dir.getEntry(name); + final Entry entry = dir.getEntryCaseInsensitive(name); if (!(entry instanceof DocumentEntry)) { throw new IllegalArgumentException("Had unexpected type of entry for name: " + name + ": " + entry); } @@ -368,4 +368,4 @@ public abstract class HWPFDocumentCore extends POIDocument { } return new SequenceInputStream(new ByteArrayInputStream(plain), cis); } -} \ No newline at end of file +} diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/WordToTextConverter.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/WordToTextConverter.java index 915abe819a..58f529a3c9 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/WordToTextConverter.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/converter/WordToTextConverter.java @@ -332,7 +332,7 @@ public class WordToTextConverter extends AbstractWordConverter { * even if there is no ExtractorFactory in classpath, still support * included Word's objects */ - if ( directoryNode.hasEntry( "WordDocument" ) ) + if ( directoryNode.hasEntryCaseInsensitive( "WordDocument" ) ) { String text = WordToTextConverter.getText( (DirectoryNode) entry ); block.appendChild( textDocumentFacade diff --git a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/usermodel/ObjectPoolImpl.java b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/usermodel/ObjectPoolImpl.java index c672134ec4..644814d340 100644 --- a/poi-scratchpad/src/main/java/org/apache/poi/hwpf/usermodel/ObjectPoolImpl.java +++ b/poi-scratchpad/src/main/java/org/apache/poi/hwpf/usermodel/ObjectPoolImpl.java @@ -42,7 +42,7 @@ public class ObjectPoolImpl implements ObjectsPool try { - return _objectPool.getEntry( objId ); + return _objectPool.getEntryCaseInsensitive( objId ); } catch ( FileNotFoundException exc ) { diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/TestReWrite.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/TestReWrite.java index 48e2666aa1..0606c28950 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/TestReWrite.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/TestReWrite.java @@ -92,20 +92,20 @@ public final class TestReWrite { assertSlideShowWritesOutTheSame(hssC, pfsC); // Currently has a Macros stream - assertNotNull(pfsC.getRoot().getEntry("Macros")); + assertNotNull(pfsC.getRoot().getEntryCaseInsensitive("Macros")); // Write out normally, will loose the macro stream UnsynchronizedByteArrayOutputStream baos = UnsynchronizedByteArrayOutputStream.builder().get(); hssC.write(baos); try (POIFSFileSystem pfsNew = new POIFSFileSystem(baos.toInputStream())) { - assertFalse(pfsNew.getRoot().hasEntry("Macros")); + assertFalse(pfsNew.getRoot().hasEntryCaseInsensitive("Macros")); } // But if we write out with nodes preserved, will be there baos.reset(); hssC.write(baos, true); try (POIFSFileSystem pfsNew = new POIFSFileSystem(baos.toInputStream())) { - assertTrue(pfsNew.getRoot().hasEntry("Macros")); + assertTrue(pfsNew.getRoot().hasEntryCaseInsensitive("Macros")); } } } @@ -145,8 +145,8 @@ public final class TestReWrite { private void assertSame(POIFSFileSystem origPFS, POIFSFileSystem newPFS) throws IOException { // Check that the "PowerPoint Document" sections have the same size - DocumentEntry oProps = (DocumentEntry) origPFS.getRoot().getEntry(POWERPOINT_DOCUMENT); - DocumentEntry nProps = (DocumentEntry) newPFS.getRoot().getEntry(POWERPOINT_DOCUMENT); + DocumentEntry oProps = (DocumentEntry) origPFS.getRoot().getEntryCaseInsensitive(POWERPOINT_DOCUMENT); + DocumentEntry nProps = (DocumentEntry) newPFS.getRoot().getEntryCaseInsensitive(POWERPOINT_DOCUMENT); assertEquals(oProps.getSize(), nProps.getSize()); diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/extractor/TestExtractor.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/extractor/TestExtractor.java index 6b8a08ff2d..4d70257650 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/extractor/TestExtractor.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/extractor/TestExtractor.java @@ -185,8 +185,8 @@ public final class TestExtractor { }; for (int i=0; i ppt = SlideShowFactory.create(dir); final SlideShowExtractor ppe = new SlideShowExtractor<>(ppt)) { diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/model/TestTextRunReWrite.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/model/TestTextRunReWrite.java index b38ae3ba51..658e2df370 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/model/TestTextRunReWrite.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/model/TestTextRunReWrite.java @@ -79,8 +79,8 @@ public final class TestTextRunReWrite { // Check that the "PowerPoint Document" sections have the same size DirectoryNode oDir = ppt1.getSlideShowImpl().getDirectory(); - DocumentEntry oProps = (DocumentEntry) oDir.getEntry(HSLFSlideShow.POWERPOINT_DOCUMENT); - DocumentEntry nProps = (DocumentEntry) npfs.getRoot().getEntry(HSLFSlideShow.POWERPOINT_DOCUMENT); + DocumentEntry oProps = (DocumentEntry) oDir.getEntryCaseInsensitive(HSLFSlideShow.POWERPOINT_DOCUMENT); + DocumentEntry nProps = (DocumentEntry) npfs.getRoot().getEntryCaseInsensitive(HSLFSlideShow.POWERPOINT_DOCUMENT); assertEquals(oProps.getSize(), nProps.getSize()); // Check that they contain the same data @@ -130,8 +130,8 @@ public final class TestTextRunReWrite { // Check that the "PowerPoint Document" sections have the same size DirectoryNode oDir = ppt1.getSlideShowImpl().getDirectory(); - DocumentEntry oProps = (DocumentEntry) oDir.getEntry(HSLFSlideShow.POWERPOINT_DOCUMENT); - DocumentEntry nProps = (DocumentEntry) npfs.getRoot().getEntry(HSLFSlideShow.POWERPOINT_DOCUMENT); + DocumentEntry oProps = (DocumentEntry) oDir.getEntryCaseInsensitive(HSLFSlideShow.POWERPOINT_DOCUMENT); + DocumentEntry nProps = (DocumentEntry) npfs.getRoot().getEntryCaseInsensitive(HSLFSlideShow.POWERPOINT_DOCUMENT); assertEquals(oProps.getSize(), nProps.getSize()); // Check that they contain the same data diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestCurrentUserAtom.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestCurrentUserAtom.java index a1ee955fd3..780e36500a 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestCurrentUserAtom.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestCurrentUserAtom.java @@ -76,7 +76,7 @@ public final class TestCurrentUserAtom { // Get raw contents from a known file byte[] contents; try (POIFSFileSystem fs = new POIFSFileSystem(_slTests.getFile(normalFile))) { - DocumentEntry docProps = (DocumentEntry) fs.getRoot().getEntry("Current User"); + DocumentEntry docProps = (DocumentEntry) fs.getRoot().getEntryCaseInsensitive("Current User"); contents = new byte[docProps.getSize()]; try (InputStream in = fs.getRoot().createDocumentInputStream("Current User")) { in.read(contents); diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExOleObjStg.java b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExOleObjStg.java index 46d607e729..8563bf7c5e 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExOleObjStg.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hslf/record/TestExOleObjStg.java @@ -62,7 +62,7 @@ public final class TestExOleObjStg { assertEquals(len, oledata.length); try (POIFSFileSystem fs = new POIFSFileSystem(record.getData())) { - DocumentEntry doc = (DocumentEntry) fs.getRoot().getEntry("Contents"); + DocumentEntry doc = (DocumentEntry) fs.getRoot().getEntryCaseInsensitive("Contents"); assertNotNull(doc); } } diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hsmf/parsers/TestPOIFSChunkParser.java b/poi-scratchpad/src/test/java/org/apache/poi/hsmf/parsers/TestPOIFSChunkParser.java index f93ff19f0f..17d58effea 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hsmf/parsers/TestPOIFSChunkParser.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hsmf/parsers/TestPOIFSChunkParser.java @@ -56,13 +56,13 @@ public final class TestPOIFSChunkParser { void testFindsCore() throws IOException, ChunkNotFoundException { try (POIFSFileSystem simple = new POIFSFileSystem(samples.getFile("quick.msg"), true)) { - // Check a few core things are present - simple.getRoot().getEntry( - (new StringChunk(MAPIProperty.SUBJECT.id, Types.ASCII_STRING)).getEntryName() - ); - simple.getRoot().getEntry( - (new StringChunk(MAPIProperty.SENDER_NAME.id, Types.ASCII_STRING)).getEntryName() - ); + // Check a few core things are present + simple.getRoot().getEntryCaseInsensitive( + (new StringChunk(MAPIProperty.SUBJECT.id, Types.ASCII_STRING)).getEntryName() + ); + simple.getRoot().getEntryCaseInsensitive( + (new StringChunk(MAPIProperty.SENDER_NAME.id, Types.ASCII_STRING)).getEntryName() + ); // Now load the file try (MAPIMessage msg = new MAPIMessage(simple)) { @@ -82,7 +82,7 @@ public final class TestPOIFSChunkParser { void testFindsRecips() throws IOException, ChunkNotFoundException { try (POIFSFileSystem simple = new POIFSFileSystem(samples.getFile("quick.msg"), true)) { - simple.getRoot().getEntry("__recip_version1.0_#00000000"); + simple.getRoot().getEntryCaseInsensitive("__recip_version1.0_#00000000"); ChunkGroup[] groups = POIFSChunkParser.parse(simple.getRoot()); assertEquals(3, groups.length); @@ -136,12 +136,12 @@ public final class TestPOIFSChunkParser { void testFindsMultipleRecipients() throws IOException, ChunkNotFoundException { try (POIFSFileSystem multiple = new POIFSFileSystem(samples.getFile("example_received_unicode.msg"), true)) { - multiple.getRoot().getEntry("__recip_version1.0_#00000000"); - multiple.getRoot().getEntry("__recip_version1.0_#00000001"); - multiple.getRoot().getEntry("__recip_version1.0_#00000002"); - multiple.getRoot().getEntry("__recip_version1.0_#00000003"); - multiple.getRoot().getEntry("__recip_version1.0_#00000004"); - multiple.getRoot().getEntry("__recip_version1.0_#00000005"); + multiple.getRoot().getEntryCaseInsensitive("__recip_version1.0_#00000000"); + multiple.getRoot().getEntryCaseInsensitive("__recip_version1.0_#00000001"); + multiple.getRoot().getEntryCaseInsensitive("__recip_version1.0_#00000002"); + multiple.getRoot().getEntryCaseInsensitive("__recip_version1.0_#00000003"); + multiple.getRoot().getEntryCaseInsensitive("__recip_version1.0_#00000004"); + multiple.getRoot().getEntryCaseInsensitive("__recip_version1.0_#00000005"); ChunkGroup[] groups = POIFSChunkParser.parse(multiple.getRoot()); assertEquals(9, groups.length); @@ -228,7 +228,7 @@ public final class TestPOIFSChunkParser { void testFindsNameId() throws IOException { try (POIFSFileSystem simple = new POIFSFileSystem(samples.getFile("quick.msg"), true)) { - simple.getRoot().getEntry("__nameid_version1.0"); + simple.getRoot().getEntryCaseInsensitive("__nameid_version1.0"); ChunkGroup[] groups = POIFSChunkParser.parse(simple.getRoot()); assertEquals(3, groups.length); @@ -253,10 +253,11 @@ public final class TestPOIFSChunkParser { POIFSFileSystem without = new POIFSFileSystem(samples.getFile("quick.msg"), true)) { AttachmentChunks attachment; - // Check raw details on the one with - with.getRoot().getEntry("__attach_version1.0_#00000000"); - with.getRoot().getEntry("__attach_version1.0_#00000001"); - POIFSChunkParser.parse(with.getRoot()); + + // Check raw details on the one with + with.getRoot().getEntryCaseInsensitive("__attach_version1.0_#00000000"); + with.getRoot().getEntryCaseInsensitive("__attach_version1.0_#00000001"); + POIFSChunkParser.parse(with.getRoot()); ChunkGroup[] groups = POIFSChunkParser.parse(with.getRoot()); assertEquals(5, groups.length); @@ -276,9 +277,10 @@ public final class TestPOIFSChunkParser { assertEquals("pj1.txt", attachment.getAttachLongFileName().toString()); assertEquals(89, attachment.getAttachData().getValue().length); - // Check raw details on one without - assertFalse(without.getRoot().hasEntry("__attach_version1.0_#00000000")); - assertFalse(without.getRoot().hasEntry("__attach_version1.0_#00000001")); + + // Check raw details on one without + assertFalse(without.getRoot().hasEntryCaseInsensitive("__attach_version1.0_#00000000")); + assertFalse(without.getRoot().hasEntryCaseInsensitive("__attach_version1.0_#00000001")); // One with, from the top try (MAPIMessage msgWith = new MAPIMessage(with)) { diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/HWPFDocFixture.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/HWPFDocFixture.java index ea2a93cc12..54052acc58 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/HWPFDocFixture.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/HWPFDocFixture.java @@ -44,7 +44,7 @@ public final class HWPFDocFixture POIDataSamples.getDocumentInstance().openResourceAsStream(_testFile)); DocumentEntry documentProps = - (DocumentEntry) filesystem.getRoot().getEntry("WordDocument"); + (DocumentEntry) filesystem.getRoot().getEntryCaseInsensitive("WordDocument"); _mainStream = new byte[documentProps.getSize()]; filesystem.createDocumentInputStream("WordDocument").read(_mainStream); @@ -59,7 +59,7 @@ public final class HWPFDocFixture // read in the table stream. DocumentEntry tableProps = - (DocumentEntry) filesystem.getRoot().getEntry(name); + (DocumentEntry) filesystem.getRoot().getEntryCaseInsensitive(name); _tableStream = new byte[tableProps.getSize()]; filesystem.createDocumentInputStream(name).read(_tableStream); diff --git a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/extractor/TestWordExtractor.java b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/extractor/TestWordExtractor.java index 4ef67c44c8..a53fefd7fe 100644 --- a/poi-scratchpad/src/test/java/org/apache/poi/hwpf/extractor/TestWordExtractor.java +++ b/poi-scratchpad/src/test/java/org/apache/poi/hwpf/extractor/TestWordExtractor.java @@ -142,15 +142,15 @@ public final class TestWordExtractor { POIFSFileSystem fs = new POIFSFileSystem(is); is.close(); - DirectoryNode dirA = (DirectoryNode) fs.getRoot().getEntry("MBD0000A3B7"); - DirectoryNode dirB = (DirectoryNode) fs.getRoot().getEntry("MBD0000A3B2"); + DirectoryNode dirA = (DirectoryNode) fs.getRoot().getEntryCaseInsensitive("MBD0000A3B7"); + DirectoryNode dirB = (DirectoryNode) fs.getRoot().getEntryCaseInsensitive("MBD0000A3B2"); // Should have WordDocument and 1Table - assertNotNull(dirA.getEntry("1Table")); - assertNotNull(dirA.getEntry("WordDocument")); + assertNotNull(dirA.getEntryCaseInsensitive("1Table")); + assertNotNull(dirA.getEntryCaseInsensitive("WordDocument")); - assertNotNull(dirB.getEntry("1Table")); - assertNotNull(dirB.getEntry("WordDocument")); + assertNotNull(dirB.getEntryCaseInsensitive("1Table")); + assertNotNull(dirB.getEntryCaseInsensitive("WordDocument")); // Check each in turn HWPFDocument docA = new HWPFDocument(dirA); @@ -402,6 +402,18 @@ public final class TestWordExtractor { } } + @Test + public void testCaseInsensitiveOLENames() throws Exception { + //test files are from Ross Johnson on TIKA-4091 + for (String n : new String[]{"normal", "lower", "upper"}) { + try (InputStream is = docTests.openResourceAsStream("47950_" + n + ".doc"); + POIFSFileSystem fs = new POIFSFileSystem(is); + WordExtractor wExt = new WordExtractor(fs)) { + assertContains(wExt.getText(), "This is a sample Word document"); + } + } + } + @Test void testCapitalized() throws Exception { try (WordExtractor wExt = openExtractor("capitalized.doc")) { diff --git a/poi/src/main/java/org/apache/poi/POIDocument.java b/poi/src/main/java/org/apache/poi/POIDocument.java index c7e4536b3b..ab312bccd3 100644 --- a/poi/src/main/java/org/apache/poi/POIDocument.java +++ b/poi/src/main/java/org/apache/poi/POIDocument.java @@ -222,7 +222,7 @@ public abstract class POIDocument implements Closeable { if (encryptionInfo != null && encryptionInfo.isDocPropsEncrypted()) { step = "getting encrypted"; String encryptedStream = getEncryptedPropertyStreamName(); - if (!dirNode.hasEntry(encryptedStream)) { + if (!dirNode.hasEntryCaseInsensitive(encryptedStream)) { throw new EncryptedDocumentException("can't find encrypted property stream '"+encryptedStream+"'"); } CryptoAPIDecryptor dec = (CryptoAPIDecryptor)encryptionInfo.getDecryptor(); @@ -231,13 +231,13 @@ public abstract class POIDocument implements Closeable { } //directory can be null when creating new documents - if (dirNode == null || !dirNode.hasEntry(setName)) { + if (dirNode == null || !dirNode.hasEntryCaseInsensitive(setName)) { return null; } // Find the entry, and get an input stream for it step = "getting"; - try (DocumentInputStream dis = dirNode.createDocumentInputStream(dirNode.getEntry(setName))) { + try (DocumentInputStream dis = dirNode.createDocumentInputStream(dirNode.getEntryCaseInsensitive(setName))) { // Create the Property Set step = "creating"; return PropertySetFactory.create(dis); @@ -302,8 +302,8 @@ public abstract class POIDocument implements Closeable { writePropertySet(DocumentSummaryInformation.DEFAULT_STREAM_NAME, newDocumentSummaryInformation(), outFS); // remove summary, if previously available - if (outFS.getRoot().hasEntry(SummaryInformation.DEFAULT_STREAM_NAME)) { - outFS.getRoot().getEntry(SummaryInformation.DEFAULT_STREAM_NAME).delete(); + if (outFS.getRoot().hasEntryCaseInsensitive(SummaryInformation.DEFAULT_STREAM_NAME)) { + outFS.getRoot().getEntryCaseInsensitive(SummaryInformation.DEFAULT_STREAM_NAME).delete(); } CryptoAPIEncryptor enc = (CryptoAPIEncryptor) encGen; try { diff --git a/poi/src/main/java/org/apache/poi/extractor/ExtractorFactory.java b/poi/src/main/java/org/apache/poi/extractor/ExtractorFactory.java index b3c6ef0514..21e61e572a 100644 --- a/poi/src/main/java/org/apache/poi/extractor/ExtractorFactory.java +++ b/poi/src/main/java/org/apache/poi/extractor/ExtractorFactory.java @@ -222,7 +222,7 @@ public final class ExtractorFactory { POIFSFileSystem poifs = new POIFSFileSystem(is); DirectoryNode root = poifs.getRoot(); - boolean isOOXML = root.hasEntry(DEFAULT_POIFS_ENTRY) || root.hasEntry(OOXML_PACKAGE); + boolean isOOXML = root.hasEntryCaseInsensitive(DEFAULT_POIFS_ENTRY) || root.hasEntryCaseInsensitive(OOXML_PACKAGE); return wp(isOOXML ? FileMagic.OOXML : fm, w -> w.create(root, password)); } @@ -267,7 +267,7 @@ public final class ExtractorFactory { try { poifs = new POIFSFileSystem(file, true); DirectoryNode root = poifs.getRoot(); - boolean isOOXML = root.hasEntry(DEFAULT_POIFS_ENTRY) || root.hasEntry(OOXML_PACKAGE); + boolean isOOXML = root.hasEntryCaseInsensitive(DEFAULT_POIFS_ENTRY) || root.hasEntryCaseInsensitive(OOXML_PACKAGE); return wp(isOOXML ? FileMagic.OOXML : fm, w -> w.create(root, password)); } catch (IOException | RuntimeException e) { IOUtils.closeQuietly(poifs); @@ -313,7 +313,7 @@ public final class ExtractorFactory { */ public static POITextExtractor createExtractor(final DirectoryNode root, String password) throws IOException { // Encrypted OOXML files go inside OLE2 containers, is this one? - if (root.hasEntry(DEFAULT_POIFS_ENTRY) || root.hasEntry(OOXML_PACKAGE)) { + if (root.hasEntryCaseInsensitive(DEFAULT_POIFS_ENTRY) || root.hasEntryCaseInsensitive(OOXML_PACKAGE)) { return wp(FileMagic.OOXML, w -> w.create(root, password)); } else { return wp(FileMagic.OLE2, w -> w.create(root, password)); 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 89815bfd9e..eba21972d9 100644 --- a/poi/src/main/java/org/apache/poi/extractor/MainExtractorFactory.java +++ b/poi/src/main/java/org/apache/poi/extractor/MainExtractorFactory.java @@ -17,7 +17,7 @@ package org.apache.poi.extractor; -import static org.apache.poi.hssf.model.InternalWorkbook.WORKBOOK_DIR_ENTRY_NAMES; +import static org.apache.poi.hssf.model.InternalWorkbook.WORKBOOK_DIR_ENTRY_NAMES_CASE_INSENSITIVE; import java.io.File; import java.io.IOException; @@ -59,16 +59,17 @@ public class MainExtractorFactory implements ExtractorProvider { try { Biff8EncryptionKey.setCurrentUserPassword(password); + if (poifsDir.hasEntry(InternalWorkbook.OLD_WORKBOOK_DIR_ENTRY_NAME)) { + return new OldExcelExtractor(poifsDir); + } + // Look for certain entries in the stream, to figure it out from - for (String workbookName : WORKBOOK_DIR_ENTRY_NAMES) { - if (poifsDir.hasEntry(workbookName)) { + for (String workbookName : WORKBOOK_DIR_ENTRY_NAMES_CASE_INSENSITIVE) { + if (poifsDir.hasEntryCaseInsensitive(workbookName)) { return ExtractorFactory.getPreferEventExtractor() ? new EventBasedExcelExtractor(poifsDir) : new ExcelExtractor(poifsDir); } } - if (poifsDir.hasEntry(InternalWorkbook.OLD_WORKBOOK_DIR_ENTRY_NAME)) { - return new OldExcelExtractor(poifsDir); - } } finally { Biff8EncryptionKey.setCurrentUserPassword(oldPW); } diff --git a/poi/src/main/java/org/apache/poi/hpsf/PropertySet.java b/poi/src/main/java/org/apache/poi/hpsf/PropertySet.java index 5bd4cd6b44..39d259d14a 100644 --- a/poi/src/main/java/org/apache/poi/hpsf/PropertySet.java +++ b/poi/src/main/java/org/apache/poi/hpsf/PropertySet.java @@ -575,8 +575,8 @@ public class PropertySet { public void write(final DirectoryEntry dir, final String name) throws WritingNotSupportedException, IOException { /* If there is already an entry with the same name, remove it. */ - if (dir.hasEntry(name)) { - final Entry e = dir.getEntry(name); + if (dir.hasEntryCaseInsensitive(name)) { + final Entry e = dir.getEntryCaseInsensitive(name); e.delete(); } diff --git a/poi/src/main/java/org/apache/poi/hssf/eventusermodel/HSSFEventFactory.java b/poi/src/main/java/org/apache/poi/hssf/eventusermodel/HSSFEventFactory.java index dafa88c1cd..309c3a5e8f 100644 --- a/poi/src/main/java/org/apache/poi/hssf/eventusermodel/HSSFEventFactory.java +++ b/poi/src/main/java/org/apache/poi/hssf/eventusermodel/HSSFEventFactory.java @@ -24,6 +24,9 @@ import java.util.Set; import org.apache.poi.hssf.record.*; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.POIFSFileSystem; + +import static org.apache.poi.hssf.model.InternalWorkbook.BOOK; +import static org.apache.poi.hssf.model.InternalWorkbook.WORKBOOK; import static org.apache.poi.hssf.model.InternalWorkbook.WORKBOOK_DIR_ENTRY_NAMES; /** @@ -64,13 +67,12 @@ public class HSSFEventFactory { public void processWorkbookEvents(HSSFRequest req, DirectoryNode dir) throws IOException { // some old documents have "WORKBOOK" or "BOOK" String name = null; - Set entryNames = dir.getEntryNames(); - for (String potentialName : WORKBOOK_DIR_ENTRY_NAMES) { - if (entryNames.contains(potentialName)) { - name = potentialName; - break; - } + if (dir.hasEntry(WORKBOOK)) { + name = WORKBOOK; + } else if (dir.hasEntry(BOOK)) { + name = BOOK; } + // If in doubt, go for the default if (name == null) { name = WORKBOOK_DIR_ENTRY_NAMES.get(0); diff --git a/poi/src/main/java/org/apache/poi/hssf/extractor/OldExcelExtractor.java b/poi/src/main/java/org/apache/poi/hssf/extractor/OldExcelExtractor.java index 80b715a59b..1db03f80bc 100644 --- a/poi/src/main/java/org/apache/poi/hssf/extractor/OldExcelExtractor.java +++ b/poi/src/main/java/org/apache/poi/hssf/extractor/OldExcelExtractor.java @@ -18,6 +18,7 @@ package org.apache.poi.hssf.extractor; import static org.apache.poi.hssf.model.InternalWorkbook.OLD_WORKBOOK_DIR_ENTRY_NAME; +import static org.apache.poi.hssf.model.InternalWorkbook.WORKBOOK; import static org.apache.poi.hssf.model.InternalWorkbook.WORKBOOK_DIR_ENTRY_NAMES; import java.io.BufferedInputStream; @@ -150,14 +151,14 @@ public class OldExcelExtractor implements POITextExtractor { private void open(DirectoryNode directory) throws IOException { DocumentNode book; try { - Entry entry = directory.getEntry(OLD_WORKBOOK_DIR_ENTRY_NAME); + Entry entry = directory.getEntryCaseInsensitive(OLD_WORKBOOK_DIR_ENTRY_NAME); if (!(entry instanceof DocumentNode)) { throw new IllegalArgumentException("Did not have an Excel 5/95 Book stream: " + entry); } book = (DocumentNode) entry; } catch (FileNotFoundException | IllegalArgumentException e) { // some files have "Workbook" instead - Entry entry = directory.getEntry(WORKBOOK_DIR_ENTRY_NAMES.get(0)); + Entry entry = directory.getEntryCaseInsensitive(WORKBOOK); if (!(entry instanceof DocumentNode)) { throw new IllegalArgumentException("Did not have an Excel 5/95 Book stream: " + entry); } diff --git a/poi/src/main/java/org/apache/poi/hssf/model/InternalWorkbook.java b/poi/src/main/java/org/apache/poi/hssf/model/InternalWorkbook.java index 39ea0530a4..acd3541cf7 100644 --- a/poi/src/main/java/org/apache/poi/hssf/model/InternalWorkbook.java +++ b/poi/src/main/java/org/apache/poi/hssf/model/InternalWorkbook.java @@ -87,7 +87,7 @@ public final class InternalWorkbook { /** * Normally, the Workbook will be in a POIFS Stream called * "Workbook". However, some weird XLS generators use "WORKBOOK" - * or "BOOK". + * or "BOOK". This includes common case sensitive variations. */ public static final List WORKBOOK_DIR_ENTRY_NAMES = Collections.unmodifiableList( Arrays.asList( @@ -98,6 +98,19 @@ public final class InternalWorkbook { ) ); + /** + * Crystal exports may use this for a regular .xls file. This + * needs to be distinguished case sensitively from {@link #OLD_WORKBOOK_DIR_ENTRY_NAME}. + */ + public static final String BOOK = "BOOK"; + + public static final String WORKBOOK = "WORKBOOK"; + + public static final List WORKBOOK_DIR_ENTRY_NAMES_CASE_INSENSITIVE = + Collections.unmodifiableList( + Arrays.asList(WORKBOOK, BOOK) + ); + /** * Name of older (pre-Excel 97) Workbook streams, which * aren't supported by HSSFWorkbook, only by diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java index 27ea1deebe..5c1bdee1ef 100644 --- a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java +++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java @@ -19,7 +19,6 @@ package org.apache.poi.hssf.usermodel; import java.io.IOException; -import java.util.Iterator; import org.apache.poi.ddf.*; import org.apache.poi.hssf.record.*; @@ -56,7 +55,7 @@ public final class HSSFObjectData extends HSSFPicture implements ObjectData { int streamId = subRecord.getStreamId().intValue(); String streamName = "MBD" + HexDump.toHex(streamId); - Entry entry = _root.getEntry(streamName); + Entry entry = _root.getEntryCaseInsensitive(streamName); if (entry instanceof DirectoryEntry) { return (DirectoryEntry) entry; } diff --git a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java index 716e215bbc..dc64f10f5e 100644 --- a/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java +++ b/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java @@ -290,7 +290,7 @@ public final class HSSFPatriarch implements HSSFShapeContainer, Drawing olemap = getOleMap(); for (Map.Entry entry : olemap.entrySet()) { - if (root.hasEntry(entry.getKey())) { + if (root.hasEntryCaseInsensitive(entry.getKey())) { root.setStorageClsid(entry.getValue()); break; } @@ -2129,7 +2135,7 @@ public final class HSSFWorkbook extends POIDocument implements Workbook { DirectoryEntry oleDir = null; do { String storageStr = "MBD" + HexDump.toHex(++storageId); - if (!getDirectory().hasEntry(storageStr)) { + if (!getDirectory().hasEntryCaseInsensitive(storageStr)) { oleDir = getDirectory().createDirectory(storageStr); oleDir.setStorageClsid(ClassIDPredefined.OLE_V1_PACKAGE.getClassID()); } diff --git a/poi/src/main/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java b/poi/src/main/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java index a904214121..bcbebd7ed6 100644 --- a/poi/src/main/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java +++ b/poi/src/main/java/org/apache/poi/poifs/crypt/DataSpaceMapUtils.java @@ -61,8 +61,8 @@ public class DataSpaceMapUtils { public static DocumentEntry createEncryptionEntry(DirectoryEntry dir, String path, EncryptionRecord out) throws IOException { String[] parts = path.split("/"); for (int i=0; i { diff --git a/poi/src/main/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java b/poi/src/main/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java index 3698c57b7e..ed0cf12372 100644 --- a/poi/src/main/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java +++ b/poi/src/main/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIDecryptor.java @@ -173,9 +173,9 @@ public class CryptoAPIDecryptor extends Decryptor { throws IOException, GeneralSecurityException { POIFSFileSystem fsOut = null; try ( - DocumentInputStream dis = root.createDocumentInputStream(root.getEntry(encryptedStream)); - CryptoAPIDocumentInputStream sbis = new CryptoAPIDocumentInputStream(this, IOUtils.toByteArray(dis)); - LittleEndianInputStream leis = new LittleEndianInputStream(sbis) + DocumentInputStream dis = root.createDocumentInputStream(root.getEntryCaseInsensitive(encryptedStream)); + CryptoAPIDocumentInputStream sbis = new CryptoAPIDocumentInputStream(this, IOUtils.toByteArray(dis)); + LittleEndianInputStream leis = new LittleEndianInputStream(sbis) ) { int streamDescriptorArrayOffset = (int) leis.readUInt(); /* int streamDescriptorArraySize = (int) */ leis.readUInt(); diff --git a/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryEntry.java b/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryEntry.java index 2c99782af9..2ede110ec5 100644 --- a/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryEntry.java +++ b/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryEntry.java @@ -76,14 +76,20 @@ public interface DirectoryEntry extends Entry, Iterable { int getEntryCount(); - /** - * Checks if entry with specified name present - */ + /** + * Checks if entry with specified name present, case sensitive + */ boolean hasEntry( final String name ); /** - * get a specified Entry by name + * Checks if entry with specified name present, case sensitive + */ + + boolean hasEntryCaseInsensitive(final String name ); + + /** + * get a specified Entry by name, case sensitive * * @param name the name of the Entry to obtain. * @@ -96,6 +102,20 @@ public interface DirectoryEntry extends Entry, Iterable { Entry getEntry(final String name) throws FileNotFoundException; + /** + * get a specified Entry by name, case insensitive + * + * @param name the name of the Entry to obtain. + * + * @return the specified Entry, if it is directly contained in + * this DirectoryEntry + * + * @throws FileNotFoundException if no Entry with the specified + * name exists in this DirectoryEntry + */ + + Entry getEntryCaseInsensitive(final String name) throws FileNotFoundException; + /** * create a new DocumentEntry * diff --git a/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryNode.java b/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryNode.java index 54fab5f498..6e7f7508d0 100644 --- a/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryNode.java +++ b/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryNode.java @@ -23,9 +23,12 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.Spliterator; @@ -40,13 +43,16 @@ import org.apache.poi.poifs.property.Property; * Simple implementation of DirectoryEntry */ public class DirectoryNode - extends EntryNode - implements DirectoryEntry, POIFSViewable, Iterable + extends EntryNode + implements DirectoryEntry, POIFSViewable, Iterable { - // Map of Entry instances, keyed by their names + // Map of Entry instances, keyed by their literal names as stored private final Map _byname = new HashMap<>(); + // Map of Entry instances, keyed by their Uppercased names + private final Map _byUCName = new HashMap<>(); + // Our list of entries, kept sorted to preserve order private final ArrayList _entries = new ArrayList<>(); @@ -100,6 +106,7 @@ public class DirectoryNode } _entries.add(childNode); _byname.put(childNode.getName(), childNode); + _byUCName.put(childNode.getName().toUpperCase(Locale.ROOT), childNode); } } @@ -132,9 +139,9 @@ public class DirectoryNode */ public DocumentInputStream createDocumentInputStream( final String documentName) - throws IOException + throws IOException { - return createDocumentInputStream(getEntry(documentName)); + return createDocumentInputStream(getEntryCaseInsensitive(documentName)); } /** @@ -149,11 +156,11 @@ public class DirectoryNode */ public DocumentInputStream createDocumentInputStream( final Entry document) - throws IOException + throws IOException { if (!document.isDocumentEntry()) { throw new IOException("Entry '" + document.getName() - + "' is not a DocumentEntry"); + + "' is not a DocumentEntry"); } DocumentEntry entry = (DocumentEntry)document; @@ -170,7 +177,7 @@ public class DirectoryNode * @throws IOException if the document can't be created */ DocumentEntry createDocument(final POIFSDocument document) - throws IOException + throws IOException { DocumentProperty property = document.getDocumentProperty(); DocumentNode rval = new DocumentNode(property, this); @@ -180,6 +187,7 @@ public class DirectoryNode _entries.add(rval); _byname.put(property.getName(), rval); + _byUCName.put(property.getName().toUpperCase(Locale.ROOT), rval); return rval; } @@ -194,16 +202,18 @@ public class DirectoryNode boolean changeName(final String oldName, final String newName) { boolean rval = false; - EntryNode child = ( EntryNode ) _byname.get(oldName); + EntryNode child = ( EntryNode ) _byUCName.get(oldName.toUpperCase(Locale.ROOT)); if (child != null) { rval = (( DirectoryProperty ) getProperty()) - .changeName(child.getProperty(), newName); + .changeName(child.getProperty(), newName); if (rval) { _byname.remove(oldName); _byname.put(child.getProperty().getName(), child); + _byUCName.remove(oldName.toUpperCase(Locale.ROOT)); + _byUCName.put(child.getProperty().getName().toUpperCase(Locale.ROOT), child); } } return rval; @@ -220,13 +230,14 @@ public class DirectoryNode boolean deleteEntry(final EntryNode entry) { boolean rval = - (( DirectoryProperty ) getProperty()) - .deleteChild(entry.getProperty()); + (( DirectoryProperty ) getProperty()) + .deleteChild(entry.getProperty()); if (rval) { _entries.remove(entry); _byname.remove(entry.getName()); + _byUCName.remove(entry.getName().toUpperCase(Locale.ROOT)); try { _filesystem.remove(entry); @@ -258,9 +269,9 @@ public class DirectoryNode } /** - * get the names of all the Entries contained directly in this - * instance (in other words, names of children only; no grandchildren - * etc). + * get the literal, case-sensitive names of all the Entries contained + * directly in this instance (in other words, names of children only; + * no grandchildren etc). * * @return the names of all the entries that may be retrieved with * getEntry(String), which may be empty (if this @@ -298,14 +309,32 @@ public class DirectoryNode return _entries.size(); } + /** + * Checks for a specific entry in a case-sensitive way. + * + * @param name + * @return whether or not an entry exists for that name (case-sensitive) + */ @Override - public boolean hasEntry( String name ) + public boolean hasEntry(String name ) { - return name != null && _byname.containsKey( name ); + return name != null && _byname.containsKey(name); } /** - * get a specified Entry by name + * Checks for a specific entry in a case-insensitive way. + * + * @param name + * @return whether or not an entry exists for that name (case-insensitive) + */ + @Override + public boolean hasEntryCaseInsensitive(String name ) + { + return name != null && _byUCName.containsKey(name.toUpperCase(Locale.ROOT)); + } + + /** + * get a specified Entry by name, case sensitive * * @param name the name of the Entry to obtain. * @@ -315,7 +344,6 @@ public class DirectoryNode * @throws FileNotFoundException if no Entry with the specified * name exists in this DirectoryEntry */ - @Override public Entry getEntry(final String name) throws FileNotFoundException { Entry rval = null; @@ -340,6 +368,41 @@ public class DirectoryNode return rval; } + /** + * get a specified Entry by name, case-insensitive + * + * @param name the name of the Entry to obtain. + * + * @return the specified Entry, if it is directly contained in + * this DirectoryEntry + * + * @throws FileNotFoundException if no Entry with the specified + * name exists in this DirectoryEntry + */ + @Override + public Entry getEntryCaseInsensitive(final String name) throws FileNotFoundException { + Entry rval = null; + + if (name != null) { + rval = _byUCName.get(name.toUpperCase(Locale.ROOT)); + } + if (rval == null) { + // throw more useful exceptions for known wrong file-extensions + if(_byname.containsKey("Workbook")) { + throw new IllegalArgumentException("The document is really a XLS file"); + } else if(_byname.containsKey("PowerPoint Document")) { + throw new IllegalArgumentException("The document is really a PPT file"); + } else if(_byname.containsKey("VisioDocument")) { + throw new IllegalArgumentException("The document is really a VSD file"); + } + + // either a null name was given, or there is no such name + throw new FileNotFoundException("no such entry: \"" + name + + "\", had: " + _byUCName.keySet()); + } + return rval; + } + /** * create a new DocumentEntry * @@ -355,7 +418,7 @@ public class DirectoryNode @Override public DocumentEntry createDocument(final String name, final InputStream stream) - throws IOException + throws IOException { return createDocument(new POIFSDocument(name, _filesystem, stream)); } @@ -375,7 +438,7 @@ public class DirectoryNode @Override public DocumentEntry createDocument(final String name, final int size, final POIFSWriterListener writer) - throws IOException + throws IOException { return createDocument(new POIFSDocument(name, size, _filesystem, writer)); } @@ -392,16 +455,17 @@ public class DirectoryNode @Override public DirectoryEntry createDirectory(final String name) - throws IOException + throws IOException { DirectoryProperty property = new DirectoryProperty(name); DirectoryNode rval = new DirectoryNode(property, _filesystem, this); - _filesystem.addDirectory(property); + _filesystem.addDirectory(property); (( DirectoryProperty ) getProperty()).addChild(property); _entries.add(rval); _byname.put(name, rval); + _byUCName.put(name.toUpperCase(Locale.ROOT), rval); return rval; } @@ -419,12 +483,12 @@ public class DirectoryNode @SuppressWarnings("WeakerAccess") public DocumentEntry createOrUpdateDocument(final String name, final InputStream stream) - throws IOException + throws IOException { - if (! hasEntry(name)) { + if (! hasEntryCaseInsensitive(name)) { return createDocument(name, stream); } else { - DocumentNode existing = (DocumentNode)getEntry(name); + DocumentNode existing = (DocumentNode) getEntryCaseInsensitive(name); POIFSDocument nDoc = new POIFSDocument(existing); nDoc.replaceContents(stream); return existing; diff --git a/poi/src/main/java/org/apache/poi/poifs/filesystem/DocumentFactoryHelper.java b/poi/src/main/java/org/apache/poi/poifs/filesystem/DocumentFactoryHelper.java index 088b549283..6b9b749362 100644 --- a/poi/src/main/java/org/apache/poi/poifs/filesystem/DocumentFactoryHelper.java +++ b/poi/src/main/java/org/apache/poi/poifs/filesystem/DocumentFactoryHelper.java @@ -73,7 +73,7 @@ public final class DocumentFactoryHelper { public static InputStream getDecryptedStream(final DirectoryNode root, String password) throws IOException { // first check if the node contains an plain package - if (root.hasEntry(OOXML_PACKAGE)) { + if (root.hasEntryCaseInsensitive(OOXML_PACKAGE)) { return root.createDocumentInputStream(OOXML_PACKAGE); } diff --git a/poi/src/main/java/org/apache/poi/poifs/filesystem/FilteringDirectoryNode.java b/poi/src/main/java/org/apache/poi/poifs/filesystem/FilteringDirectoryNode.java index 9b3c0150b0..f9410c0264 100644 --- a/poi/src/main/java/org/apache/poi/poifs/filesystem/FilteringDirectoryNode.java +++ b/poi/src/main/java/org/apache/poi/poifs/filesystem/FilteringDirectoryNode.java @@ -129,7 +129,7 @@ public class FilteringDirectoryNode implements DirectoryEntry public int getEntryCount() { int size = directory.getEntryCount(); for (String excl : excludes) { - if (directory.hasEntry(excl)) { + if (directory.hasEntryCaseInsensitive(excl)) { size--; } } @@ -160,6 +160,15 @@ public class FilteringDirectoryNode implements DirectoryEntry return directory.hasEntry(name); } + @Override + public boolean hasEntryCaseInsensitive(String name) { + if (excludes.contains(name)) { + return false; + } + return directory.hasEntryCaseInsensitive(name); + } + + @Override public Entry getEntry(String name) throws FileNotFoundException { if (excludes.contains(name)) { @@ -169,6 +178,17 @@ public class FilteringDirectoryNode implements DirectoryEntry Entry entry = directory.getEntry(name); return wrapEntry(entry); } + + @Override + public Entry getEntryCaseInsensitive(String name) throws FileNotFoundException { + if (excludes.contains(name)) { + throw new FileNotFoundException(name); + } + + Entry entry = directory.getEntryCaseInsensitive(name); + return wrapEntry(entry); + } + private Entry wrapEntry(Entry entry) { String name = entry.getName(); if (childExcludes.containsKey(name) && entry instanceof DirectoryEntry) { @@ -258,4 +278,4 @@ public class FilteringDirectoryNode implements DirectoryEntry throw new UnsupportedOperationException("Remove not supported"); } } -} \ No newline at end of file +} diff --git a/poi/src/main/java/org/apache/poi/poifs/filesystem/Ole10Native.java b/poi/src/main/java/org/apache/poi/poifs/filesystem/Ole10Native.java index 90fbc2433e..fef85f82db 100644 --- a/poi/src/main/java/org/apache/poi/poifs/filesystem/Ole10Native.java +++ b/poi/src/main/java/org/apache/poi/poifs/filesystem/Ole10Native.java @@ -133,7 +133,7 @@ public class Ole10Native { * @throws Ole10NativeException on invalid or unexcepted data format */ public static Ole10Native createFromEmbeddedOleObject(DirectoryNode directory) throws IOException, Ole10NativeException { - DocumentEntry nativeEntry = (DocumentEntry) directory.getEntry(OLE10_NATIVE); + DocumentEntry nativeEntry = (DocumentEntry) directory.getEntryCaseInsensitive(OLE10_NATIVE); try (DocumentInputStream dis = directory.createDocumentInputStream(nativeEntry)) { byte[] data = IOUtils.toByteArray(dis, nativeEntry.getSize(), MAX_RECORD_LENGTH); return new Ole10Native(data, 0); @@ -253,7 +253,7 @@ public class Ole10Native { * OlePresXXX, but it seems, that they aren't necessary */ public static void createOleMarkerEntry(final DirectoryEntry parent) throws IOException { - if (!parent.hasEntry(OLE_MARKER_NAME)) { + if (!parent.hasEntryCaseInsensitive(OLE_MARKER_NAME)) { parent.createDocument(OLE_MARKER_NAME, UnsynchronizedByteArrayInputStream.builder().setByteArray(OLE_MARKER_BYTES).get()); } } diff --git a/poi/src/main/java/org/apache/poi/poifs/macros/VBAMacroReader.java b/poi/src/main/java/org/apache/poi/poifs/macros/VBAMacroReader.java index 944c05bbd1..5d5081a8f2 100644 --- a/poi/src/main/java/org/apache/poi/poifs/macros/VBAMacroReader.java +++ b/poi/src/main/java/org/apache/poi/poifs/macros/VBAMacroReader.java @@ -325,7 +325,7 @@ public class VBAMacroReader implements Closeable { //process the dirstream first -- "dir" is case insensitive for (String entryName : macroDir.getEntryNames()) { if ("dir".equalsIgnoreCase(entryName)) { - processDirStream(macroDir.getEntry(entryName), modules); + processDirStream(macroDir.getEntryCaseInsensitive(entryName), modules); break; } } diff --git a/poi/src/main/java/org/apache/poi/sl/usermodel/ObjectShape.java b/poi/src/main/java/org/apache/poi/sl/usermodel/ObjectShape.java index 8f6bd803e4..8fad23ee9e 100644 --- a/poi/src/main/java/org/apache/poi/sl/usermodel/ObjectShape.java +++ b/poi/src/main/java/org/apache/poi/sl/usermodel/ObjectShape.java @@ -113,7 +113,7 @@ public interface ObjectShape< final DirectoryNode root = poifs.getRoot(); String entryName = null; for (String n : names) { - if (root.hasEntry(n)) { + if (root.hasEntryCaseInsensitive(n)) { entryName = n; break; } diff --git a/poi/src/main/java/org/apache/poi/sl/usermodel/SlideShowFactory.java b/poi/src/main/java/org/apache/poi/sl/usermodel/SlideShowFactory.java index cb4c81ca77..b0aa16a89b 100644 --- a/poi/src/main/java/org/apache/poi/sl/usermodel/SlideShowFactory.java +++ b/poi/src/main/java/org/apache/poi/sl/usermodel/SlideShowFactory.java @@ -126,7 +126,7 @@ public final class SlideShowFactory { */ public static SlideShow create(final DirectoryNode root, String password) throws IOException { // Encrypted OOXML files go inside OLE2 containers, is this one? - if (root.hasEntry(Decryptor.DEFAULT_POIFS_ENTRY) || root.hasEntry(OOXML_PACKAGE)) { + if (root.hasEntryCaseInsensitive(Decryptor.DEFAULT_POIFS_ENTRY) || root.hasEntryCaseInsensitive(OOXML_PACKAGE)) { return wp(FileMagic.OOXML, w -> w.create(root, password)); } else { return wp(FileMagic.OLE2, w -> w.create(root, password)); @@ -200,7 +200,7 @@ public final class SlideShowFactory { POIFSFileSystem poifs = new POIFSFileSystem(is); DirectoryNode root = poifs.getRoot(); - boolean isOOXML = root.hasEntry(DEFAULT_POIFS_ENTRY) || root.hasEntry(OOXML_PACKAGE); + boolean isOOXML = root.hasEntryCaseInsensitive(DEFAULT_POIFS_ENTRY) || root.hasEntryCaseInsensitive(OOXML_PACKAGE); return wp(isOOXML ? FileMagic.OOXML : fm, w -> w.create(poifs.getRoot(), password)); } @@ -274,7 +274,7 @@ public final class SlideShowFactory { final boolean ooxmlEnc; try (POIFSFileSystem fs = new POIFSFileSystem(file, true)) { DirectoryNode root = fs.getRoot(); - ooxmlEnc = root.hasEntry(Decryptor.DEFAULT_POIFS_ENTRY) || root.hasEntry(OOXML_PACKAGE); + ooxmlEnc = root.hasEntryCaseInsensitive(Decryptor.DEFAULT_POIFS_ENTRY) || root.hasEntryCaseInsensitive(OOXML_PACKAGE); } return wp(ooxmlEnc ? FileMagic.OOXML : fm, w -> w.create(file, password, readOnly)); } else { diff --git a/poi/src/main/java/org/apache/poi/ss/extractor/EmbeddedExtractor.java b/poi/src/main/java/org/apache/poi/ss/extractor/EmbeddedExtractor.java index 31c6632c07..b0b3cbd990 100644 --- a/poi/src/main/java/org/apache/poi/ss/extractor/EmbeddedExtractor.java +++ b/poi/src/main/java/org/apache/poi/ss/extractor/EmbeddedExtractor.java @@ -213,7 +213,7 @@ public class EmbeddedExtractor implements Iterable { @Override public boolean canExtract(DirectoryNode dn) { ClassID clsId = dn.getStorageClsid(); - return (ClassIDPredefined.PDF.equals(clsId) || dn.hasEntry("CONTENTS")); + return (ClassIDPredefined.PDF.equals(clsId) || dn.hasEntryCaseInsensitive("CONTENTS")); } @Override @@ -273,7 +273,7 @@ public class EmbeddedExtractor implements Iterable { static class OOXMLExtractor extends EmbeddedExtractor { @Override public boolean canExtract(DirectoryNode dn) { - return dn.hasEntry("package"); + return dn.hasEntryCaseInsensitive("package"); } @Override @@ -312,14 +312,14 @@ public class EmbeddedExtractor implements Iterable { ClassIDPredefined clsId = ClassIDPredefined.lookup(dn.getStorageClsid()); return (ClassIDPredefined.EXCEL_V7 == clsId || ClassIDPredefined.EXCEL_V8 == clsId - || dn.hasEntry("Workbook") /*...*/); + || dn.hasEntryCaseInsensitive("Workbook") /*...*/); } protected boolean canExtractWord(DirectoryNode dn) { ClassIDPredefined clsId = ClassIDPredefined.lookup(dn.getStorageClsid()); return (ClassIDPredefined.WORD_V7 == clsId || ClassIDPredefined.WORD_V8 == clsId - || dn.hasEntry("WordDocument")); + || dn.hasEntryCaseInsensitive("WordDocument")); } @Override diff --git a/poi/src/main/java/org/apache/poi/ss/usermodel/WorkbookFactory.java b/poi/src/main/java/org/apache/poi/ss/usermodel/WorkbookFactory.java index 707c045bab..34ac9afd3c 100644 --- a/poi/src/main/java/org/apache/poi/ss/usermodel/WorkbookFactory.java +++ b/poi/src/main/java/org/apache/poi/ss/usermodel/WorkbookFactory.java @@ -150,7 +150,7 @@ public final class WorkbookFactory { */ public static Workbook create(final DirectoryNode root, String password) throws IOException { // Encrypted OOXML files go inside OLE2 containers, is this one? - if (root.hasEntry(DEFAULT_POIFS_ENTRY) || root.hasEntry(OOXML_PACKAGE)) { + if (root.hasEntryCaseInsensitive(DEFAULT_POIFS_ENTRY) || root.hasEntryCaseInsensitive(OOXML_PACKAGE)) { return wp(FileMagic.OOXML, w -> w.create(root, password)); } else { return wp(FileMagic.OLE2, w -> w.create(root, password)); @@ -230,7 +230,7 @@ public final class WorkbookFactory { POIFSFileSystem poifs = new POIFSFileSystem(is); DirectoryNode root = poifs.getRoot(); - boolean isOOXML = root.hasEntry(DEFAULT_POIFS_ENTRY) || root.hasEntry(OOXML_PACKAGE); + boolean isOOXML = root.hasEntryCaseInsensitive(DEFAULT_POIFS_ENTRY) || root.hasEntryCaseInsensitive(OOXML_PACKAGE); return wp(isOOXML ? FileMagic.OOXML : fm, w -> w.create(root, password)); } @@ -313,7 +313,7 @@ public final class WorkbookFactory { final boolean ooxmlEnc; try (POIFSFileSystem fs = new POIFSFileSystem(file, true)) { DirectoryNode root = fs.getRoot(); - ooxmlEnc = root.hasEntry(DEFAULT_POIFS_ENTRY) || root.hasEntry(OOXML_PACKAGE); + ooxmlEnc = root.hasEntryCaseInsensitive(DEFAULT_POIFS_ENTRY) || root.hasEntryCaseInsensitive(OOXML_PACKAGE); } return wp(ooxmlEnc ? FileMagic.OOXML : fm, w -> w.create(file, password, readOnly)); } else { diff --git a/poi/src/test/java/org/apache/poi/hpsf/basic/TestReadAllFiles.java b/poi/src/test/java/org/apache/poi/hpsf/basic/TestReadAllFiles.java index 395aab02cf..cf13fd0474 100644 --- a/poi/src/test/java/org/apache/poi/hpsf/basic/TestReadAllFiles.java +++ b/poi/src/test/java/org/apache/poi/hpsf/basic/TestReadAllFiles.java @@ -154,7 +154,7 @@ class TestReadAllFiles { * If there is a document summry information stream, read it from * the POI filesystem. */ - if (dir.hasEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME)) { + if (dir.hasEntryCaseInsensitive(DocumentSummaryInformation.DEFAULT_STREAM_NAME)) { final DocumentSummaryInformation dsi = TestWriteWellKnown.getDocumentSummaryInformation(poifs); assertNotNull(dsi); diff --git a/poi/src/test/java/org/apache/poi/hpsf/basic/TestWrite.java b/poi/src/test/java/org/apache/poi/hpsf/basic/TestWrite.java index 48b8b594ec..442bcde58f 100644 --- a/poi/src/test/java/org/apache/poi/hpsf/basic/TestWrite.java +++ b/poi/src/test/java/org/apache/poi/hpsf/basic/TestWrite.java @@ -447,8 +447,8 @@ class TestWrite { DirectoryEntry root = fs.getRoot(); // Read the properties in there - DocumentNode sinfDoc = (DocumentNode) root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME); - DocumentNode dinfDoc = (DocumentNode) root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME); + DocumentNode sinfDoc = (DocumentNode) root.getEntryCaseInsensitive(SummaryInformation.DEFAULT_STREAM_NAME); + DocumentNode dinfDoc = (DocumentNode) root.getEntryCaseInsensitive(DocumentSummaryInformation.DEFAULT_STREAM_NAME); InputStream sinfStream = new DocumentInputStream(sinfDoc); SummaryInformation sinf = (SummaryInformation) PropertySetFactory.create(sinfStream); @@ -479,8 +479,8 @@ class TestWrite { // Check it didn't get changed - sinfDoc = (DocumentNode) root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME); - dinfDoc = (DocumentNode) root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME); + sinfDoc = (DocumentNode) root.getEntryCaseInsensitive(SummaryInformation.DEFAULT_STREAM_NAME); + dinfDoc = (DocumentNode) root.getEntryCaseInsensitive(DocumentSummaryInformation.DEFAULT_STREAM_NAME); InputStream sinfStream2 = new DocumentInputStream(sinfDoc); sinf = (SummaryInformation) PropertySetFactory.create(sinfStream2); @@ -503,8 +503,8 @@ class TestWrite { DirectoryEntry root = fs.getRoot(); // Read the properties in once more - DocumentNode sinfDoc = (DocumentNode)root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME); - DocumentNode dinfDoc = (DocumentNode)root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME); + DocumentNode sinfDoc = (DocumentNode)root.getEntryCaseInsensitive(SummaryInformation.DEFAULT_STREAM_NAME); + DocumentNode dinfDoc = (DocumentNode)root.getEntryCaseInsensitive(DocumentSummaryInformation.DEFAULT_STREAM_NAME); InputStream sinfStream3 = new DocumentInputStream(sinfDoc); SummaryInformation sinf = (SummaryInformation)PropertySetFactory.create(sinfStream3); @@ -533,8 +533,8 @@ class TestWrite { // Check that the filesystem can give us back the same bytes - sinfDoc = (DocumentNode)root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME); - dinfDoc = (DocumentNode)root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME); + sinfDoc = (DocumentNode)root.getEntryCaseInsensitive(SummaryInformation.DEFAULT_STREAM_NAME); + dinfDoc = (DocumentNode)root.getEntryCaseInsensitive(DocumentSummaryInformation.DEFAULT_STREAM_NAME); InputStream sinfStream4 = new DocumentInputStream(sinfDoc); byte[] sinfData = IOUtils.toByteArray(sinfStream4); @@ -581,13 +581,13 @@ class TestWrite { // Read them back in again - sinfDoc = (DocumentNode)root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME); + sinfDoc = (DocumentNode)root.getEntryCaseInsensitive(SummaryInformation.DEFAULT_STREAM_NAME); InputStream sinfStream6 = new DocumentInputStream(sinfDoc); sinf = (SummaryInformation)PropertySetFactory.create(sinfStream6); sinfStream6.close(); assertEquals(131077, sinf.getOSVersion()); - dinfDoc = (DocumentNode)root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME); + dinfDoc = (DocumentNode)root.getEntryCaseInsensitive(DocumentSummaryInformation.DEFAULT_STREAM_NAME); InputStream dinfStream6 = new DocumentInputStream(dinfDoc); dinf = (DocumentSummaryInformation)PropertySetFactory.create(dinfStream6); dinfStream6.close(); @@ -609,13 +609,13 @@ class TestWrite { DirectoryEntry root = fs.getRoot(); // Re-check on load - DocumentNode sinfDoc = (DocumentNode) root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME); + DocumentNode sinfDoc = (DocumentNode) root.getEntryCaseInsensitive(SummaryInformation.DEFAULT_STREAM_NAME); InputStream sinfStream7 = new DocumentInputStream(sinfDoc); SummaryInformation sinf = (SummaryInformation) PropertySetFactory.create(sinfStream7); sinfStream7.close(); assertEquals(131077, sinf.getOSVersion()); - DocumentNode dinfDoc = (DocumentNode) root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME); + DocumentNode dinfDoc = (DocumentNode) root.getEntryCaseInsensitive(DocumentSummaryInformation.DEFAULT_STREAM_NAME); InputStream dinfStream7 = new DocumentInputStream(dinfDoc); DocumentSummaryInformation dinf = (DocumentSummaryInformation) PropertySetFactory.create(dinfStream7); dinfStream7.close(); diff --git a/poi/src/test/java/org/apache/poi/hpsf/basic/TestWriteWellKnown.java b/poi/src/test/java/org/apache/poi/hpsf/basic/TestWriteWellKnown.java index 06cf09cf3f..7a296522c7 100644 --- a/poi/src/test/java/org/apache/poi/hpsf/basic/TestWriteWellKnown.java +++ b/poi/src/test/java/org/apache/poi/hpsf/basic/TestWriteWellKnown.java @@ -494,7 +494,7 @@ class TestWriteWellKnown { static DocumentSummaryInformation getDocumentSummaryInformation(POIFSFileSystem poifs) throws IOException, NoPropertySetStreamException, UnexpectedPropertySetTypeException { - if (!poifs.getRoot().hasEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME)) { + if (!poifs.getRoot().hasEntryCaseInsensitive(DocumentSummaryInformation.DEFAULT_STREAM_NAME)) { return null; } diff --git a/poi/src/test/java/org/apache/poi/hssf/extractor/TestExcelExtractor.java b/poi/src/test/java/org/apache/poi/hssf/extractor/TestExcelExtractor.java index 497bd20843..495ceb9837 100644 --- a/poi/src/test/java/org/apache/poi/hssf/extractor/TestExcelExtractor.java +++ b/poi/src/test/java/org/apache/poi/hssf/extractor/TestExcelExtractor.java @@ -252,9 +252,9 @@ final class TestExcelExtractor { try { fs = new POIFSFileSystem(POIDataSamples.getDocumentInstance().getFile("word_with_embeded.doc")); - DirectoryNode objPool = (DirectoryNode) fs.getRoot().getEntry("ObjectPool"); - DirectoryNode dirA = (DirectoryNode) objPool.getEntry("_1269427460"); - DirectoryNode dirB = (DirectoryNode) objPool.getEntry("_1269427461"); + DirectoryNode objPool = (DirectoryNode) fs.getRoot().getEntryCaseInsensitive("ObjectPool"); + DirectoryNode dirA = (DirectoryNode) objPool.getEntryCaseInsensitive("_1269427460"); + DirectoryNode dirB = (DirectoryNode) objPool.getEntryCaseInsensitive("_1269427461"); wbA = new HSSFWorkbook(dirA, fs, true); exA = new ExcelExtractor(wbA); @@ -287,8 +287,8 @@ final class TestExcelExtractor { try { fs = new POIFSFileSystem(ssSamples.getFile("excel_with_embeded.xls")); - DirectoryNode dirA = (DirectoryNode) fs.getRoot().getEntry("MBD0000A3B5"); - DirectoryNode dirB = (DirectoryNode) fs.getRoot().getEntry("MBD0000A3B4"); + DirectoryNode dirA = (DirectoryNode) fs.getRoot().getEntryCaseInsensitive("MBD0000A3B5"); + DirectoryNode dirB = (DirectoryNode) fs.getRoot().getEntryCaseInsensitive("MBD0000A3B4"); wbA = new HSSFWorkbook(dirA, fs, true); wbB = new HSSFWorkbook(dirB, fs, true); diff --git a/poi/src/test/java/org/apache/poi/hssf/usermodel/TestBugs.java b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestBugs.java index b836e3269c..b9d5fcb3ca 100644 --- a/poi/src/test/java/org/apache/poi/hssf/usermodel/TestBugs.java +++ b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestBugs.java @@ -2451,7 +2451,7 @@ final class TestBugs extends BaseTestBugzillaIssues { try (POIFSFileSystem poifs = new POIFSFileSystem(HSSFTestDataSamples.openSampleFileStream("61300.xls"))) { DocumentEntry entry = - (DocumentEntry) poifs.getRoot().getEntry(SummaryInformation.DEFAULT_STREAM_NAME); + (DocumentEntry) poifs.getRoot().getEntryCaseInsensitive(SummaryInformation.DEFAULT_STREAM_NAME); RuntimeException ex = assertThrows( RuntimeException.class, diff --git a/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java index eb87441cd3..94f3c4fa78 100644 --- a/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java +++ b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java @@ -644,7 +644,7 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook { DirectoryEntry dir = embeddedObject.getDirectory(); if (dir instanceof DirectoryNode) { DirectoryNode dNode = (DirectoryNode) dir; - if (dNode.hasEntry("WordDocument")) { + if (dNode.hasEntryCaseInsensitive("WordDocument")) { found = true; break; } diff --git a/poi/src/test/java/org/apache/poi/hssf/usermodel/TestNonStandardWorkbookStreamNames.java b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestNonStandardWorkbookStreamNames.java index 3434d7b581..e44195afcd 100644 --- a/poi/src/test/java/org/apache/poi/hssf/usermodel/TestNonStandardWorkbookStreamNames.java +++ b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestNonStandardWorkbookStreamNames.java @@ -121,14 +121,13 @@ final class TestNonStandardWorkbookStreamNames { wb.close(); DirectoryNode root = wb2.getDirectory(); - // Check that we have the new entries assertTrue(root.hasEntry("Workbook")); assertFalse(root.hasEntry("BOOK")); assertFalse(root.hasEntry("WORKBOOK")); // As we preserved, should also have a few other streams - assertTrue(root.hasEntry(SummaryInformation.DEFAULT_STREAM_NAME)); + assertTrue(root.hasEntryCaseInsensitive(SummaryInformation.DEFAULT_STREAM_NAME)); wb2.close(); } } diff --git a/poi/src/test/java/org/apache/poi/hssf/usermodel/TestPOIFSProperties.java b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestPOIFSProperties.java index 2bc2da0a1c..4faf164731 100644 --- a/poi/src/test/java/org/apache/poi/hssf/usermodel/TestPOIFSProperties.java +++ b/poi/src/test/java/org/apache/poi/hssf/usermodel/TestPOIFSProperties.java @@ -89,7 +89,7 @@ class TestPOIFSProperties { summary1.setTitle(title); //write the modified property back to POIFS - fs.getRoot().getEntry(SummaryInformation.DEFAULT_STREAM_NAME).delete(); + fs.getRoot().getEntryCaseInsensitive(SummaryInformation.DEFAULT_STREAM_NAME).delete(); fs.createDocument(summary1.toInputStream(), SummaryInformation.DEFAULT_STREAM_NAME); // check that the information was added successfully to the filesystem object diff --git a/poi/src/test/java/org/apache/poi/poifs/filesystem/ReaderWriter.java b/poi/src/test/java/org/apache/poi/poifs/filesystem/ReaderWriter.java index 195682ae75..0c57856df0 100644 --- a/poi/src/test/java/org/apache/poi/poifs/filesystem/ReaderWriter.java +++ b/poi/src/test/java/org/apache/poi/poifs/filesystem/ReaderWriter.java @@ -106,7 +106,7 @@ public final class ReaderWriter implements POIFSReaderListener, POIFSWriterListe try { - nextEntry = entry.getEntry(componentName); + nextEntry = entry.getEntryCaseInsensitive(componentName); } catch (FileNotFoundException ignored) { diff --git a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestDirectoryNode.java b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestDirectoryNode.java index 1a81dc5a58..15342a245d 100644 --- a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestDirectoryNode.java +++ b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestDirectoryNode.java @@ -73,7 +73,7 @@ final class TestDirectoryNode { assertEquals(0, node.getEntryCount()); // verify behavior of getEntry - assertThrows(FileNotFoundException.class, () -> node.getEntry("foo")); + assertThrows(FileNotFoundException.class, () -> node.getEntryCaseInsensitive("foo")); // verify behavior of isDirectoryEntry assertTrue(node.isDirectoryEntry()); @@ -124,11 +124,11 @@ final class TestDirectoryNode { assertEquals(2, node.getEntryCount()); // verify behavior of getEntry - DirectoryNode child1 = (DirectoryNode) node.getEntry("child1"); + DirectoryNode child1 = (DirectoryNode) node.getEntryCaseInsensitive("child1"); - child1.getEntry("child3"); - node.getEntry("child2"); - assertThrows(FileNotFoundException.class, () -> node.getEntry("child3")); + child1.getEntryCaseInsensitive("child3"); + node.getEntryCaseInsensitive("child2"); + assertThrows(FileNotFoundException.class, () -> node.getEntryCaseInsensitive("child3")); // verify behavior of isDirectoryEntry assertTrue(node.isDirectoryEntry()); diff --git a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestDocument.java b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestDocument.java index 94bc700be3..59c6d168ba 100644 --- a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestDocument.java +++ b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestDocument.java @@ -101,8 +101,8 @@ class TestDocument { POIFSFileSystem poifs = document.getFileSystem(); String name = "test" + input.length; DirectoryNode root = poifs.getRoot(); - if (root.hasEntry(name)) { - root.deleteEntry((EntryNode)root.getEntry(name)); + if (root.hasEntryCaseInsensitive(name)) { + root.deleteEntry((EntryNode)root.getEntryCaseInsensitive(name)); } return ((DocumentNode)root .createDocument(name, new ByteArrayInputStream(input))) diff --git a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestDocumentInputStream.java b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestDocumentInputStream.java index c0d4de1353..c083a2c3e4 100644 --- a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestDocumentInputStream.java +++ b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestDocumentInputStream.java @@ -381,22 +381,22 @@ final class TestDocumentInputStream { // Check inside DirectoryNode root = poifs.getRoot(); // Top Level - Entry top = root.getEntry("Contents"); + Entry top = root.getEntryCaseInsensitive("Contents"); assertTrue(top.isDocumentEntry()); stream = root.createDocumentInputStream(top); assertNotEquals(-1, stream.read()); // One Level Down - DirectoryNode escher = (DirectoryNode) root.getEntry("Escher"); - Entry one = escher.getEntry("EscherStm"); + DirectoryNode escher = (DirectoryNode) root.getEntryCaseInsensitive("Escher"); + Entry one = escher.getEntryCaseInsensitive("EscherStm"); assertTrue(one.isDocumentEntry()); stream = escher.createDocumentInputStream(one); assertNotEquals(-1, stream.read()); // Two Levels Down - DirectoryNode quill = (DirectoryNode) root.getEntry("Quill"); - DirectoryNode quillSub = (DirectoryNode) quill.getEntry("QuillSub"); - Entry two = quillSub.getEntry("CONTENTS"); + DirectoryNode quill = (DirectoryNode) root.getEntryCaseInsensitive("Quill"); + DirectoryNode quillSub = (DirectoryNode) quill.getEntryCaseInsensitive("QuillSub"); + Entry two = quillSub.getEntryCaseInsensitive("CONTENTS"); assertTrue(two.isDocumentEntry()); stream = quillSub.createDocumentInputStream(two); assertNotEquals(-1, stream.read()); diff --git a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestEmptyDocument.java b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestEmptyDocument.java index f60ce5bc3b..9507b13a7d 100644 --- a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestEmptyDocument.java +++ b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestEmptyDocument.java @@ -101,13 +101,13 @@ final class TestEmptyDocument { // This line caused the error. try (POIFSFileSystem fs = new POIFSFileSystem(out.toInputStream())) { - DocumentEntry entry = (DocumentEntry) fs.getRoot().getEntry("Empty"); + DocumentEntry entry = (DocumentEntry) fs.getRoot().getEntryCaseInsensitive("Empty"); assertEquals(0, entry.getSize(), "Expected zero size"); byte[] actualReadbackData; actualReadbackData = IOUtils.toByteArray(new DocumentInputStream(entry)); assertEquals(0, actualReadbackData.length, "Expected zero read from stream"); - entry = (DocumentEntry) fs.getRoot().getEntry("NotEmpty"); + entry = (DocumentEntry) fs.getRoot().getEntryCaseInsensitive("NotEmpty"); actualReadbackData = IOUtils.toByteArray(new DocumentInputStream(entry)); assertEquals(testData.length, entry.getSize(), "Expected size was wrong"); assertArrayEquals(testData, actualReadbackData, "Expected same data read from stream"); diff --git a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestEntryUtils.java b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestEntryUtils.java index 16fa1fd240..9dfec6f276 100644 --- a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestEntryUtils.java +++ b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestEntryUtils.java @@ -53,18 +53,18 @@ class TestEntryUtils { EntryUtils.copyNodeRecursively(entryR, fsD.getRoot()); assertEquals(1, fsD.getRoot().getEntryCount()); - assertNotNull(fsD.getRoot().getEntry("EntryRoot")); + assertNotNull(fsD.getRoot().getEntryCaseInsensitive("EntryRoot")); EntryUtils.copyNodeRecursively(entryA1, fsD.getRoot()); assertEquals(2, fsD.getRoot().getEntryCount()); - assertNotNull(fsD.getRoot().getEntry("EntryRoot")); - assertNotNull(fsD.getRoot().getEntry("EntryA1")); + assertNotNull(fsD.getRoot().getEntryCaseInsensitive("EntryRoot")); + assertNotNull(fsD.getRoot().getEntryCaseInsensitive("EntryA1")); EntryUtils.copyNodeRecursively(entryA2, fsD.getRoot()); assertEquals(3, fsD.getRoot().getEntryCount()); - assertNotNull(fsD.getRoot().getEntry("EntryRoot")); - assertNotNull(fsD.getRoot().getEntry("EntryA1")); - assertNotNull(fsD.getRoot().getEntry("EntryA2")); + assertNotNull(fsD.getRoot().getEntryCaseInsensitive("EntryRoot")); + assertNotNull(fsD.getRoot().getEntryCaseInsensitive("EntryA1")); + assertNotNull(fsD.getRoot().getEntryCaseInsensitive("EntryA2")); fsD.close(); @@ -74,15 +74,15 @@ class TestEntryUtils { EntryUtils.copyNodeRecursively(dirB, fsD.getRoot()); assertEquals(1, fsD.getRoot().getEntryCount()); - assertNotNull(fsD.getRoot().getEntry("DirB")); - assertEquals(0, ((DirectoryEntry)fsD.getRoot().getEntry("DirB")).getEntryCount()); + assertNotNull(fsD.getRoot().getEntryCaseInsensitive("DirB")); + assertEquals(0, ((DirectoryEntry)fsD.getRoot().getEntryCaseInsensitive("DirB")).getEntryCount()); EntryUtils.copyNodeRecursively(dirA, fsD.getRoot()); assertEquals(2, fsD.getRoot().getEntryCount()); - assertNotNull(fsD.getRoot().getEntry("DirB")); - assertEquals(0, ((DirectoryEntry)fsD.getRoot().getEntry("DirB")).getEntryCount()); - assertNotNull(fsD.getRoot().getEntry("DirA")); - assertEquals(2, ((DirectoryEntry)fsD.getRoot().getEntry("DirA")).getEntryCount()); + assertNotNull(fsD.getRoot().getEntryCaseInsensitive("DirB")); + assertEquals(0, ((DirectoryEntry)fsD.getRoot().getEntryCaseInsensitive("DirB")).getEntryCount()); + assertNotNull(fsD.getRoot().getEntryCaseInsensitive("DirA")); + assertEquals(2, ((DirectoryEntry)fsD.getRoot().getEntryCaseInsensitive("DirA")).getEntryCount()); fsD.close(); // Copy the whole lot @@ -91,11 +91,11 @@ class TestEntryUtils { EntryUtils.copyNodes(fs, fsD, new ArrayList<>()); assertEquals(3, fsD.getRoot().getEntryCount()); - assertNotNull(fsD.getRoot().getEntry(dirA.getName())); - assertNotNull(fsD.getRoot().getEntry(dirB.getName())); - assertNotNull(fsD.getRoot().getEntry(entryR.getName())); - assertEquals(0, ((DirectoryEntry)fsD.getRoot().getEntry("DirB")).getEntryCount()); - assertEquals(2, ((DirectoryEntry)fsD.getRoot().getEntry("DirA")).getEntryCount()); + assertNotNull(fsD.getRoot().getEntryCaseInsensitive(dirA.getName())); + assertNotNull(fsD.getRoot().getEntryCaseInsensitive(dirB.getName())); + assertNotNull(fsD.getRoot().getEntryCaseInsensitive(entryR.getName())); + assertEquals(0, ((DirectoryEntry)fsD.getRoot().getEntryCaseInsensitive("DirB")).getEntryCount()); + assertEquals(2, ((DirectoryEntry)fsD.getRoot().getEntryCaseInsensitive("DirA")).getEntryCount()); fsD.close(); fs.close(); } @@ -131,11 +131,11 @@ class TestEntryUtils { try (InputStream tmpI = tmpO.toInputStream(); POIFSFileSystem nfs = new POIFSFileSystem(tmpI)) { - DirectoryEntry dN1 = (DirectoryEntry) nfs.getRoot().getEntry("DirA"); - DirectoryEntry dN2 = (DirectoryEntry) nfs.getRoot().getEntry("DirB"); - DocumentEntry eNA1 = (DocumentEntry) dN1.getEntry(entryA1.getName()); - DocumentEntry eNA2 = (DocumentEntry) dN1.getEntry(entryA2.getName()); - DocumentEntry eNB1 = (DocumentEntry) dN2.getEntry(entryB1.getName()); + DirectoryEntry dN1 = (DirectoryEntry) nfs.getRoot().getEntryCaseInsensitive("DirA"); + DirectoryEntry dN2 = (DirectoryEntry) nfs.getRoot().getEntryCaseInsensitive("DirB"); + DocumentEntry eNA1 = (DocumentEntry) dN1.getEntryCaseInsensitive(entryA1.getName()); + DocumentEntry eNA2 = (DocumentEntry) dN1.getEntryCaseInsensitive(entryA2.getName()); + DocumentEntry eNB1 = (DocumentEntry) dN2.getEntryCaseInsensitive(entryB1.getName()); assertFalse(EntryUtils.areDocumentsIdentical(eNA1, eNA2)); assertTrue(EntryUtils.areDocumentsIdentical(eNA1, eNB1)); diff --git a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestFilteringDirectoryNode.java b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestFilteringDirectoryNode.java index ae28e00d36..39bbfa2a40 100644 --- a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestFilteringDirectoryNode.java +++ b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestFilteringDirectoryNode.java @@ -63,16 +63,16 @@ final class TestFilteringDirectoryNode { void testNoFiltering() throws Exception { FilteringDirectoryNode d = new FilteringDirectoryNode(fs.getRoot(), new HashSet<>()); assertEquals(3, d.getEntryCount()); - assertEquals(dirA.getName(), d.getEntry(dirA.getName()).getName()); + assertEquals(dirA.getName(), d.getEntryCaseInsensitive(dirA.getName()).getName()); - assertTrue(d.getEntry(dirA.getName()).isDirectoryEntry()); - assertFalse(d.getEntry(dirA.getName()).isDocumentEntry()); + assertTrue(d.getEntryCaseInsensitive(dirA.getName()).isDirectoryEntry()); + assertFalse(d.getEntryCaseInsensitive(dirA.getName()).isDocumentEntry()); - assertTrue(d.getEntry(dirB.getName()).isDirectoryEntry()); - assertFalse(d.getEntry(dirB.getName()).isDocumentEntry()); + assertTrue(d.getEntryCaseInsensitive(dirB.getName()).isDirectoryEntry()); + assertFalse(d.getEntryCaseInsensitive(dirB.getName()).isDocumentEntry()); - assertFalse(d.getEntry(eRoot.getName()).isDirectoryEntry()); - assertTrue(d.getEntry(eRoot.getName()).isDocumentEntry()); + assertFalse(d.getEntryCaseInsensitive(eRoot.getName()).isDirectoryEntry()); + assertTrue(d.getEntryCaseInsensitive(eRoot.getName()).isDocumentEntry()); Iterator i = d.getEntries(); assertEquals(dirA, i.next()); @@ -93,13 +93,13 @@ final class TestFilteringDirectoryNode { FilteringDirectoryNode d1 = new FilteringDirectoryNode(fs.getRoot(), excl); assertEquals(2, d1.getEntryCount()); - assertTrue(d1.hasEntry(dirA.getName())); - assertTrue(d1.hasEntry(dirB.getName())); - assertFalse(d1.hasEntry(eRoot.getName())); + assertTrue(d1.hasEntryCaseInsensitive(dirA.getName())); + assertTrue(d1.hasEntryCaseInsensitive(dirB.getName())); + assertFalse(d1.hasEntryCaseInsensitive(eRoot.getName())); - assertEquals(dirA, d1.getEntry(dirA.getName())); - assertEquals(dirB, d1.getEntry(dirB.getName())); - assertThrows(FileNotFoundException.class, () -> d1.getEntry(eRoot.getName())); + assertEquals(dirA, d1.getEntryCaseInsensitive(dirA.getName())); + assertEquals(dirB, d1.getEntryCaseInsensitive(dirB.getName())); + assertThrows(FileNotFoundException.class, () -> d1.getEntryCaseInsensitive(eRoot.getName())); Iterator i = d1.getEntries(); assertEquals(dirA, i.next()); @@ -117,12 +117,12 @@ final class TestFilteringDirectoryNode { FilteringDirectoryNode d2 = new FilteringDirectoryNode(fs.getRoot(), excl); assertEquals(1, d2.getEntryCount()); - assertFalse(d2.hasEntry(dirA.getName())); - assertTrue(d2.hasEntry(dirB.getName())); - assertFalse(d2.hasEntry(eRoot.getName())); - assertThrows(FileNotFoundException.class, () -> d2.getEntry(dirA.getName()), "Should be filtered"); - assertEquals(dirB, d2.getEntry(dirB.getName())); - assertThrows(FileNotFoundException.class, () -> d2.getEntry(eRoot.getName()), "Should be filtered"); + assertFalse(d2.hasEntryCaseInsensitive(dirA.getName())); + assertTrue(d2.hasEntryCaseInsensitive(dirB.getName())); + assertFalse(d2.hasEntryCaseInsensitive(eRoot.getName())); + assertThrows(FileNotFoundException.class, () -> d2.getEntryCaseInsensitive(dirA.getName()), "Should be filtered"); + assertEquals(dirB, d2.getEntryCaseInsensitive(dirB.getName())); + assertThrows(FileNotFoundException.class, () -> d2.getEntryCaseInsensitive(eRoot.getName()), "Should be filtered"); i = d2.getEntries(); assertEquals(dirB, i.next()); @@ -137,12 +137,12 @@ final class TestFilteringDirectoryNode { FilteringDirectoryNode d3 = new FilteringDirectoryNode(fs.getRoot(), excl); assertEquals(0, d3.getEntryCount()); - assertFalse(d3.hasEntry(dirA.getName())); - assertFalse(d3.hasEntry(dirB.getName())); - assertFalse(d3.hasEntry(eRoot.getName())); - assertThrows(FileNotFoundException.class, () -> d3.getEntry(dirA.getName()), "Should be filtered"); - assertThrows(FileNotFoundException.class, () -> d3.getEntry(dirB.getName()), "Should be filtered"); - assertThrows(FileNotFoundException.class, () -> d3.getEntry(eRoot.getName()), "Should be filtered"); + assertFalse(d3.hasEntryCaseInsensitive(dirA.getName())); + assertFalse(d3.hasEntryCaseInsensitive(dirB.getName())); + assertFalse(d3.hasEntryCaseInsensitive(eRoot.getName())); + assertThrows(FileNotFoundException.class, () -> d3.getEntryCaseInsensitive(dirA.getName()), "Should be filtered"); + assertThrows(FileNotFoundException.class, () -> d3.getEntryCaseInsensitive(dirB.getName()), "Should be filtered"); + assertThrows(FileNotFoundException.class, () -> d3.getEntryCaseInsensitive(eRoot.getName()), "Should be filtered"); i = d3.getEntries(); assertThrows(NoSuchElementException.class, i::next, "Should throw NoSuchElementException when depleted"); @@ -161,24 +161,24 @@ final class TestFilteringDirectoryNode { // Check main assertEquals(2, d.getEntryCount()); - assertTrue(d.hasEntry(dirA.getName())); - assertTrue(d.hasEntry(dirB.getName())); - assertFalse(d.hasEntry(eRoot.getName())); + assertTrue(d.hasEntryCaseInsensitive(dirA.getName())); + assertTrue(d.hasEntryCaseInsensitive(dirB.getName())); + assertFalse(d.hasEntryCaseInsensitive(eRoot.getName())); // Check filtering down - assertTrue(d.getEntry(dirA.getName()) instanceof FilteringDirectoryNode); - assertFalse(d.getEntry(dirB.getName()) instanceof FilteringDirectoryNode); + assertTrue(d.getEntryCaseInsensitive(dirA.getName()) instanceof FilteringDirectoryNode); + assertFalse(d.getEntryCaseInsensitive(dirB.getName()) instanceof FilteringDirectoryNode); - DirectoryEntry fdA = (DirectoryEntry) d.getEntry(dirA.getName()); - assertFalse(fdA.hasEntry(eA.getName())); - assertTrue(fdA.hasEntry(dirAA.getName())); + DirectoryEntry fdA = (DirectoryEntry) d.getEntryCaseInsensitive(dirA.getName()); + assertFalse(fdA.hasEntryCaseInsensitive(eA.getName())); + assertTrue(fdA.hasEntryCaseInsensitive(dirAA.getName())); - DirectoryEntry fdAA = (DirectoryEntry) fdA.getEntry(dirAA.getName()); - assertTrue(fdAA.hasEntry(eAA.getName())); + DirectoryEntry fdAA = (DirectoryEntry) fdA.getEntryCaseInsensitive(dirAA.getName()); + assertTrue(fdAA.hasEntryCaseInsensitive(eAA.getName())); } @Test void testNullDirectory() { assertThrows(IllegalArgumentException.class, () -> new FilteringDirectoryNode(null, null)); } -} \ No newline at end of file +} diff --git a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPOIFSFileSystem.java b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPOIFSFileSystem.java index 10e7759a06..a4c421a2a7 100644 --- a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPOIFSFileSystem.java +++ b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPOIFSFileSystem.java @@ -214,7 +214,7 @@ final class TestPOIFSFileSystem { DirectoryNode root = fs.getRoot(); assertEquals(1, root.getEntryCount()); - DocumentNode big = (DocumentNode)root.getEntry("BIG"); + DocumentNode big = (DocumentNode)root.getEntryCaseInsensitive("BIG"); assertEquals(hugeStream.length, big.getSize()); } diff --git a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPOIFSMiniStore.java b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPOIFSMiniStore.java index fcc1e4bcf1..8d24e9f87b 100644 --- a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPOIFSMiniStore.java +++ b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPOIFSMiniStore.java @@ -390,7 +390,7 @@ final class TestPOIFSMiniStore { assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(2)); // Check the data is unchanged and the right length - entry = (DocumentEntry) fs.getRoot().getEntry("mini"); + entry = (DocumentEntry) fs.getRoot().getEntryCaseInsensitive("mini"); assertEquals(data.length, entry.getSize()); byte[] rdata = new byte[data.length]; dis = new DocumentInputStream(entry); @@ -398,7 +398,7 @@ final class TestPOIFSMiniStore { assertArrayEquals(data, rdata); dis.close(); - entry = (DocumentEntry) fs.getRoot().getEntry("mini2"); + entry = (DocumentEntry) fs.getRoot().getEntryCaseInsensitive("mini2"); assertEquals(data.length, entry.getSize()); rdata = new byte[data.length]; dis = new DocumentInputStream(entry); diff --git a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPOIFSStream.java b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPOIFSStream.java index 4efcc80983..7f25ca751d 100644 --- a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPOIFSStream.java +++ b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPOIFSStream.java @@ -960,7 +960,7 @@ final class TestPOIFSStream { assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(10)); assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(11)); - DocumentEntry normal = (DocumentEntry) fs1.getRoot().getEntry("Normal"); + DocumentEntry normal = (DocumentEntry) fs1.getRoot().getEntryCaseInsensitive("Normal"); assertEquals(4106, normal.getSize()); assertEquals(4106, ((DocumentNode) normal).getProperty().getSize()); @@ -988,7 +988,7 @@ final class TestPOIFSStream { assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(10)); assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(11)); - normal = (DocumentEntry) fs1.getRoot().getEntry("Normal"); + normal = (DocumentEntry) fs1.getRoot().getEntryCaseInsensitive("Normal"); assertEquals(4096, normal.getSize()); assertEquals(4096, ((DocumentNode) normal).getProperty().getSize()); @@ -1011,13 +1011,13 @@ final class TestPOIFSStream { assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(10)); assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(11)); - normal = (DocumentEntry) fs2.getRoot().getEntry("Normal"); + normal = (DocumentEntry) fs2.getRoot().getEntryCaseInsensitive("Normal"); assertEquals(4096, normal.getSize()); assertEquals(4096, ((DocumentNode) normal).getProperty().getSize()); // Make longer, take 1 block at the end - normal = (DocumentEntry) fs2.getRoot().getEntry("Normal"); + normal = (DocumentEntry) fs2.getRoot().getEntryCaseInsensitive("Normal"); try (DocumentOutputStream nout = new DocumentOutputStream(normal)) { nout.write(main4106); } @@ -1036,14 +1036,14 @@ final class TestPOIFSStream { assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(11)); assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(12)); - normal = (DocumentEntry) fs2.getRoot().getEntry("Normal"); + normal = (DocumentEntry) fs2.getRoot().getEntryCaseInsensitive("Normal"); assertEquals(4106, normal.getSize()); assertEquals(4106, ((DocumentNode) normal).getProperty().getSize()); // Make it small, will trigger the SBAT stream and free lots up byte[] mini = new byte[]{42, 0, 1, 2, 3, 4, 42}; - normal = (DocumentEntry) fs2.getRoot().getEntry("Normal"); + normal = (DocumentEntry) fs2.getRoot().getEntryCaseInsensitive("Normal"); try (DocumentOutputStream nout = new DocumentOutputStream(normal)) { nout.write(mini); } @@ -1062,7 +1062,7 @@ final class TestPOIFSStream { assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(11)); assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(12)); - normal = (DocumentEntry) fs2.getRoot().getEntry("Normal"); + normal = (DocumentEntry) fs2.getRoot().getEntryCaseInsensitive("Normal"); assertEquals(7, normal.getSize()); assertEquals(7, ((DocumentNode) normal).getProperty().getSize()); @@ -1088,7 +1088,7 @@ final class TestPOIFSStream { assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(12)); assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(13)); - normal = (DocumentEntry) fs2.getRoot().getEntry("Normal"); + normal = (DocumentEntry) fs2.getRoot().getEntryCaseInsensitive("Normal"); assertEquals(4096, normal.getSize()); assertEquals(4096, ((DocumentNode) normal).getProperty().getSize()); @@ -1112,7 +1112,7 @@ final class TestPOIFSStream { assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(12)); assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(13)); - normal = (DocumentEntry) fs3.getRoot().getEntry("Normal"); + normal = (DocumentEntry) fs3.getRoot().getEntryCaseInsensitive("Normal"); assertEquals(4096, normal.getSize()); assertEquals(4096, ((DocumentNode) normal).getProperty().getSize()); } @@ -1639,11 +1639,11 @@ final class TestPOIFSStream { assertEquals(5, root.getEntryCount()); // Check by the names - Entry thumbnail = root.getEntry("Thumbnail"); - Entry dsi = root.getEntry("\u0005DocumentSummaryInformation"); - Entry si = root.getEntry("\u0005SummaryInformation"); - Entry image = root.getEntry("Image"); - Entry tags = root.getEntry("Tags"); + Entry thumbnail = root.getEntryCaseInsensitive("Thumbnail"); + Entry dsi = root.getEntryCaseInsensitive("\u0005DocumentSummaryInformation"); + Entry si = root.getEntryCaseInsensitive("\u0005SummaryInformation"); + Entry image = root.getEntryCaseInsensitive("Image"); + Entry tags = root.getEntryCaseInsensitive("Tags"); assertFalse(thumbnail.isDirectoryEntry()); assertFalse(dsi.isDirectoryEntry()); @@ -1675,7 +1675,7 @@ final class TestPOIFSStream { throws IOException, NoPropertySetStreamException { try (POIFSFileSystem fs = opener.apply(file)) { DirectoryEntry root = fs.getRoot(); - Entry si = root.getEntry("\u0005SummaryInformation"); + Entry si = root.getEntryCaseInsensitive("\u0005SummaryInformation"); assertTrue(si.isDocumentEntry()); DocumentNode doc = (DocumentNode) si; @@ -1697,7 +1697,7 @@ final class TestPOIFSStream { // Try the other summary information - si = root.getEntry("\u0005DocumentSummaryInformation"); + si = root.getEntryCaseInsensitive("\u0005DocumentSummaryInformation"); assertTrue(si.isDocumentEntry()); doc = (DocumentNode) si; assertContentsMatches(null, doc); @@ -1745,11 +1745,11 @@ final class TestPOIFSStream { // Check the contents of them - parse the summary block and check sinf = (SummaryInformation) PropertySetFactory.create(new DocumentInputStream( - (DocumentEntry) root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME))); + (DocumentEntry) root.getEntryCaseInsensitive(SummaryInformation.DEFAULT_STREAM_NAME))); assertEquals(131333, sinf.getOSVersion()); dinf = (DocumentSummaryInformation) PropertySetFactory.create(new DocumentInputStream( - (DocumentEntry) root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME))); + (DocumentEntry) root.getEntryCaseInsensitive(DocumentSummaryInformation.DEFAULT_STREAM_NAME))); assertEquals(131333, dinf.getOSVersion()); @@ -1765,7 +1765,7 @@ final class TestPOIFSStream { try (POIFSFileSystem fs3 = writeOutAndReadBack(fs2)) { root = fs3.getRoot(); - testDir = (DirectoryEntry) root.getEntry("Testing 123"); + testDir = (DirectoryEntry) root.getEntryCaseInsensitive("Testing 123"); assertEquals(6, root.getEntryCount()); assertThat(root.getEntryNames(), hasItem("Thumbnail")); assertThat(root.getEntryNames(), hasItem("Image")); @@ -1777,21 +1777,21 @@ final class TestPOIFSStream { // Check old and new are there sinf = (SummaryInformation) PropertySetFactory.create(new DocumentInputStream( - (DocumentEntry) root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME))); + (DocumentEntry) root.getEntryCaseInsensitive(SummaryInformation.DEFAULT_STREAM_NAME))); assertEquals(131333, sinf.getOSVersion()); dinf = (DocumentSummaryInformation) PropertySetFactory.create(new DocumentInputStream( - (DocumentEntry) root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME))); + (DocumentEntry) root.getEntryCaseInsensitive(DocumentSummaryInformation.DEFAULT_STREAM_NAME))); assertEquals(131333, dinf.getOSVersion()); - assertContentsMatches(mini, (DocumentEntry) testDir.getEntry("Mini")); + assertContentsMatches(mini, (DocumentEntry) testDir.getEntryCaseInsensitive("Mini")); // Write out and read once more, just to be sure try (POIFSFileSystem fs4 = writeOutAndReadBack(fs3)) { root = fs4.getRoot(); - testDir = (DirectoryEntry) root.getEntry("Testing 123"); + testDir = (DirectoryEntry) root.getEntryCaseInsensitive("Testing 123"); assertEquals(6, root.getEntryCount()); assertThat(root.getEntryNames(), hasItem("Thumbnail")); assertThat(root.getEntryNames(), hasItem("Image")); @@ -1801,14 +1801,14 @@ final class TestPOIFSStream { assertThat(root.getEntryNames(), hasItem("\u0005SummaryInformation")); sinf = (SummaryInformation) PropertySetFactory.create(new DocumentInputStream( - (DocumentEntry) root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME))); + (DocumentEntry) root.getEntryCaseInsensitive(SummaryInformation.DEFAULT_STREAM_NAME))); assertEquals(131333, sinf.getOSVersion()); dinf = (DocumentSummaryInformation) PropertySetFactory.create(new DocumentInputStream( - (DocumentEntry) root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME))); + (DocumentEntry) root.getEntryCaseInsensitive(DocumentSummaryInformation.DEFAULT_STREAM_NAME))); assertEquals(131333, dinf.getOSVersion()); - assertContentsMatches(mini, (DocumentEntry) testDir.getEntry("Mini")); + assertContentsMatches(mini, (DocumentEntry) testDir.getEntryCaseInsensitive("Mini")); // Add a full stream, delete a full stream @@ -1817,7 +1817,7 @@ final class TestPOIFSStream { main4096[4095] = -11; testDir.createDocument("Normal4096", new ByteArrayInputStream(main4096)); - root.getEntry("Tags").delete(); + root.getEntryCaseInsensitive("Tags").delete(); // Write out, re-load @@ -1825,7 +1825,7 @@ final class TestPOIFSStream { // Check it's all there root = fs5.getRoot(); - testDir = (DirectoryEntry) root.getEntry("Testing 123"); + testDir = (DirectoryEntry) root.getEntryCaseInsensitive("Testing 123"); assertEquals(5, root.getEntryCount()); assertThat(root.getEntryNames(), hasItem("Thumbnail")); assertThat(root.getEntryNames(), hasItem("Image")); @@ -1836,19 +1836,19 @@ final class TestPOIFSStream { // Check old and new are there sinf = (SummaryInformation) PropertySetFactory.create(new DocumentInputStream( - (DocumentEntry) root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME))); + (DocumentEntry) root.getEntryCaseInsensitive(SummaryInformation.DEFAULT_STREAM_NAME))); assertEquals(131333, sinf.getOSVersion()); dinf = (DocumentSummaryInformation) PropertySetFactory.create(new DocumentInputStream( - (DocumentEntry) root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME))); + (DocumentEntry) root.getEntryCaseInsensitive(DocumentSummaryInformation.DEFAULT_STREAM_NAME))); assertEquals(131333, dinf.getOSVersion()); - assertContentsMatches(mini, (DocumentEntry) testDir.getEntry("Mini")); - assertContentsMatches(main4096, (DocumentEntry) testDir.getEntry("Normal4096")); + assertContentsMatches(mini, (DocumentEntry) testDir.getEntryCaseInsensitive("Mini")); + assertContentsMatches(main4096, (DocumentEntry) testDir.getEntryCaseInsensitive("Normal4096")); // Delete a directory, and add one more - testDir.getEntry("Testing 456").delete(); + testDir.getEntryCaseInsensitive("Testing 456").delete(); testDir.createDirectory("Testing ABC"); @@ -1857,7 +1857,7 @@ final class TestPOIFSStream { // Check root = fs6.getRoot(); - testDir = (DirectoryEntry) root.getEntry("Testing 123"); + testDir = (DirectoryEntry) root.getEntryCaseInsensitive("Testing 123"); assertEquals(5, root.getEntryCount()); assertThat(root.getEntryNames(), hasItem("Thumbnail")); @@ -1881,7 +1881,7 @@ final class TestPOIFSStream { try (POIFSFileSystem fs7 = writeOutAndReadBack(fs6)) { root = fs7.getRoot(); - testDir = (DirectoryEntry) root.getEntry("Testing 123"); + testDir = (DirectoryEntry) root.getEntryCaseInsensitive("Testing 123"); assertEquals(5, root.getEntryCount()); assertThat(root.getEntryNames(), hasItem("Thumbnail")); @@ -1897,13 +1897,13 @@ final class TestPOIFSStream { assertThat(testDir.getEntryNames(), hasItem("Testing 789")); assertThat(testDir.getEntryNames(), hasItem("Testing ABC")); - assertContentsMatches(mini, (DocumentEntry) testDir.getEntry("Mini")); - assertContentsMatches(mini2, (DocumentEntry) testDir.getEntry("Mini2")); - assertContentsMatches(main4096, (DocumentEntry) testDir.getEntry("Normal4096")); + assertContentsMatches(mini, (DocumentEntry) testDir.getEntryCaseInsensitive("Mini")); + assertContentsMatches(mini2, (DocumentEntry) testDir.getEntryCaseInsensitive("Mini2")); + assertContentsMatches(main4096, (DocumentEntry) testDir.getEntryCaseInsensitive("Normal4096")); // Delete a mini stream, add one more - testDir.getEntry("Mini").delete(); + testDir.getEntryCaseInsensitive("Mini").delete(); byte[] mini3 = new byte[]{42, 0, 42, 0, 42, 0, 42}; testDir.createDocument("Mini3", new ByteArrayInputStream(mini3)); @@ -1913,7 +1913,7 @@ final class TestPOIFSStream { try (POIFSFileSystem fs8 = writeOutAndReadBack(fs7)) { root = fs8.getRoot(); - testDir = (DirectoryEntry) root.getEntry("Testing 123"); + testDir = (DirectoryEntry) root.getEntryCaseInsensitive("Testing 123"); assertEquals(5, root.getEntryCount()); assertThat(root.getEntryNames(), hasItem("Thumbnail")); @@ -1929,19 +1929,19 @@ final class TestPOIFSStream { assertThat(testDir.getEntryNames(), hasItem("Testing 789")); assertThat(testDir.getEntryNames(), hasItem("Testing ABC")); - assertContentsMatches(mini2, (DocumentEntry) testDir.getEntry("Mini2")); - assertContentsMatches(mini3, (DocumentEntry) testDir.getEntry("Mini3")); - assertContentsMatches(main4096, (DocumentEntry) testDir.getEntry("Normal4096")); + assertContentsMatches(mini2, (DocumentEntry) testDir.getEntryCaseInsensitive("Mini2")); + assertContentsMatches(mini3, (DocumentEntry) testDir.getEntryCaseInsensitive("Mini3")); + assertContentsMatches(main4096, (DocumentEntry) testDir.getEntryCaseInsensitive("Normal4096")); // Change some existing streams - POIFSDocument mini2Doc = new POIFSDocument((DocumentNode) testDir.getEntry("Mini2")); + POIFSDocument mini2Doc = new POIFSDocument((DocumentNode) testDir.getEntryCaseInsensitive("Mini2")); mini2Doc.replaceContents(new ByteArrayInputStream(mini)); byte[] main4106 = new byte[4106]; main4106[0] = 41; main4106[4105] = 42; - POIFSDocument mainDoc = new POIFSDocument((DocumentNode) testDir.getEntry("Normal4096")); + POIFSDocument mainDoc = new POIFSDocument((DocumentNode) testDir.getEntryCaseInsensitive("Normal4096")); mainDoc.replaceContents(new ByteArrayInputStream(main4106)); @@ -1949,7 +1949,7 @@ final class TestPOIFSStream { try (POIFSFileSystem fs9 = writeOutAndReadBack(fs8)) { root = fs9.getRoot(); - testDir = (DirectoryEntry) root.getEntry("Testing 123"); + testDir = (DirectoryEntry) root.getEntryCaseInsensitive("Testing 123"); assertEquals(5, root.getEntryCount()); assertThat(root.getEntryNames(), hasItem("Thumbnail")); @@ -1965,9 +1965,9 @@ final class TestPOIFSStream { assertThat(testDir.getEntryNames(), hasItem("Testing 789")); assertThat(testDir.getEntryNames(), hasItem("Testing ABC")); - assertContentsMatches(mini, (DocumentEntry) testDir.getEntry("Mini2")); - assertContentsMatches(mini3, (DocumentEntry) testDir.getEntry("Mini3")); - assertContentsMatches(main4106, (DocumentEntry) testDir.getEntry("Normal4096")); + assertContentsMatches(mini, (DocumentEntry) testDir.getEntryCaseInsensitive("Mini2")); + assertContentsMatches(mini3, (DocumentEntry) testDir.getEntryCaseInsensitive("Mini3")); + assertContentsMatches(main4106, (DocumentEntry) testDir.getEntryCaseInsensitive("Normal4096")); } } } @@ -2165,16 +2165,16 @@ final class TestPOIFSStream { // Check some data assertEquals(1, fs5.getRoot().getEntryCount()); - testDir = (DirectoryEntry) fs5.getRoot().getEntry("Test Directory"); + testDir = (DirectoryEntry) fs5.getRoot().getEntryCaseInsensitive("Test Directory"); assertEquals(3, testDir.getEntryCount()); - DocumentEntry miniDoc = (DocumentEntry) testDir.getEntry("Mini"); + DocumentEntry miniDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("Mini"); assertContentsMatches(mini, miniDoc); - DocumentEntry normDoc = (DocumentEntry) testDir.getEntry("Normal4096"); + DocumentEntry normDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("Normal4096"); assertContentsMatches(main4096, normDoc); - normDoc = (DocumentEntry) testDir.getEntry("Normal5124"); + normDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("Normal5124"); assertContentsMatches(main5124, normDoc); @@ -2278,10 +2278,10 @@ final class TestPOIFSStream { // Check that we can read the right data pre-write - DocumentEntry miniDoc = (DocumentEntry) testDir.getEntry("Mini"); + DocumentEntry miniDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("Mini"); assertContentsMatches(mini, miniDoc); - DocumentEntry normDoc = (DocumentEntry) testDir.getEntry("Normal4096"); + DocumentEntry normDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("Normal4096"); assertContentsMatches(main4096, normDoc); @@ -2319,16 +2319,16 @@ final class TestPOIFSStream { DirectoryEntry fsRoot = fs2.getRoot(); assertEquals(1, fsRoot.getEntryCount()); - parentDir = (DirectoryEntry) fsRoot.getEntry("Parent Directory"); + parentDir = (DirectoryEntry) fsRoot.getEntryCaseInsensitive("Parent Directory"); assertEquals(1, parentDir.getEntryCount()); - testDir = (DirectoryEntry) parentDir.getEntry("Test Directory"); + testDir = (DirectoryEntry) parentDir.getEntryCaseInsensitive("Test Directory"); assertEquals(2, testDir.getEntryCount()); - miniDoc = (DocumentEntry) testDir.getEntry("Mini"); + miniDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("Mini"); assertContentsMatches(mini, miniDoc); - normDoc = (DocumentEntry) testDir.getEntry("Normal4096"); + normDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("Normal4096"); assertContentsMatches(main4096, normDoc); @@ -2347,19 +2347,19 @@ final class TestPOIFSStream { fsRoot = fs3.getRoot(); assertEquals(1, fsRoot.getEntryCount()); - parentDir = (DirectoryEntry) fsRoot.getEntry("Parent Directory"); + parentDir = (DirectoryEntry) fsRoot.getEntryCaseInsensitive("Parent Directory"); assertEquals(1, parentDir.getEntryCount()); - testDir = (DirectoryEntry) parentDir.getEntry("Test Directory"); + testDir = (DirectoryEntry) parentDir.getEntryCaseInsensitive("Test Directory"); assertEquals(4, testDir.getEntryCount()); - miniDoc = (DocumentEntry) testDir.getEntry("Mini"); + miniDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("Mini"); assertContentsMatches(mini, miniDoc); - miniDoc = (DocumentEntry) testDir.getEntry("Mini2"); + miniDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("Mini2"); assertContentsMatches(mini2, miniDoc); - normDoc = (DocumentEntry) testDir.getEntry("Normal4106"); + normDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("Normal4106"); assertContentsMatches(main4106, normDoc); } } @@ -2372,15 +2372,15 @@ final class TestPOIFSStream { DirectoryNode testDir = fs.getRoot(); assertEquals(3, testDir.getEntryCount()); - DocumentEntry entry = (DocumentEntry) testDir.getEntry("test-zero-1"); + DocumentEntry entry = (DocumentEntry) testDir.getEntryCaseInsensitive("test-zero-1"); assertNotNull(entry); assertEquals(0, entry.getSize()); - entry = (DocumentEntry) testDir.getEntry("test-zero-2"); + entry = (DocumentEntry) testDir.getEntryCaseInsensitive("test-zero-2"); assertNotNull(entry); assertEquals(0, entry.getSize()); - entry = (DocumentEntry) testDir.getEntry("test-zero-3"); + entry = (DocumentEntry) testDir.getEntryCaseInsensitive("test-zero-3"); assertNotNull(entry); assertEquals(0, entry.getSize()); @@ -2419,19 +2419,19 @@ final class TestPOIFSStream { testDir.createDocument("empty-3", new ByteArrayInputStream(empty)); // Check - miniDoc = (DocumentEntry) testDir.getEntry("Mini2"); + miniDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("Mini2"); assertContentsMatches(mini2, miniDoc); - normDoc = (DocumentEntry) testDir.getEntry("Normal4106"); + normDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("Normal4106"); assertContentsMatches(main4106, normDoc); - emptyDoc = (DocumentEntry) testDir.getEntry("empty-1"); + emptyDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("empty-1"); assertContentsMatches(empty, emptyDoc); - emptyDoc = (DocumentEntry) testDir.getEntry("empty-2"); + emptyDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("empty-2"); assertContentsMatches(empty, emptyDoc); - emptyDoc = (DocumentEntry) testDir.getEntry("empty-3"); + emptyDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("empty-3"); assertContentsMatches(empty, emptyDoc); // Look at the properties entry, and check the empty ones @@ -2469,19 +2469,19 @@ final class TestPOIFSStream { try (POIFSFileSystem fs2 = writeOutAndReadBack(fs1)) { testDir = fs2.getRoot(); - miniDoc = (DocumentEntry) testDir.getEntry("Mini2"); + miniDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("Mini2"); assertContentsMatches(mini2, miniDoc); - normDoc = (DocumentEntry) testDir.getEntry("Normal4106"); + normDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("Normal4106"); assertContentsMatches(main4106, normDoc); - emptyDoc = (DocumentEntry) testDir.getEntry("empty-1"); + emptyDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("empty-1"); assertContentsMatches(empty, emptyDoc); - emptyDoc = (DocumentEntry) testDir.getEntry("empty-2"); + emptyDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("empty-2"); assertContentsMatches(empty, emptyDoc); - emptyDoc = (DocumentEntry) testDir.getEntry("empty-3"); + emptyDoc = (DocumentEntry) testDir.getEntryCaseInsensitive("empty-3"); assertContentsMatches(empty, emptyDoc); // Check that a mini-stream was assigned, with one block used @@ -2528,7 +2528,7 @@ final class TestPOIFSStream { assertEquals(5, src.getRoot().getEntryCount()); // Grab the VBA project root - DirectoryEntry vbaProj = (DirectoryEntry) src.getRoot().getEntry("_VBA_PROJECT_CUR"); + DirectoryEntry vbaProj = (DirectoryEntry) src.getRoot().getEntryCaseInsensitive("_VBA_PROJECT_CUR"); assertEquals(3, vbaProj.getEntryCount()); // Can't delete yet, has stuff assertFalse(vbaProj.delete()); @@ -2550,7 +2550,7 @@ final class TestPOIFSStream { DirectoryEntry dir = (DirectoryEntry) entry; String[] names = dir.getEntryNames().toArray(new String[dir.getEntryCount()]); for (String name : names) { - Entry ce = dir.getEntry(name); + Entry ce = dir.getEntryCaseInsensitive(name); _recursiveDeletee(ce); } assertTrue(dir.delete()); @@ -2602,7 +2602,7 @@ final class TestPOIFSStream { // Extend it past the 2gb mark try (POIFSFileSystem fs = new POIFSFileSystem(big, false)) { for (int i = 0; i < 19; i++) { - entry = (DocumentEntry) fs.getRoot().getEntry("Entry" + i); + entry = (DocumentEntry) fs.getRoot().getEntryCaseInsensitive("Entry" + i); assertNotNull(entry); assertEquals(s100mb, entry.getSize()); } @@ -2614,11 +2614,11 @@ final class TestPOIFSStream { // Check it still works try (POIFSFileSystem fs = new POIFSFileSystem(big, false)) { for (int i = 0; i < 19; i++) { - entry = (DocumentEntry) fs.getRoot().getEntry("Entry" + i); + entry = (DocumentEntry) fs.getRoot().getEntryCaseInsensitive("Entry" + i); assertNotNull(entry); assertEquals(s100mb, entry.getSize()); } - entry = (DocumentEntry) fs.getRoot().getEntry("Bigger"); + entry = (DocumentEntry) fs.getRoot().getEntryCaseInsensitive("Bigger"); assertNotNull(entry); assertEquals(s512mb, entry.getSize()); } @@ -2637,7 +2637,7 @@ final class TestPOIFSStream { // Read it try (POIFSFileSystem fs = new POIFSFileSystem(big, false)) { for (int i = 0; i < 4; i++) { - entry = (DocumentEntry) fs.getRoot().getEntry("Entry" + i); + entry = (DocumentEntry) fs.getRoot().getEntryCaseInsensitive("Entry" + i); assertNotNull(entry); assertEquals(s512mb, entry.getSize()); } @@ -2650,7 +2650,7 @@ final class TestPOIFSStream { // Check it worked try (POIFSFileSystem fs = new POIFSFileSystem(big, false)) { for (int i = 0; i < 5; i++) { - entry = (DocumentEntry) fs.getRoot().getEntry("Entry" + i); + entry = (DocumentEntry) fs.getRoot().getEntryCaseInsensitive("Entry" + i); assertNotNull(entry); assertEquals(s512mb, entry.getSize()); } diff --git a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPropertySorter.java b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPropertySorter.java index 7c674b5b69..4b12050ba2 100644 --- a/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPropertySorter.java +++ b/poi/src/test/java/org/apache/poi/poifs/filesystem/TestPropertySorter.java @@ -116,9 +116,9 @@ final class TestPropertySorter { String VBA = "VBA"; DirectoryEntry root = fs.getRoot(); - DirectoryEntry vba_project = (DirectoryEntry)root.getEntry(_VBA_PROJECT_CUR); + DirectoryEntry vba_project = (DirectoryEntry)root.getEntryCaseInsensitive(_VBA_PROJECT_CUR); - DirectoryNode vba = (DirectoryNode)vba_project.getEntry(VBA); + DirectoryNode vba = (DirectoryNode)vba_project.getEntryCaseInsensitive(VBA); DirectoryProperty p = (DirectoryProperty)vba.getProperty(); List lst = new ArrayList<>(); diff --git a/test-data/document/47950_lower.doc b/test-data/document/47950_lower.doc new file mode 100644 index 0000000000000000000000000000000000000000..f9f2c6ed12224ca3f671c37cf259248d88364f2e GIT binary patch literal 27136 zcmeHQ2V7J~x1U`)f-FU(s4R#|48o!as6nZUG-+0B3oJ!p7g4iIrWOo`}8VF z3+Yc}$UBJ=k#82yf-svt=MaMDh<6f+gpP(FBma*WcnfvK>nGEA9pymdHCF&A0+ayC zfHnZkrwY0)Kn(!508s~M05kzwfOY_FKzo1=Ko_6~z_J}ccLa0-7y!5cLx2$g(~UuQ z0dxg)1DF8519S&qx+&-$05gC&fCsPu^aNl!gRkd+etsG5zMi{(17}f01plJpSriZ< z=qNG`o~ADsZ6e2lM~@PGhsY~QzYv8|69YeHsTV}XH6{cRK6vGSEZY~wDHHa4|5%AH zDI|-T@Z|+!L3s}#;n4oSBW=MyK12A<{8Ilake7`wLy)P!eiR9UemW`2 z{8115Bjfnq{!;(?XtuHaazspdjeu)_*FFsHf?%pn7!wWWB8X{SO#TM{oj>s3vgKb_ z9~Gs^XJ7>rU!TJin4tO`TC>p~%C?sFe-WPn?WOJFItCqXO&|P%JT1$H!i1pLO1{}fCsPxFlpb8 zmyf+yjKTd7R~h2vDoeaUk9B2}aV{*`2p1(;p^Lh#7<4pf$VNN~8UI|u2CdS#YJlq< zp6^!)!XXc?X=nt=z*>mbwp7xAIJ#<6_V}PbW)tl;i4(Es)=D-LC!&H2%pe?CMRtO< zkYHGam<+2kxI*Pctx@nv2+W@IVa7fb;s#Rd6VX%|A6TvULy}E=-do|xs}MiPD_!5= zwy1Ll(jH$imRIBnOIapd8jyn+K1Q>tHE$C#ky|G@hHKG{HRH)EPL$Ne2e!f1godYs?1NP&2aSxiLu?v&G>#XOF4 zgUg%v`#oIOXW1!sc|7ODk`r5I7M@&VtX*;~D}Cte2KNho4jEkSaMSC(8aDR38+Ft` zA*Xot`gGSlwGQ7KSLqKLlXlyB$n~FxEu5{V^8-IkZFOB<{t*-F`Ei36uJuWq@gOq9 zJxwhMpSuuu1%(lzdFT-&pgy>IGNEljbwTjF^2zRZEW9Y@$cz5i;p@tx%T zc>}CGce^?&#%C8Uy;Pm?YG8@BgW0J=-RjM@eZO$?*^xzluXOi58Y}31zIVngZf%>N zG>Z4CEF5<(gsa=*K|#Nb3#-enj0`_gz9ehOOslbHJda7V#@7#cqX~~Y}TW66< zlh{xr{WATkvLPqrl@BW>YqCzCWI6<$FX3EpbuP0EFpf=6nKbUI z!Rn2=6;|#S>$QEZT9406$|#X!7xT_+9C9pnkLi79S)uiE_po~bn={Ps`W{Wr5bV6v zsWj){t1EAzDSvI~#Az$FQ_yuuXuV;TE^}?pItM~85TmN=j>+(7`)sd#_6;u-iXU!Jm*32|b z*Uz}&(%~1=@X8bI9z2fGDcQeR^Y-AAV((d!-+6wX=TSCS|G7AXm317w(v~Hx>-aHR@CElWI4ru9O_D_tH`=C92aOCs|aa zdc-=-A04)8dB)4xT8hg4ahucfb$?vHX2Y5dN5u_c?ngDx$nggko8RvKs*~qDQ|{nv zH3s#EH0fY@@it))GMV|+!vf` zmo;znaLL(w!R%u(W1f{1+vkU+`TTroO4M6DyZb#eeV<+Gn=^Wod}<}fbM2&kldoL$ zU!i-22*!2HE31Do@OqK{pVljFp7~uqQ8dwOdqGyhvnl@Lo!jiO*UisM*kfhAF2cV+ zUhwjUM*i3vVZ(o4`J-y0$>3kz9{J=PIKOt2)%>4y$|o0D?^+?8HEa73JA2D}=hF`8 z>~qRY%+cxC>y}&`+sAnDoszJ`L7|G?HyxI%*gSvXqGMl?X2NH$bgN1ehRM9!HN-jg zVkc*R9o-9w?Rn~MZiz|V=B?kBRe4+C=X_S5*gqarU$4pzDcEEi`{Rr1tJiOhTG1tU z(bCf8Ga4>hOOCv`@cMPG!R@0jt;(jWo4da$8<#)*^@&Z-eAT*{xlejmzAJanxDBzA z`f&paB13OihK?_KZTxFdzryrej@renj&GjFjq})IU>M+9ZM@k|$>*?5-PE9<&1%~h z7%5~fjOf?@LGpyrg)^1~E{Zh2qdB;Po`KUoxtk$BS?Nw4RXO{{X`VQCX~NU9uZ|zL zb$WC>XKI@+D_8YfrWIv6X-By8wJp<}yp6mUXqwvA>+1(r+mvfMm>zz*%rIom;%yBH zF&<9qyFOkvyPe0}QnQ7}%zfM2*W?P;y*)8@nfKKlWiO8pEIK+nBYviV@9Cc!N}aY` zOUp_Mn4mXPt>mP0mi2u{&8zAfKXeQ@b;L7nZe&S^D4RW%bqdMBH-)#;FJ2oMHTYMv z4Ko&4XkHJ#J1pVOrMXX1jC=0ew8$dCq;|>b=wl6QX3fu-SR>;)Ebq0&v6Y9-f0Iw* z7O!2NNW2T&4;HU#;AP**wNC4tFlI;a{1d|x%PWuTc04;cbnc5zziMsRLIR(if7n*u zW929-bC=sm++EcH!^f8onzDOmm28_wEBwUS>$^29*z0g$zT<&8=iWsdK6m%l=$!BR z2P>w0|1<^HG1ba(j(t0%XfmH2t#jkhYcxrLb zJgJA?s)OeC^5aIzYaIUWkFjNS>N!>>?CnXZrz6w+Is0yoTaa;Q=PzA752ehys4a|p zdUC?_fTg3av3k_?zbwgYnBDg7oB6Ajysjv&>nHqWSXN#@dUp3U)n;|pyCN5j@mTac zZsr>g4}FiNomD0W^$9Gmv$VEdEGc*vHmv-d^@cM$f4sYW+4IfC2OkFo7q3veSfX{d zO#lVh+oxVv-E~Hk>+_AJ@dm7Oz3kg-uUNk^=FUvz)dOpWuIO{EuxM_F zFx{kHujEp^%^kjTpMNUfMi&zWbWZ6YB%wR_(eP?r0mjLDMU1xFJ70c-ghc_>$6 z9dUEm?+-Ia1+Xqf?J1PWRY-cQS}=;G&Y3fm z)xBb-`%W4&?T5*ErkBhr!xkl|3$2tQbjvFiDt3wwIlp6=x#QiP`L|3*PdM+pz4Wzx zXgkZ_b8nxxlb0`l=$D&zn!S8WkN1msnX|Zi!WmAQYOJhd;7h%9PCo}*v7uhkx>cL+ zU003WaAs+gVVR55nq!kMlw{ev8$amOWm56*6X(k9G&eX}=GOK#PDomLv+K4MNsBw! zluzl|X>pC$TA}r@G#M!wtm%O161OT*bupE@7gVV$b^j$^-IXq7-v7^fIB z)$6z2x||r@mEE$8-f1geG<~vGv^82qP_!ovv zSF)Sa)?w&)kFBFFTkg@*oxfseLx7>6PvvQEyw)}dgqVu|)?y{%+^YV`0e&2K!y9aFcY^|FM*_z2mI=x(ALPpjAz6Z2m?hyVZsnwqoIBSd)OFp#nF6W z5If!{YUJj#O~$pr&KabLczQD}5@WM6Z0aUgU$`C>Csq(BI1 z!J?=Lel(m$g_s9L@uz~}h;Z|sJf4+#1V2n@#0?0sur&&gwlLyG$3Q4(B7_1$dSYBp zjDt|nL$MmA}Skf_;bWCqLrZ*j9MaNhfaYMtygcG4f zsEoM5qHq^!1RXLm?~m+3M-}%K!tid55RS=A*5t$kuoU0Mp8WSpB zspkDi8qR596J@F#%)e5V!~71AsL>ct?R0}?_>wj?xQV&|9B{~KbVDR?R3x%8xM6#M z42$xuUIT`x5az%Vh5%V=bN64*F%7qUf0zOzVXO`{q`i-cAn34*-zlQ*bC)O&uBYOV zWVC>S=@L6u9E=JlVh=23i50@DND$Glf+@r7j{raz-)sEW-JKlWkz{#BQMKFY1O+u z%x8pwCoE$vEu$uf1!Sl)_huNAqLwvwr1FP>FDy%lqjoYYj(S(X3CKe>iIcoJ(H-~Z zqimw?WI{&5YzminKp7$Id<=z}5@I848{9Dj-n3?>tT+z44PJ5-nDVKRygkt!M|mh8 z+86|7qrpNL*pbeKguofjhS&)A^KyB`ygj@R;~l|1Tn#muuWH+eHteCDU_(|8uBbfl zL)Vq6ARHi(666Q3gp^rqG45s!g)}3$oh=mObVv=(Q{r4aA^nygP(WZZ3DNzgBfX3<|2giG8g zEVp=dyiSVb4Nh!)TomoRFhQwCqDGXAA$$*R1lV62+Zyl{h_?m)2Ia3}h__J-;lPX! z{Q@B*22v5Uq{2t(tW26O{@w=VCID+Ikv#-gZDZzwVK&T@rkF%+I?F=*i@QlurB zBf|jAKy}(N;zpFd{9tV;LpoIKBXJ8Q2B6IJO=6-BR{68S$p`&8frTI27K;t zbxQ?*$_DZ|{jf1#OFa_o;M>Q)@$>m5+8FZJLf7*E6wH7R%_umJh4PIq;H*h#9%#Q! zDbf%f-iBA-a;+yv^+Gplj z-ru#~S{-P6G*9&XR@ncBHE+xH_n#O#zM+v9x*ToS8F;{3bSG#YXuSVW=zR1qg%ltj zJ9zXtola%`2M)Ad+7x}g&=201G|#lA{nO{Prpvdc>3l6UeLvE=weoblI@C-0s-j~) zu3P${&uO0N^VT$NmA;NG_2<%C=KrV8>Fd>6y<3Z?>-)93HGBAO9sw`V?Xbkz7w&pF zq5(%GS#?=zxcaqjnEcpRTpmTDnoH3xwUif<+drR3m0F`8%HDl!8!oWKi zBg5ZN_)Bx}=BSvvsrJ>7P|mItMe=>O?CUr>nF$H_H(xM48Gt2M18^R88vrH}2;45z z^2JHexUO;ufCKpo0K95Q9RTOERlo?&YUzN+kqz!K#gVuZXzY1-fyPCf(V%hWAP6)E zbU0|-PZtdu{o@=R&J&_}#Jx<1Pw{(2Wp?tt;tGW|7$8rejr;O+X4Pd4H!lJ_klqo71Vi;i< zU>IN+U>IN+U>IN+U>IN+U>IN+U>IN+_}4JNg8y@h3@pCmuGE(Q?*=ZkvS~e=+8Ef! rx(ECwv=`T@af2YWZtvlXX%Iz??lEjer<>W3x;|Nx{xx*{>l*SuETSyXHR1sg^Idlw6WC5R|u zMFbPY5>af3DA*0CNI*1}edpZeDiSf6_dS2_<=vC~@0mF>bI#1UbMKwDSb9;lYRf*I zYSM}Z5h?OstUzR2$XO6(({Tf3T00 zXip(&%!Ds5AT#0z)&occ5l94IdF=@H@fpH*W_#@`L0&e#41q>~_hU#9aReSnrjSUe z2i}MFk`CBMkK=p0z4mocd2{<^h%aR|61;%-ei&E}rs{-}SP}+dA?9y`jQ)ZDyQ8iT z_FK37>*`|-_VIpV+mYI+<|pFsG1hFKMI4}oktCXULN5saBwu?XYA_;_Se9JdQwHNDG}+rA5GFfkQUp zLCC}xVm5H4=2dgt@9_ArOArBha8E-mNDB5sG`6RcF2un_lhVfr{yCkf_aiwHJ8r#r z3+#d@;RZ7h2X>JiVJ{>Yb|I#~?hNiwc~N^5d=dhy=X_YP4+Yr}YJWnqU*ZG16@Q5L z6Q2)Sc(O_@_IJ3g>fD8N##fBRHCe(^l!}l9WI)14F`L@+HX@U_4dRoy7u{Slo~#_D zhfCbRo`~A3VN>lV#LHDmS_6E8Ur&AVq!3&j9X^k8y|+#tMY76a1z}3q<2g z;vysVq@D99=5d^woZlus=;N{>*H*sAlewptp58jE@XT66&5|3rnZw^Sxn1_N&*ExE z7?+zjZ5ntl=D40*Uh$d@nJ#&rCHxAak&0K>R?XS zkv7jByk28?H}$}g!ImC-TpZ*R_ZKd^Qk(U9NQtJs$=Sob8cnu;zi7*aQAK{QwR0Yi z7xcT-FY7k9zQa#y#W_lgCR_~RYWI0~V&JAlwH4P!MI5VKn!9wC<@oa+C&d~Q8wWpD zFFPMUCLTP3XAVB~SH`u>M}^=gOP1uk!Gst=gvitcuSqEv!;5)J3!cwAo_J}t_vK=( z9#c&-QXNdU%_h}G@u3E~6}mMQo~LCMkIE-)f8Mmy=6&|!*VQW?aW&WNk}baLF!)?( z^;DY^@pDV&ZO`l>KPE1E{`td&-du70!M#MQ-|lE!UGJ(q%6NmE zaVSvQ@#{9+tYeY(@bCvjRO2bQSc8FohGJ-hqW)OkPWRdTQ8eScN| zxpC$A!-nBDi-(SQT-Nm6U8kDwdn&T6KVSKx0ZSXJ;H$bHj&R@zsYSIVO)$f1*N$?H z(zW6gbbcH^viA7Cpc+-(G^v_SRxdiFEi)ME;`;RRU6am+f}!~a{TqGKZAUkhlH-kD z8p@?adB&3zv#NCWc*g}}!&a}zdNoHwUU5vqmW%@JA2+PsxOU@lQB#=ParN^u{9(nW zcY43><}u%xJM2cCUgOctl`n1dz16s9)o#^gj(jyOfAG8e9d9mEUAj-Me$fqk<-yDP zR*oK{?l5x5T}{`?>=R40Qqq!KyJgFC**N$1n(UufyX56*rJZV0(@4Bod}*Q5zUw1; zzk7PPzT>=ej*5A_?Z-0x0$uF`6DN<-KjnA8sL6v9`6|b=(BsXkoeeh0NlAJ-KMoVW zo>VdITIn^ng=ahE&L2BMeBpjD`()g>=Ox8<1z{OJKVO*|^G?V1LEmiO=T`>gjomDp zUd{1XH+kQbYuCrD)V@Xp6S^L$XnZ-Oyh!&?t5w#|{jQ!an&h?PL~hdasbeNOb=YgC zU2r66ucg)c$T25m1+Q+Z6^y?bHsbeHKPo314g1ygu}|K?OY1gUF8E2Sa!Qfa?v=vX zvv(Y`wX?W?DdV8lKF93jJgu(gw`CI8K8C~YmV_k_4VCx4Wxqnn`o&9UExW1=BR+eT zYfXkQOzQn^Pp9~@Zcbygv@a)j=Bc{6Ca3h8zhQfB^&PpN3t0W*|9DtiUb8>s#AciL zA79p9FTXu{Wsm&D%Su3zq-PgipE_mZ`1n-bv<^L1tsb~sBgT00&IqR)Tc#Ax$bPYIr%p+l5bV-*O>%G+ta;d?$ zgm*H_ZVZVT_N&RpnG4O-%Y*OvC*8d=?`fK0-+h}GnZs{&vMJo+bt{sI_X)Q{#jBfm`|svkWpqy(w=;ObY5(NP>QmZXFANKv_p;ls z8XLEgz~`49b(D2qHQLhD`A!OVcWuCkiIqdA?%7o%-Qn>{KhgdTy_y#0*dJWraB%L$ z_p$mf+`QGg7r6YvimN;@UCw1(tzv@1fG+C`rPwyyQ;W-t7O-QrP9FEE@lM*q-jO|T z;P}j2^>+l%%nq5R^wC*;$ka}D!YEm_qu>28zM?@j&(es!BPIP@bjBFYzFQL(X5HQO zOHYr(X|u~Tg$d8jgwF_AHueUqPs5ui(e$ndh714>%OeJ(v+b7ft3vwRyIq-C!UA-S6;N*cz)N9_jW9Qv8DLX zlc3<@l`3T=8W%b=^b4;_Q=ZXqqu2QUjoPX%Gh#VtQ!=|{qvlQ11 zsT;ns|Bb?;d0oP^Q_Nq>q&2iBx%`mB zdt}#-5_EFbtjP#3=$P1h?UqT60ST*jUypFG3Eimfl{-S89}&F#Ms#Y{#m+0!8b)^h z=^=NE=S#bh5d%iv^8fu&_UHiCm6*MSQu%TzPn1uLW~p-KPVZvzXimNF!`}~2%QGLm zJ#&P1SuzRDd8FzUH^X=GxamJkIbwXpq&jSIlB&>BAyT`tYLR@m#E?rn{Y@S2?JBr! zJU0B2?~c+pcA=dte$T&i`tFee*~7owvQ;SlF-bv><8Org}4uP+9GC2e7 zZAAJyMeA2@xnHgvzw!LC82t)o$F(P?TrSDAb2EI{t;giz5vMO!+Ny7Ku*k0;V3?G$ z>Q>L~D^r$qv96rjx7(6BuXREz{}mbgUC-2w%8q`&>zBPM{>viR&z?D*+-a4r{+?sE zaCnVCP?#VeH_hv}J=&Z&?Nz;U4c==imKi@?7qu-`Nl>$Jhw8fF8s=+5qBouu4fwNn z{+!AE2AXSK;g#&+bhIBn(S6(Ks}_58v=^)#-V~rO=-)j|vtQZS-n+t&>|c{td`!vs zM*R$@+Y|d)nccV8Ulg))rr87GZ=y>3&8Z_4cyYqPL$4lpwBu!UT0iQF#=Qp?dtzQj zT+QzKhtzo6r+uA@&it8o_@>O!2mOi;cQqcryFT$&z?GuQp|?kbyVm4Ce7HE$(t7^= zOY=>p*=LkyCzY5CE#)-EdM?XU?sMcFo;&>O2VMD6>gI!xq6?pUJh|BNnbibdn%%T4<1m?K9{-TBaT7P}7|_H1jI3)x!GX9m4quAeGs zJ?{Hhng{-DF$!#5u=P0VV?k{gV79yot=->RQ|m#^M@`p0r->TkwARtO6MWS1JDj3z zS(`6(2`^U}7+c|aE*UZoTK@nK-;y5&!;p$QRS+WzixS!xn3?blxB_8dR8W{O#KvH_ z-;h4m23%1rUl_!Xh!P5H45kZ227?DFEB?SA5Ev2T&X4AT0-Isi`Os z2AzD7NmR5z2x-AlF_HXOh{lAN2F38Ff#S#r)4n{OrD-HTOlZIj2r;uUh=?^a;Ks&5 zC}ML_4)fbXqFS?@I_U<@@FgAU@DTM0Fu)<_&UMaNH(;_7X69}P#MfgU!Ikzuh}ap#A1MKYzHovv63!7u!HNYT<|dT& z4zkj0q&BVF!Fom*Si&+^k}@hXSU`#@bAP5GDQaC~2P%IU*ut`eIB2G_5~z0tM1UT# zNrL$8>E3uYA89kylL;9Gt0`RK4rPRJ-ZT_yN{F?vV{q3Hc+;8~vl2M$4tUFvV9BRS z{O)vboaG^Xs$(dWjRg&1phvP65&|(?iLn+Q;N|m*d3$-E${j#I+zl0}uWH+;I_#jG zphH>)?x-yIhpsDCLAXF7Md%;A6B5s2i}5sTD5M!ccQ%tx&?0rXPKj&rgbZA9P!54% zi3aTQcurRGAi=H(nx!6uk5bx}z7(MzXF3iU8EUr&(q+k>i5~1X)2A@wHBXuMJ;Q`@(zJ9)RiH}@CT9a77 zaKy5|MHm9V;a?&#JXAEb6{gekseniGgMz#Ye_jUkCElEc%7>@oG0@N~{2a$!3;f9% zaytDceC}{}O9_9<2K0CQQFFf5d=%)xx6hd7&u4qMA>^-zq31y;m<1o2(GZV^^35h7 z_K|2m&~`tjNJ6x{EslCy60MKsbi3(17_WfH3Mhv~^_$DL=4cPQP-{J{&dZ7u)siJ|39&3>WF(R!W057%r?t}eu{Hm@^w#x7?3;N&Rx^}Zu>+1%SL&cA-t%|gtOkss z|0N#45h|-MF-r|)4T#3&T)mu9Q*KU`jebtLi~*o~YPyUephph;J&&AHwiZAs6<5s| z`nP!CJ=54Nj?HS71ohDDd@3p@iXD72D0srO;rl$h16K= zR}O-JbAU$x$MbZtz|lUg(cwBF+D2*}#xg!pA`#amDpV+n5`HdE%d%Jp58MxnFbRr^ zjimH_NeBK78ng)$cj6uv7!xIm3XbJ^1_y@)O2$(lw*}B-i-BE3G;x;LGK@ZiCQ-h` z`d}Pan~^ibc!2Q$;{nD4j0YGGFdkq$z<7Z10OJA11B?g$J0AGb{GWaG!qp8Xx}4>! zVg7IYI-3WE9s_WGjPuk`0M5&!0eF^j769k_NdR0U_z8f22X+Mj&$Da*;5>Re0O#*} z0JzzC0D$xTV*u1$0{Gm#zUBOwo+snHTQWc9P&OdiChrEuu^fW>DI*#|1z2gnu-FIz zrHV=h2}6tr7!NQWU_8Khfbjt10mcK22N(}99$-Acc;H{-0T%qrDN?Zcj;B&v|Jw~* zXywQKZ0cZOf2%(5n^1GEWAgz)YTw@77t=sQ&F(R5LZ_QplZO7elm9jD`qwq&zW{Nc B0tNs8 literal 0 HcmV?d00001 diff --git a/test-data/document/47950_upper.doc b/test-data/document/47950_upper.doc new file mode 100644 index 0000000000000000000000000000000000000000..b09ec382cc040733bbb7f47be103e1b21df8b436 GIT binary patch literal 27136 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