From 818bc296963de5db06ea152c94184a4c8c8ec9de Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Wed, 4 Aug 2010 17:08:39 +0000 Subject: [PATCH] Fix bug #47990 - Support for .msg attachments within a MAPIMessage .msg git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@982331 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/status.xml | 1 + .../poi/poifs/filesystem/DirectoryNode.java | 9 +++ .../poi/hsmf/datatypes/AttachmentChunks.java | 10 ++- .../poi/hsmf/datatypes/DirectoryChunk.java | 68 ++++++++++++++++++ .../org/apache/poi/hsmf/datatypes/Types.java | 1 + .../poi/hsmf/parsers/POIFSChunkParser.java | 32 ++++++--- .../poi/hsmf/TestFileWithAttachmentsRead.java | 58 ++++++++++++--- test-data/hsmf/attachment_msg_pdf.msg | Bin 0 -> 71680 bytes 8 files changed, 159 insertions(+), 20 deletions(-) create mode 100644 src/scratchpad/src/org/apache/poi/hsmf/datatypes/DirectoryChunk.java create mode 100644 test-data/hsmf/attachment_msg_pdf.msg diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 040594cecf..e1883e98d9 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -34,6 +34,7 @@ + 47990 - Support for .msg attachments within a MAPIMessage .msg Improve handling and warnings when closing OPCPackage objects 49702 - Correct XSSFWorkbook.getNumCellStyles to check the right styles list 49690 - Add WorkbookUtil, which provies a way of generating valid sheet names diff --git a/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java b/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java index cb61e9e042..8d79ef80a8 100644 --- a/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java +++ b/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java @@ -110,6 +110,15 @@ public class DirectoryNode return _path; } + /** + * @return the filesystem that this belongs to + */ + + public POIFSFileSystem getFileSystem() + { + return _filesystem; + } + /** * open a document in the directory's entry's list of entries * diff --git a/src/scratchpad/src/org/apache/poi/hsmf/datatypes/AttachmentChunks.java b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/AttachmentChunks.java index 5bc00c4b0f..106a1c4b2d 100644 --- a/src/scratchpad/src/org/apache/poi/hsmf/datatypes/AttachmentChunks.java +++ b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/AttachmentChunks.java @@ -42,6 +42,8 @@ public class AttachmentChunks implements ChunkGroup { public StringChunk attachFileName; public StringChunk attachLongFileName; public StringChunk attachMimeTag; + public DirectoryChunk attachmentDirectory; + /** * This is in WMF Format. You'll probably want to pass it * to Apache Batik to turn it into a SVG that you can @@ -79,7 +81,13 @@ public class AttachmentChunks implements ChunkGroup { public void record(Chunk chunk) { switch(chunk.getChunkId()) { case ATTACH_DATA: - attachData = (ByteChunk)chunk; + if(chunk instanceof ByteChunk) { + attachData = (ByteChunk)chunk; + } else if(chunk instanceof DirectoryChunk) { + attachmentDirectory = (DirectoryChunk)chunk; + } else { + System.err.println("Unexpected data chunk of type " + chunk); + } break; case ATTACH_EXTENSION: attachExtension = (StringChunk)chunk; diff --git a/src/scratchpad/src/org/apache/poi/hsmf/datatypes/DirectoryChunk.java b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/DirectoryChunk.java new file mode 100644 index 0000000000..647be0c25b --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/DirectoryChunk.java @@ -0,0 +1,68 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hsmf.datatypes; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.poi.hsmf.MAPIMessage; +import org.apache.poi.poifs.filesystem.DirectoryNode; + +/** + * A Chunk that is just a placeholder in the + * MAPIMessage directory structure, which + * contains children. + * This is most commonly used with nested + * MAPIMessages + */ +public class DirectoryChunk extends Chunk { + private DirectoryNode dir; + + public DirectoryChunk(DirectoryNode dir, String namePrefix, int chunkId, int type) { + super(namePrefix, chunkId, type); + this.dir = dir; + } + + /** + * Returns the directory entry for this chunk. + * You can then use standard POIFS methods to + * enumerate the entries in it. + */ + public DirectoryNode getDirectory() { + return dir; + } + + /** + * Treats the directory as an embeded MAPIMessage + * (it normally is one), and returns a MAPIMessage + * object to process it with. + */ + public MAPIMessage getAsEmbededMessage() throws IOException { + return new MAPIMessage(dir, dir.getFileSystem()); + } + + @Override + public void readValue(InputStream value) { + // DirectoryChunks have 0 byte contents + } + + @Override + public void writeValue(OutputStream out) { + // DirectoryChunks have 0 byte contents + } +} diff --git a/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java index e093126e32..8346fee7e2 100644 --- a/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java +++ b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java @@ -32,6 +32,7 @@ public final class Types { public static final int LONG = 0x0003; public static final int TIME = 0x0040; public static final int BOOLEAN = 0x000B; + public static final int DIRECTORY = 0x000D; public static String asFileEnding(int type) { String str = Integer.toHexString(type).toUpperCase(); diff --git a/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java b/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java index 2f2899f345..8ff74b7bcc 100644 --- a/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java +++ b/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java @@ -25,6 +25,7 @@ import org.apache.poi.hsmf.datatypes.ByteChunk; import org.apache.poi.hsmf.datatypes.Chunk; import org.apache.poi.hsmf.datatypes.ChunkGroup; import org.apache.poi.hsmf.datatypes.Chunks; +import org.apache.poi.hsmf.datatypes.DirectoryChunk; import org.apache.poi.hsmf.datatypes.MessageSubmissionChunk; import org.apache.poi.hsmf.datatypes.NameIdChunks; import org.apache.poi.hsmf.datatypes.RecipientChunks; @@ -93,7 +94,11 @@ public final class POIFSChunkParser { protected static void processChunks(DirectoryNode node, ChunkGroup grouping) { for(Entry entry : node) { if(entry instanceof DocumentNode) { - process((DocumentNode)entry, grouping); + process(entry, grouping); + } else if(entry instanceof DirectoryNode) { + if(entry.getName().endsWith(Types.asFileEnding(Types.DIRECTORY))) { + process(entry, grouping); + } } } } @@ -101,7 +106,7 @@ public final class POIFSChunkParser { /** * Creates a chunk, and gives it to its parent group */ - protected static void process(DocumentNode entry, ChunkGroup grouping) { + protected static void process(Entry entry, ChunkGroup grouping) { String entryName = entry.getName(); if(entryName.length() < 9) { @@ -140,6 +145,11 @@ public final class POIFSChunkParser { case Types.BINARY: chunk = new ByteChunk(namePrefix, chunkId, type); break; + case Types.DIRECTORY: + if(entry instanceof DirectoryNode) { + chunk = new DirectoryChunk((DirectoryNode)entry, namePrefix, chunkId, type); + } + break; case Types.ASCII_STRING: case Types.UNICODE_STRING: chunk = new StringChunk(namePrefix, chunkId, type); @@ -148,13 +158,17 @@ public final class POIFSChunkParser { } if(chunk != null) { - try { - DocumentInputStream inp = new DocumentInputStream(entry); - chunk.readValue(inp); - grouping.record(chunk); - } catch(IOException e) { - System.err.println("Error reading from part " + entry.getName() + " - " + e.toString()); - } + if(entry instanceof DocumentNode) { + try { + DocumentInputStream inp = new DocumentInputStream((DocumentNode)entry); + chunk.readValue(inp); + grouping.record(chunk); + } catch(IOException e) { + System.err.println("Error reading from part " + entry.getName() + " - " + e.toString()); + } + } else { + grouping.record(chunk); + } } } catch(NumberFormatException e) { // Name in the wrong format diff --git a/src/scratchpad/testcases/org/apache/poi/hsmf/TestFileWithAttachmentsRead.java b/src/scratchpad/testcases/org/apache/poi/hsmf/TestFileWithAttachmentsRead.java index cd8bfbf110..3c6ed37ba6 100644 --- a/src/scratchpad/testcases/org/apache/poi/hsmf/TestFileWithAttachmentsRead.java +++ b/src/scratchpad/testcases/org/apache/poi/hsmf/TestFileWithAttachmentsRead.java @@ -31,7 +31,8 @@ import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; * @author Nicolas Bureau */ public class TestFileWithAttachmentsRead extends TestCase { - private MAPIMessage mapiMessage; + private MAPIMessage twoSimpleAttachments; + private MAPIMessage pdfMsgAttachments; /** * Initialize this test, load up the attachment_test_msg.msg mapi message. @@ -40,7 +41,8 @@ public class TestFileWithAttachmentsRead extends TestCase { */ public TestFileWithAttachmentsRead() throws IOException { POIDataSamples samples = POIDataSamples.getHSMFInstance(); - this.mapiMessage = new MAPIMessage(samples.openResourceAsStream("attachment_test_msg.msg")); + this.twoSimpleAttachments = new MAPIMessage(samples.openResourceAsStream("attachment_test_msg.msg")); + this.pdfMsgAttachments = new MAPIMessage(samples.openResourceAsStream("attachment_msg_pdf.msg")); } /** @@ -50,18 +52,20 @@ public class TestFileWithAttachmentsRead extends TestCase { * */ public void testRetrieveAttachments() { - AttachmentChunks[] attachments = mapiMessage.getAttachmentFiles(); - int obtained = attachments.length; - int expected = 2; - - TestCase.assertEquals(obtained, expected); + // Simple file + AttachmentChunks[] attachments = twoSimpleAttachments.getAttachmentFiles(); + assertEquals(2, attachments.length); + + // Other file + attachments = pdfMsgAttachments.getAttachmentFiles(); + assertEquals(2, attachments.length); } /** * Test to see if attachments are not empty. */ public void testReadAttachments() throws IOException { - AttachmentChunks[] attachments = mapiMessage.getAttachmentFiles(); + AttachmentChunks[] attachments = twoSimpleAttachments.getAttachmentFiles(); // Basic checks for (AttachmentChunks attachment : attachments) { @@ -76,18 +80,52 @@ public class TestFileWithAttachmentsRead extends TestCase { AttachmentChunks attachment; // Now check in detail - attachment = mapiMessage.getAttachmentFiles()[0]; + attachment = twoSimpleAttachments.getAttachmentFiles()[0]; assertEquals("TEST-U~1.DOC", attachment.attachFileName.toString()); assertEquals("test-unicode.doc", attachment.attachLongFileName.toString()); assertEquals(".doc", attachment.attachExtension.getValue()); assertEquals(null, attachment.attachMimeTag); assertEquals(24064, attachment.attachData.getValue().length); - attachment = mapiMessage.getAttachmentFiles()[1]; + attachment = twoSimpleAttachments.getAttachmentFiles()[1]; assertEquals("pj1.txt", attachment.attachFileName.toString()); assertEquals("pj1.txt", attachment.attachLongFileName.toString()); assertEquals(".txt", attachment.attachExtension.getValue()); assertEquals(null, attachment.attachMimeTag); assertEquals(89, attachment.attachData.getValue().length); } + + /** + * Test that we can handle both PDF and MSG attachments + */ + public void testReadMsgAttachments() throws Exception { + AttachmentChunks[] attachments = pdfMsgAttachments.getAttachmentFiles(); + assertEquals(2, attachments.length); + + AttachmentChunks attachment; + + // Second is a PDF + attachment = pdfMsgAttachments.getAttachmentFiles()[1]; + assertEquals("smbprn~1.pdf", attachment.attachFileName.toString()); + assertEquals("smbprn.00009008.KdcPjl.pdf", attachment.attachLongFileName.toString()); + assertEquals(".pdf", attachment.attachExtension.getValue()); + assertEquals(null, attachment.attachMimeTag); + assertEquals(null, attachment.attachmentDirectory); + assertEquals(13539, attachment.attachData.getValue().length); + + // First in a nested message + attachment = pdfMsgAttachments.getAttachmentFiles()[0]; + assertEquals("Test Attachment", attachment.attachFileName.toString()); + assertEquals(null, attachment.attachLongFileName); + assertEquals(null, attachment.attachExtension); + assertEquals(null, attachment.attachMimeTag); + assertEquals(null, attachment.attachData); + assertNotNull(attachment.attachmentDirectory); + + // Check we can see some bits of it + MAPIMessage nested = attachment.attachmentDirectory.getAsEmbededMessage(); + assertEquals(1, nested.getRecipientNamesList().length); + assertEquals("Nick Booth", nested.getRecipientNames()); + assertEquals("Test Attachment", nested.getConversationTopic()); + } } diff --git a/test-data/hsmf/attachment_msg_pdf.msg b/test-data/hsmf/attachment_msg_pdf.msg new file mode 100644 index 0000000000000000000000000000000000000000..35b66e1116ab2f4d734a328e09710cc3dca74422 GIT binary patch literal 71680 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