diff --git a/build.xml b/build.xml index 5012001fb3..ce1cf7ff47 100644 --- a/build.xml +++ b/build.xml @@ -503,6 +503,7 @@ under the License. + @@ -536,6 +537,7 @@ under the License. + diff --git a/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java b/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java new file mode 100644 index 0000000000..ed215f6382 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java @@ -0,0 +1,146 @@ +/* ==================================================================== + 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; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.poi.hsmf.datatypes.Chunk; +import org.apache.poi.hsmf.datatypes.Chunks; +import org.apache.poi.hsmf.datatypes.StringChunk; +import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; +import org.apache.poi.hsmf.parsers.POIFSChunkParser; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; + +/** + * Reads an Outlook MSG File in and provides hooks into its data structure. + * + * @author Travis Ferguson + */ +public class MAPIMessage { + private POIFSChunkParser chunkParser; + private POIFSFileSystem fs; + + /** + * Constructor for creating new files. + * + */ + public MAPIMessage() { + //TODO make writing possible + } + + + /** + * Constructor for reading MSG Files. + * @param filename + * @throws IOException + */ + public MAPIMessage(String filename) throws IOException { + InputStream in = new FileInputStream(new File(filename)); + this.fs = new POIFSFileSystem(in); + chunkParser = new POIFSChunkParser(this.fs); + } + + /** + * Gets a string value based on the passed chunk. + * @param chunk + * @return + * @throws ChunkNotFoundException + */ + public String getStringFromChunk(StringChunk chunk) throws ChunkNotFoundException { + Chunk out = this.chunkParser.getDocumentNode(chunk); + StringChunk strchunk = (StringChunk)out; + return strchunk.toString(); + } + + + /** + * Gets the plain text body of this Outlook Message + * @return The string representation of the 'text' version of the body, if available. + * @throws IOException + * @throws ChunkNotFoundException + */ + public String getTextBody() throws IOException, ChunkNotFoundException { + return getStringFromChunk(Chunks.getInstance().textBodyChunk); + } + + /** + * Gets the subject line of the Outlook Message + * @return + * @throws ChunkNotFoundException + */ + public String getSubject() throws ChunkNotFoundException { + return getStringFromChunk(Chunks.getInstance().subjectChunk); + } + + + /** + * Gets the display value of the "TO" line of the outlook message + * This is not the actual list of addresses/values that will be sent to if you click Reply in the email. + * @return + * @throws ChunkNotFoundException + */ + public String getDisplayTo() throws ChunkNotFoundException { + return getStringFromChunk(Chunks.getInstance().displayToChunk); + } + + /** + * Gets the display value of the "TO" line of the outlook message + * This is not the actual list of addresses/values that will be sent to if you click Reply in the email. + * @return + * @throws ChunkNotFoundException + */ + public String getDisplayCC() throws ChunkNotFoundException { + return getStringFromChunk(Chunks.getInstance().displayCCChunk); + } + + /** + * Gets the display value of the "TO" line of the outlook message + * This is not the actual list of addresses/values that will be sent to if you click Reply in the email. + * @return + * @throws ChunkNotFoundException + */ + public String getDisplayBCC() throws ChunkNotFoundException { + return getStringFromChunk(Chunks.getInstance().displayBCCChunk); + } + + + /** + * Gets the conversation topic of the parsed Outlook Message. + * This is the part of the subject line that is after the RE: and FWD: + * @return + * @throws ChunkNotFoundException + */ + public String getConversationTopic() throws ChunkNotFoundException { + return getStringFromChunk(Chunks.getInstance().conversationTopic); + } + + /** + * Gets the message class of the parsed Outlook Message. + * (Yes, you can use this to determine if a message is a calendar item, note, or actual outlook Message) + * For emails the class will be IPM.Note + * + * @return + * @throws ChunkNotFoundException + */ + public String getMessageClass() throws ChunkNotFoundException { + return getStringFromChunk(Chunks.getInstance().messageClass); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunk.java b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunk.java new file mode 100644 index 0000000000..785a336fac --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunk.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.ByteArrayOutputStream; + +abstract public class Chunk { + protected int chunkId; + protected int type; + protected String namePrefix = "__substg1.0_"; + + /** + * Gets the id of this chunk + * @return + */ + public int getChunkId() { + return this.chunkId; + } + + /** + * Gets the numeric type of this chunk. + * @return + */ + public int getType() { + return this.type; + } + + /** + * Creates a string to use to identify this chunk in the POI file system object. + * @return + */ + public String getEntryName() { + String type = Integer.toHexString(this.type); + while(type.length() < 4) type = "0" + type; + + String chunkId = Integer.toHexString(this.chunkId); + while(chunkId.length() < 4) chunkId = "0" + chunkId; + + return this.namePrefix + chunkId.toUpperCase() + type.toUpperCase(); + } + + /** + * Gets a reference to a ByteArrayOutputStream that contains the value of this chunk. + * @return + */ + public abstract ByteArrayOutputStream getValueByteArray(); + + /** + * Sets the value of this chunk using a OutputStream + * @param value + */ + public abstract void setValue(ByteArrayOutputStream value); +} diff --git a/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java new file mode 100644 index 0000000000..309efeac9d --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java @@ -0,0 +1,40 @@ +/* ==================================================================== + 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; + + +/** + * Collection of convenence chunks for standard parts of the MSG file. + * + * @author Travis Ferguson + */ +public class Chunks { + /* String parts of Outlook Messages that are currently known */ + public StringChunk messageClass = new StringChunk(0x001A); //Type of message that the MSG represents (ie. IPM.Note) + public StringChunk textBodyChunk = new StringChunk(0x1000); //BODY Chunk, for plain/text messages + public StringChunk subjectChunk = new StringChunk(0x0037); //Subject link chunk, in plain/text + public StringChunk displayToChunk = new StringChunk(0x0E04); //Value that is in the TO field (not actually the addresses as they are stored in recip directory nodes + public StringChunk displayCCChunk = new StringChunk(0x0E03); //value that shows in the CC field + public StringChunk displayBCCChunk = new StringChunk(0x0E02); //Value that shows in the BCC field + public StringChunk conversationTopic = new StringChunk(0x0070); //Sort of like the subject line, but without the RE: and FWD: parts. + public StringChunk sentByServerType = new StringChunk(0x0075); //Type of server that the message originated from (SMTP, etc). + + public static Chunks getInstance() { + return new Chunks(); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hsmf/datatypes/StringChunk.java b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/StringChunk.java new file mode 100644 index 0000000000..2058b8ac58 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/StringChunk.java @@ -0,0 +1,53 @@ +/* ==================================================================== + 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.ByteArrayOutputStream; + +/** + * A Chunk made up of a single string. + * @author Travis Ferguson + */ +public class StringChunk extends Chunk { + + private String value; + + public StringChunk(int chunkId) { + this.chunkId = chunkId; + this.type = Types.STRING; + } + + /* (non-Javadoc) + * @see org.apache.poi.hsmf.Chunk.Chunk#getValueByteArray() + */ + public ByteArrayOutputStream getValueByteArray() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.apache.poi.hsmf.Chunk.Chunk#setValue(java.io.ByteArrayOutputStream) + */ + public void setValue(ByteArrayOutputStream value) { + this.value = value.toString().replaceAll("\0", ""); + } + + public String toString() { + return this.value; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java new file mode 100644 index 0000000000..9297666af7 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java @@ -0,0 +1,26 @@ +/* ==================================================================== + 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; + +public class Types { + public static int BINARY = 0x0102; + public static int STRING = 0x001E; + public static int LONG = 0x0003; + public static int TIME = 0x0040; + public static int BOOLEAN = 0x000B; +} diff --git a/src/scratchpad/src/org/apache/poi/hsmf/exceptions/ChunkNotFoundException.java b/src/scratchpad/src/org/apache/poi/hsmf/exceptions/ChunkNotFoundException.java new file mode 100644 index 0000000000..5c04518cb4 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hsmf/exceptions/ChunkNotFoundException.java @@ -0,0 +1,26 @@ +/* ==================================================================== + 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.exceptions; + +public class ChunkNotFoundException extends Exception { + private static final long serialVersionUID = 1L; + + public ChunkNotFoundException(String chunkName) { + super(chunkName + " was named, but not found in POIFS object"); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hsmf/exceptions/DirectoryChunkNotFoundException.java b/src/scratchpad/src/org/apache/poi/hsmf/exceptions/DirectoryChunkNotFoundException.java new file mode 100644 index 0000000000..308d0c6704 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hsmf/exceptions/DirectoryChunkNotFoundException.java @@ -0,0 +1,30 @@ +/* ==================================================================== + 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.exceptions; + +/** + * Exception for when a directory chunk is not found but is expected. + * @author Travis Ferguson + */ +public class DirectoryChunkNotFoundException extends Exception { + private static final long serialVersionUID = 1L; + + public DirectoryChunkNotFoundException(String directory) { + super("Directory Chunk " + directory + " was not found!"); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java b/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java new file mode 100644 index 0000000000..bdfb29e2a2 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java @@ -0,0 +1,232 @@ +/* ==================================================================== + 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.parsers; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; + +import org.apache.poi.hsmf.datatypes.Chunk; +import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; +import org.apache.poi.hsmf.exceptions.DirectoryChunkNotFoundException; +import org.apache.poi.poifs.filesystem.DirectoryEntry; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.poifs.filesystem.DocumentNode; +import org.apache.poi.poifs.filesystem.POIFSDocument; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.poifs.property.DirectoryProperty; +import org.apache.poi.poifs.property.DocumentProperty; +import org.apache.poi.poifs.storage.BlockWritable; + +/** + * Provides a HashMap with the ability to parse a PIOFS object and provide + * an 'easy to access' hashmap structure for the document chunks inside it. + * + * @author Travis Ferguson + */ +public class POIFSChunkParser { + /** + * Constructor + * @param fs + * @throws IOException + */ + public POIFSChunkParser(POIFSFileSystem fs) throws IOException { + this.setFileSystem(fs); + } + + + /** + * Set the POIFileSystem object that this object is using. + * @param fs + * @throws IOException + */ + public void setFileSystem(POIFSFileSystem fs) throws IOException { + this.fs = fs; + this.reparseFileSystem(); + } + + /** + * Get a reference to the FileSystem object that this object is currently using. + * @return + */ + public POIFSFileSystem getFileSystem() { + return this.fs; + } + + /** + * Reparse the FileSystem object, resetting all the chunks stored in this object + * @throws IOException + * + */ + public void reparseFileSystem() throws IOException { + // first clear this object of all chunks + DirectoryEntry root = this.fs.getRoot(); + Iterator iter = root.getEntries(); + + this.directoryMap = this.processPOIIterator(iter); + } + + /** + * Pull the chunk data that's stored in this object's hashmap out and return it as a HashMap. + * @param entryName + * @return + */ + public Object getChunk(HashMap dirMap, String entryName) { + if(dirMap == null) return null; + else { + return dirMap.get(entryName); + } + } + + /** + * Pull a directory/hashmap out of this hashmap and return it + * @param directoryName + * @return HashMap containing the chunks stored in the named directoryChunk + * @throws DirectoryChunkNotFoundException This is thrown should the directoryMap HashMap on this object be null + * or for some reason the directory is not found, is equal to null, or is for some reason not a HashMap/aka Directory Node. + */ + public HashMap getDirectoryChunk(String directoryName) throws DirectoryChunkNotFoundException { + DirectoryChunkNotFoundException excep = new DirectoryChunkNotFoundException(directoryName); + Object obj = getChunk(this.directoryMap, directoryName); + if(obj == null || !(obj instanceof HashMap)) throw excep; + + return (HashMap)obj; + } + + /** + * Pulls a ByteArrayOutputStream from this objects HashMap, this can be used to read a byte array of the contents of the given chunk. + * @param directoryMap, chunk + * @return + * @throws ChunkNotFoundException + */ + public Chunk getDocumentNode(HashMap dirNode, Chunk chunk) throws ChunkNotFoundException { + String entryName = chunk.getEntryName(); + ChunkNotFoundException excep = new ChunkNotFoundException(entryName); + Object obj = getChunk(dirNode, entryName); + if(obj == null || !(obj instanceof ByteArrayOutputStream)) throw excep; + + chunk.setValue((ByteArrayOutputStream)obj); + + return chunk; + } + + /** + * Pulls a Chunk out of this objects root Node tree. + * @param chunk + * @return + * @throws ChunkNotFoundException + */ + public Chunk getDocumentNode(Chunk chunk) throws ChunkNotFoundException { + return getDocumentNode(this.directoryMap, chunk); + } + + + /** + * Processes an iterator returned by a POIFS call to getRoot().getEntries() + * @param iter + * @return + * @throws IOException + */ + private HashMap processPOIIterator(Iterator iter) throws IOException { + HashMap currentNode = new HashMap(); + + while(iter.hasNext()) { + Object obj = iter.next(); + if(obj instanceof DocumentNode) { + this.processDocumentNode((DocumentNode)obj, currentNode); + } else if(obj instanceof DirectoryNode) { + String blockName = ((DirectoryNode)obj).getName(); + Iterator viewIt = null; + if( ((DirectoryNode)obj).preferArray()) { + Object[] arr = ((DirectoryNode)obj).getViewableArray(); + ArrayList viewList = new ArrayList(arr.length); + + for(int i = 0; i < arr.length; i++) { + viewList.add(arr[i]); + } + viewIt = viewList.iterator(); + } else { + viewIt = ((DirectoryNode)obj).getViewableIterator(); + } + //store the next node on the hashmap + currentNode.put(blockName, processPOIIterator(viewIt)); + } else if(obj instanceof DirectoryProperty) { + //don't do anything with the directory property chunk... + } else { + System.err.println("Unknown node: " + obj.toString()); + } + } + return currentNode; + } + + /** + * Processes a document node and adds it to the current directory HashMap + * @param obj + * @throws java.io.IOException + */ + private void processDocumentNode(DocumentNode obj, HashMap currentObj) throws IOException { + String blockName = ((DocumentNode)obj).getName(); + + Iterator viewIt = null; + if( ((DocumentNode)obj).preferArray()) { + Object[] arr = ((DocumentNode)obj).getViewableArray(); + ArrayList viewList = new ArrayList(arr.length); + + for(int i = 0; i < arr.length; i++) { + viewList.add(arr[i]); + } + viewIt = viewList.iterator(); + } else { + viewIt = ((DocumentNode)obj).getViewableIterator(); + } + + while(viewIt.hasNext()) { + Object view = viewIt.next(); + + if(view instanceof DocumentProperty) { + //we don't care about the properties + } else if(view instanceof POIFSDocument) { + //check if our node has blocks or if it can just be read raw. + int blockCount = ((POIFSDocument)view).countBlocks(); + //System.out.println("Block Name: " + blockName); + if(blockCount <= 0) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + BlockWritable[] bws = ((POIFSDocument)view).getSmallBlocks(); + for(int i = 0; i < bws.length; i++) { + bws[i].writeBlocks(out); + } + currentObj.put(blockName, out); + } else { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ((POIFSDocument)view).writeBlocks(out); + currentObj.put(blockName, out); + } + } else { + System.err.println("Unknown View Type: " + view.toString()); + } + } + } + + /* private instance variables */ + private static final long serialVersionUID = 1L; + private POIFSFileSystem fs; + private HashMap directoryMap; +} diff --git a/src/scratchpad/testcases/org/apache/poi/hsmf/AllTests.java b/src/scratchpad/testcases/org/apache/poi/hsmf/AllTests.java new file mode 100644 index 0000000000..18a622c32b --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hsmf/AllTests.java @@ -0,0 +1,40 @@ +/* ==================================================================== + 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; + +import junit.framework.*; + +public class AllTests + extends TestCase +{ + + public AllTests(String s) + { + super(s); + } + + public static Test suite() + { + TestSuite suite = new TestSuite(); + suite.addTestSuite(org.apache.poi.hsmf.model.TestBlankFileRead.class); + suite.addTestSuite(org.apache.poi.hsmf.model.TestSimpleFileRead.class); + suite.addTestSuite(org.apache.poi.hsmf.model.TestChunkData.class); + + return suite; + } +} diff --git a/src/scratchpad/testcases/org/apache/poi/hsmf/data/blank.msg b/src/scratchpad/testcases/org/apache/poi/hsmf/data/blank.msg new file mode 100644 index 0000000000..0bdb812401 Binary files /dev/null and b/src/scratchpad/testcases/org/apache/poi/hsmf/data/blank.msg differ diff --git a/src/scratchpad/testcases/org/apache/poi/hsmf/data/simple_test_msg.msg b/src/scratchpad/testcases/org/apache/poi/hsmf/data/simple_test_msg.msg new file mode 100644 index 0000000000..731fecc236 Binary files /dev/null and b/src/scratchpad/testcases/org/apache/poi/hsmf/data/simple_test_msg.msg differ diff --git a/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestBlankFileRead.java b/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestBlankFileRead.java new file mode 100644 index 0000000000..05735870b4 --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestBlankFileRead.java @@ -0,0 +1,125 @@ +/* ==================================================================== + 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.model; + +import java.io.IOException; + +import org.apache.poi.hsmf.MAPIMessage; +import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; + +import junit.framework.TestCase; + + +/** + * Tests to verify that the library can read blank msg files. + * + * @author Travis Ferguson + * + */ +public class TestBlankFileRead extends TestCase { + private MAPIMessage mapiMessage; + + /** + * Initialize this test, load up the blank.msg mapi message. + * @throws IOException + */ + public TestBlankFileRead() throws IOException { + String dirname = System.getProperty("HSMF.testdata.path"); + this.mapiMessage = new MAPIMessage(dirname + "/blank.msg"); + } + + /** + * Check if we can read the body of the blank message, we expect "". + * + * @throws Exception + */ + public void testReadBody() throws Exception { + try { + mapiMessage.getTextBody(); + } catch(ChunkNotFoundException exp) { + return; + } + + TestCase.fail("Should have thrown a ChunkNotFoundException but didn't"); + } + + + /** + * Test to see if we can read the CC Chunk. + * @throws ChunkNotFoundException + * + */ + public void testReadDisplayCC() throws ChunkNotFoundException { + String obtained = mapiMessage.getDisplayCC(); + String expected = ""; + + TestCase.assertEquals(obtained, expected); + } + + /** + * Test to see if we can read the CC Chunk. + * @throws ChunkNotFoundException + * + */ + public void testReadDisplayTo() throws ChunkNotFoundException { + String obtained = mapiMessage.getDisplayTo(); + String expected = ""; + + TestCase.assertEquals(obtained, expected); + } + + /** + * Test to see if we can read the CC Chunk. + * @throws ChunkNotFoundException + * + */ + public void testReadDisplayBCC() throws ChunkNotFoundException { + String obtained = mapiMessage.getDisplayBCC(); + String expected = ""; + + TestCase.assertEquals(obtained, expected); + } + + + /** + * Check if we can read the subject line of the blank message, we expect "" + * + * @throws Exception + */ + public void testReadSubject() throws Exception { + String obtained = mapiMessage.getSubject(); + TestCase.assertEquals("", obtained); + } + + + /** + * Check if we can read the subject line of the blank message, we expect "" + * + * @throws Exception + */ + public void testReadConversationTopic() throws Exception { + try { + mapiMessage.getConversationTopic(); + } catch(ChunkNotFoundException exp) { + return; + } + TestCase.fail("We shouldn't have a ConversationTopic node on the blank.msg file."); + } + + +} diff --git a/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestChunkData.java b/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestChunkData.java new file mode 100644 index 0000000000..dc4b531294 --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestChunkData.java @@ -0,0 +1,72 @@ +/* ==================================================================== + 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.model; + +import org.apache.poi.hsmf.datatypes.Chunk; +import org.apache.poi.hsmf.datatypes.Chunks; +import org.apache.poi.hsmf.datatypes.StringChunk; + +import junit.framework.TestCase; + +/** + * Verifies that the Chunks class is actually setup properly and hasn't been changed in ways + * that will break the library. + * + * @author Travis Ferguson + * + */ +public class TestChunkData extends TestCase { + public void testChunkCreate() { + StringChunk chunk = new StringChunk(0x0200); + TestCase.assertEquals("__substg1.0_0200001E", chunk.getEntryName()); + + /* test the lower and upper limits of the chunk ids */ + chunk = new StringChunk(0x0000); + TestCase.assertEquals("__substg1.0_0000001E", chunk.getEntryName()); + + chunk = new StringChunk(0xFFFF); + TestCase.assertEquals("__substg1.0_FFFF001E", chunk.getEntryName()); + } + + public void testTextBodyChunk() { + StringChunk chunk = new StringChunk(0x1000); + TestCase.assertEquals(chunk.getEntryName(), Chunks.getInstance().textBodyChunk.getEntryName()); + } + + public void testDisplayToChunk() { + StringChunk chunk = new StringChunk(0x0E04); + TestCase.assertEquals(chunk.getEntryName(), Chunks.getInstance().displayToChunk.getEntryName()); + } + + + public void testDisplayCCChunk() { + StringChunk chunk = new StringChunk(0x0E03); + TestCase.assertEquals(chunk.getEntryName(), Chunks.getInstance().displayCCChunk.getEntryName()); + } + + public void testDisplayBCCChunk() { + StringChunk chunk = new StringChunk(0x0E02); + TestCase.assertEquals(chunk.getEntryName(), Chunks.getInstance().displayBCCChunk.getEntryName()); + } + + public void testSubjectChunk() { + Chunk chunk = new StringChunk(0x0037); + TestCase.assertEquals(chunk.getEntryName(), Chunks.getInstance().subjectChunk.getEntryName()); + } + +} diff --git a/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestSimpleFileRead.java b/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestSimpleFileRead.java new file mode 100644 index 0000000000..0ede68965a --- /dev/null +++ b/src/scratchpad/testcases/org/apache/poi/hsmf/model/TestSimpleFileRead.java @@ -0,0 +1,129 @@ +/* ==================================================================== + 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.model; + +import java.io.IOException; + +import org.apache.poi.hsmf.MAPIMessage; +import org.apache.poi.hsmf.exceptions.ChunkNotFoundException; + +import junit.framework.TestCase; + +/** + * Tests to verify that we can read a simple msg file, that is in plain/text format with no attachments + * or extra recipents. + * + * @author Travis Ferguson + */ +public class TestSimpleFileRead extends TestCase { +private MAPIMessage mapiMessage; + + /** + * Initialize this test, load up the blank.msg mapi message. + * @throws Exception + */ + public TestSimpleFileRead() throws IOException { + String dirname = System.getProperty("HSMF.testdata.path"); + this.mapiMessage = new MAPIMessage(dirname + "/simple_test_msg.msg"); + } + + /** + * Test to see if we can read the CC Chunk. + * @throws ChunkNotFoundException + * + */ + public void testReadDisplayCC() throws ChunkNotFoundException { + String obtained = mapiMessage.getDisplayCC(); + String expected = ""; + + TestCase.assertEquals(obtained, expected); + } + + /** + * Test to see if we can read the CC Chunk. + * @throws ChunkNotFoundException + * + */ + public void testReadDisplayTo() throws ChunkNotFoundException { + String obtained = mapiMessage.getDisplayTo(); + String expected = "travis@overwrittenstack.com"; + + TestCase.assertEquals(obtained, expected); + } + + /** + * Test to see if we can read the CC Chunk. + * @throws ChunkNotFoundException + * + */ + public void testReadDisplayBCC() throws ChunkNotFoundException { + String obtained = mapiMessage.getDisplayBCC(); + String expected = ""; + + TestCase.assertEquals(obtained, expected); + } + + + /** + * Check if we can read the body of the blank message, we expect "". + * + * @throws Exception + */ + public void testReadBody() throws Exception { + String obtained = mapiMessage.getTextBody(); + String expected = "This is a test message."; + + TestCase.assertEquals(obtained, expected); + } + + /** + * Check if we can read the subject line of the blank message, we expect "" + * + * @throws Exception + */ + public void testReadSubject() throws Exception { + String obtained = mapiMessage.getSubject(); + String expected = "test message"; + + TestCase.assertEquals(expected, obtained); + } + + /** + * Check if we can read the subject line of the blank message, we expect "" + * + * @throws Exception + */ + public void testReadConversationTopic() throws Exception { + String obtained = mapiMessage.getConversationTopic(); + TestCase.assertEquals("test message", obtained); + } + + + /** + * Check if we can read the subject line of the blank message, we expect "" + * + * @throws Exception + */ + public void testReadMessageClass() throws Exception { + String obtained = mapiMessage.getMessageClass(); + TestCase.assertEquals("IPM.Note", obtained); + } + + + +}