From 70bf113c21c0cb0789a04b249c732838063159a7 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Thu, 3 Mar 2011 17:06:37 +0000 Subject: [PATCH] Tweak the attribute getter names on Attachments, and add MAPI+TNEF Attribute unit tests git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1076685 13f79535-47bb-0310-9956-ffa450edef68 --- .../src/org/apache/poi/hmef/Attachment.java | 14 +- .../src/org/apache/poi/hmef/HMEFMessage.java | 1 - .../org/apache/poi/hmef/TestAttachments.java | 2 + .../hmef/attribute/TestMAPIAttributes.java | 161 +++++++++++++-- .../hmef/attribute/TestTNEFAttributes.java | 189 ++++++++++++++++-- 5 files changed, 333 insertions(+), 34 deletions(-) diff --git a/src/scratchpad/src/org/apache/poi/hmef/Attachment.java b/src/scratchpad/src/org/apache/poi/hmef/Attachment.java index e961481a1e..89b063c263 100644 --- a/src/scratchpad/src/org/apache/poi/hmef/Attachment.java +++ b/src/scratchpad/src/org/apache/poi/hmef/Attachment.java @@ -53,7 +53,7 @@ public final class Attachment { * Return the attachment attribute with the given ID, * or null if there isn't one. */ - public TNEFAttribute getMessageAttribute(TNEFProperty id) { + public TNEFAttribute getAttribute(TNEFProperty id) { for(TNEFAttribute attr : attributes) { if(attr.getProperty() == id) { return attr; @@ -66,7 +66,7 @@ public final class Attachment { * Return the attachment MAPI Attribute with the given ID, * or null if there isn't one. */ - public MAPIAttribute getMessageMAPIAttribute(MAPIProperty id) { + public MAPIAttribute getMAPIAttribute(MAPIProperty id) { for(MAPIAttribute attr : mapiAttributes) { if(attr.getProperty() == id) { return attr; @@ -97,14 +97,14 @@ public final class Attachment { * if it isn't set */ private String getString(MAPIProperty id) { - return MAPIStringAttribute.getAsString( getMessageMAPIAttribute(id) ); + return MAPIStringAttribute.getAsString( getMAPIAttribute(id) ); } /** * Returns the string value of the TNEF property, or * null if it isn't set */ private String getString(TNEFProperty id) { - return TNEFStringAttribute.getAsString( getMessageAttribute(id) ); + return TNEFStringAttribute.getAsString( getAttribute(id) ); } /** @@ -131,7 +131,7 @@ public final class Attachment { */ public Date getModifiedDate() { return TNEFDateAttribute.getAsDate( - getMessageAttribute(TNEFProperty.ID_ATTACHMODIFYDATE) + getAttribute(TNEFProperty.ID_ATTACHMODIFYDATE) ); } @@ -139,7 +139,7 @@ public final class Attachment { * Returns the contents of the attachment. */ public byte[] getContents() { - TNEFAttribute contents = getMessageAttribute(TNEFProperty.ID_ATTACHDATA); + TNEFAttribute contents = getAttribute(TNEFProperty.ID_ATTACHDATA); if(contents == null) { throw new IllegalArgumentException("Attachment corrupt - no Data section"); } @@ -151,7 +151,7 @@ public final class Attachment { * of the attachment, or null if not set. */ public byte[] getRenderedMetaFile() { - TNEFAttribute meta = getMessageAttribute(TNEFProperty.ID_ATTACHMETAFILE); + TNEFAttribute meta = getAttribute(TNEFProperty.ID_ATTACHMETAFILE); if(meta == null) return null; return meta.getData(); } diff --git a/src/scratchpad/src/org/apache/poi/hmef/HMEFMessage.java b/src/scratchpad/src/org/apache/poi/hmef/HMEFMessage.java index 7da39f9c6c..b53543680d 100644 --- a/src/scratchpad/src/org/apache/poi/hmef/HMEFMessage.java +++ b/src/scratchpad/src/org/apache/poi/hmef/HMEFMessage.java @@ -23,7 +23,6 @@ import java.util.ArrayList; import java.util.List; import org.apache.poi.hmef.attribute.MAPIAttribute; -import org.apache.poi.hmef.attribute.MAPIRtfAttribute; import org.apache.poi.hmef.attribute.MAPIStringAttribute; import org.apache.poi.hmef.attribute.TNEFAttribute; import org.apache.poi.hmef.attribute.TNEFMAPIAttribute; diff --git a/src/scratchpad/testcases/org/apache/poi/hmef/TestAttachments.java b/src/scratchpad/testcases/org/apache/poi/hmef/TestAttachments.java index 13a82024a0..0e89f46a10 100644 --- a/src/scratchpad/testcases/org/apache/poi/hmef/TestAttachments.java +++ b/src/scratchpad/testcases/org/apache/poi/hmef/TestAttachments.java @@ -87,6 +87,8 @@ public final class TestAttachments extends TestCase { public void testAttachmentDetails() throws Exception { List attachments = quick.getAttachments(); + // Pick a predictable date format + // Note that the 28th April is in summer time in the UK DateFormat fmt = DateFormat.getDateTimeInstance( DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK ); diff --git a/src/scratchpad/testcases/org/apache/poi/hmef/attribute/TestMAPIAttributes.java b/src/scratchpad/testcases/org/apache/poi/hmef/attribute/TestMAPIAttributes.java index 8ed7ba5b49..60655a4ddd 100644 --- a/src/scratchpad/testcases/org/apache/poi/hmef/attribute/TestMAPIAttributes.java +++ b/src/scratchpad/testcases/org/apache/poi/hmef/attribute/TestMAPIAttributes.java @@ -17,26 +17,159 @@ package org.apache.poi.hmef.attribute; +import java.io.ByteArrayInputStream; +import java.text.DateFormat; +import java.util.Locale; + import junit.framework.TestCase; import org.apache.poi.POIDataSamples; import org.apache.poi.hmef.HMEFMessage; +import org.apache.poi.hsmf.datatypes.MAPIProperty; +import org.apache.poi.util.LittleEndian; public final class TestMAPIAttributes extends TestCase { - private static final POIDataSamples _samples = POIDataSamples.getHMEFInstance(); - - public void testOpen() throws Exception { - HMEFMessage msg = new HMEFMessage( - _samples.openResourceAsStream("quick-winmail.dat") - ); + private static final POIDataSamples _samples = POIDataSamples.getHMEFInstance(); + private HMEFMessage quick; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + quick = new HMEFMessage( + _samples.openResourceAsStream("quick-winmail.dat") + ); + } + + /** + * Test counts + */ + public void testCounts() throws Exception { + // Message should have 54 + assertEquals(54, quick.getMessageMAPIAttributes().size()); + + // First attachment should have 22 + assertEquals(22, quick.getAttachments().get(0).getMAPIAttributes().size()); + } + + /** + * Test various general ones + */ + public void testBasics() throws Exception { + // Try constructing two attributes + byte[] data = new byte[] { + // Level one, id 36867, type 6 + 0x01, 0x03, (byte)0x90, 0x06, 0x00, + // Length 24 + 0x24, 0x00, 0x00, 0x00, + + // Three attributes + 0x03, 0x00, 0x00, 0x00, + // AlternateRecipientAllowed = 01 00 + 0x0B, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, + // Priority = 00 00 00 00 + 0x03, 0x00, 0x26, 0x00, + 0x00, 0x00, 0x00, 0x00, + // ConversationTopic = Test + 0x1E, 0x00, 0x70, 0x00, + 0x01, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, + (byte)'T', (byte)'e', + (byte)'s', (byte)'t', + // Checksum (may be wrong...) + 0x01, 0x00 + }; + ByteArrayInputStream bais = new ByteArrayInputStream(data); + + // Create it + int level = bais.read(); + assertEquals(1, level); + TNEFAttribute attr = TNEFAttribute.create(bais); + + // Check it + assertNotNull(attr); + assertEquals(TNEFMAPIAttribute.class, attr.getClass()); + + TNEFMAPIAttribute mapi = (TNEFMAPIAttribute)attr; + assertEquals(3, mapi.getMAPIAttributes().size()); + + assertEquals( + MAPIProperty.ALTERNATE_RECIPIENT_ALLOWED, + mapi.getMAPIAttributes().get(0).getProperty() + ); + assertEquals(1, LittleEndian.getUShort( + mapi.getMAPIAttributes().get(0).getData() + )); + + assertEquals( + MAPIProperty.PRIORITY, + mapi.getMAPIAttributes().get(1).getProperty() + ); + assertEquals(0, LittleEndian.getUShort( + mapi.getMAPIAttributes().get(1).getData() + )); + + assertEquals( + MAPIProperty.CONVERSATION_TOPIC, + mapi.getMAPIAttributes().get(2).getProperty() + ); + assertEquals( + "Test", + ((MAPIStringAttribute)mapi.getMAPIAttributes().get(2)).getDataString() + ); + } - assertNotNull(msg); - } + /** + * Test String, Date and RTF ones + */ + public void testTyped() throws Exception { + MAPIAttribute attr; + + // String + // ConversationTopic -> This is a test message + attr = quick.getMessageMAPIAttribute(MAPIProperty.CONVERSATION_TOPIC); + assertNotNull(attr); + assertEquals(MAPIStringAttribute.class, attr.getClass()); + + MAPIStringAttribute str = (MAPIStringAttribute)attr; + assertEquals("This is a test message", str.getDataString()); + + // Date + // (Unknown/Custom) 32955 -> Wed Dec 15 2010 @ 14:46:31 UTC + attr = null; + for(MAPIAttribute a : quick.getMessageMAPIAttributes()) { + if(a.getProperty().id == 32955) { + attr = a; + break; + } + } + assertNotNull(attr); + assertEquals(MAPIDateAttribute.class, attr.getClass()); + + MAPIDateAttribute date = (MAPIDateAttribute)attr; + DateFormat fmt = DateFormat.getDateTimeInstance( + DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK + ); + assertEquals("15-Dec-2010 14:46:31", fmt.format(date.getDate())); + + // RTF + // RtfCompressed -> {\rtf1... + attr = quick.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED); + assertNotNull(attr); + assertEquals(MAPIRtfAttribute.class, attr.getClass()); + + MAPIRtfAttribute rtf = (MAPIRtfAttribute)attr; + assertEquals("{\\rtf1", rtf.getDataString().substring(0, 6)); + } - // Test basics - // Test counts - - // Check untyped - // Check typed - // Check common + /** + * Check common ones via helper accessors + */ + public void testCommon() throws Exception { + assertEquals("This is a test message", quick.getSubject()); + + assertEquals("quick.doc", quick.getAttachments().get(0).getLongFilename()); + assertEquals(".doc", quick.getAttachments().get(0).getExtension()); + } } diff --git a/src/scratchpad/testcases/org/apache/poi/hmef/attribute/TestTNEFAttributes.java b/src/scratchpad/testcases/org/apache/poi/hmef/attribute/TestTNEFAttributes.java index 6096ba3f1b..f7883dfed6 100644 --- a/src/scratchpad/testcases/org/apache/poi/hmef/attribute/TestTNEFAttributes.java +++ b/src/scratchpad/testcases/org/apache/poi/hmef/attribute/TestTNEFAttributes.java @@ -17,27 +17,192 @@ package org.apache.poi.hmef.attribute; +import java.io.ByteArrayInputStream; +import java.text.DateFormat; +import java.util.Locale; + import junit.framework.TestCase; import org.apache.poi.POIDataSamples; +import org.apache.poi.hmef.Attachment; import org.apache.poi.hmef.HMEFMessage; +import org.apache.poi.hsmf.datatypes.MAPIProperty; +import org.apache.poi.util.LittleEndian; public final class TestTNEFAttributes extends TestCase { - private static final POIDataSamples _samples = POIDataSamples.getHMEFInstance(); - - public void testOpen() throws Exception { - HMEFMessage msg = new HMEFMessage( - _samples.openResourceAsStream("quick-winmail.dat") - ); - - assertNotNull(msg); + private static final POIDataSamples _samples = POIDataSamples.getHMEFInstance(); + private HMEFMessage quick; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + quick = new HMEFMessage( + _samples.openResourceAsStream("quick-winmail.dat") + ); + } + + /** + * Test counts + */ + public void testCounts() throws Exception { + // The message should have 4 attributes + assertEquals(4, quick.getMessageAttributes().size()); + + // Each attachment should have 6 attributes + for(Attachment attach : quick.getAttachments()) { + assertEquals(6, attach.getAttributes().size()); + } } - // Test counts + /** + * Test the basics + */ + public void testBasics() throws Exception { + // An int one + assertEquals( + 0x010000, + LittleEndian.getInt( quick.getMessageAttribute(TNEFProperty.ID_TNEFVERSION).getData() ) + ); + + // Claims not to be text, but really is + assertEquals( + "IPM.Microsoft Mail.Note\0", + new String(quick.getMessageAttribute(TNEFProperty.ID_MESSAGECLASS).getData(), "ASCII") + ); + + // Try constructing two attributes + byte[] data = new byte[] { + // Level one, id 36870, type 8 + 0x01, 0x06, (byte)0x90, 0x08, 0x00, + // Length 4 + 0x04, 0x00, 0x00, 0x00, + // Data + 0x00, 0x00, 0x01, 0x00, + // Checksum + 0x01, 0x00, + + // level one, id 36871, type 6 + 0x01, 0x07, (byte)0x90, 0x06, 0x00, + // Length 8 + 0x08, 0x00, 0x00, 0x00, + // Data + (byte)0xe4, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + // Checksum + (byte)0xe8, 0x00 + }; + ByteArrayInputStream bais = new ByteArrayInputStream(data); + + // Create them + int level = bais.read(); + assertEquals(1, level); + TNEFAttribute attr1 = TNEFAttribute.create(bais); + + level = bais.read(); + assertEquals(1, level); + TNEFAttribute attr2 = TNEFAttribute.create(bais); + + assertEquals(-1, bais.read()); + + // Check them + assertEquals(TNEFProperty.ID_TNEFVERSION, attr1.getProperty()); + assertEquals(8, attr1.getType()); + assertEquals(4, attr1.getData().length); + assertEquals(0x010000, LittleEndian.getInt( attr1.getData() )); + + assertEquals(TNEFProperty.ID_OEMCODEPAGE, attr2.getProperty()); + assertEquals(6, attr2.getType()); + assertEquals(8, attr2.getData().length); + assertEquals(0x04e4, LittleEndian.getInt( attr2.getData() )); + } - // Test basics + /** + * Test string based ones + */ + public void testString() throws Exception { + TNEFAttribute attr = quick.getAttachments().get(0).getAttribute( + TNEFProperty.ID_ATTACHTITLE + ); + assertNotNull(attr); + assertEquals(TNEFStringAttribute.class, attr.getClass()); + + // It is a null terminated string + assertEquals("quick.doc\u0000", new String(attr.getData(), "ASCII")); + + // But when we ask for the string, that is sorted for us + TNEFStringAttribute str = (TNEFStringAttribute)attr; + assertEquals("quick.doc", str.getString()); + } + + /** + * Test date based ones + */ + public void testDate() throws Exception { + TNEFAttribute attr = quick.getAttachments().get(0).getAttribute( + TNEFProperty.ID_ATTACHMODIFYDATE + ); + assertNotNull(attr); + assertEquals(TNEFDateAttribute.class, attr.getClass()); + + // It is a series of date parts + // Weds 28th April 2010 @ 12:40:56 UTC + assertEquals(2010, LittleEndian.getUShort(attr.getData(), 0)); + assertEquals(04, LittleEndian.getUShort(attr.getData(), 2)); + assertEquals(28, LittleEndian.getUShort(attr.getData(), 4)); + assertEquals(12, LittleEndian.getUShort(attr.getData(), 6)); + assertEquals(40, LittleEndian.getUShort(attr.getData(), 8)); + assertEquals(56, LittleEndian.getUShort(attr.getData(), 10)); + assertEquals(3, LittleEndian.getUShort(attr.getData(), 12)); // Weds + + // Ask for it as a Java date, and have it converted + // Pick a predictable format + location. Note location is in summer time! + TNEFDateAttribute date = (TNEFDateAttribute)attr; + DateFormat fmt = DateFormat.getDateTimeInstance( + DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK + ); + assertEquals("28-Apr-2010 13:40:56", fmt.format(date.getDate())); + } - // Test string + /** + * Test a bit of mapi + */ + public void testMAPI() throws Exception { + // Message MAPI + TNEFAttribute attr = quick.getMessageAttribute( + TNEFProperty.ID_MAPIPROPERTIES + ); + assertNotNull(attr); + assertEquals(TNEFMAPIAttribute.class, attr.getClass()); + + TNEFMAPIAttribute mapi = (TNEFMAPIAttribute)attr; + assertEquals(54, mapi.getMAPIAttributes().size()); + assertEquals( + MAPIProperty.ALTERNATE_RECIPIENT_ALLOWED, + mapi.getMAPIAttributes().get(0).getProperty() + ); + + + // Attribute MAPI + attr = quick.getAttachments().get(0).getAttribute( + TNEFProperty.ID_ATTACHMENT + ); + assertNotNull(attr); + assertEquals(TNEFMAPIAttribute.class, attr.getClass()); + + mapi = (TNEFMAPIAttribute)attr; + assertEquals(22, mapi.getMAPIAttributes().size()); + assertEquals( + MAPIProperty.ATTACH_SIZE, + mapi.getMAPIAttributes().get(0).getProperty() + ); + } - // Test a bit of mapi + /** + * Test common ones via helpers + */ + public void testCommon() throws Exception { + assertEquals("This is a test message", quick.getSubject()); + assertEquals("quick.doc", quick.getAttachments().get(0).getFilename()); + } } -- 2.39.5