* http://search.cpan.org/dist/Convert-TNEF/
*/
public final class HMEFMessage {
- public static final long HEADER_SIGNATURE = 0x223e9f78;
+ public static final int HEADER_SIGNATURE = 0x223e9f78;
private int fileId;
private List<TNEFAttribute> messageAttributes = new ArrayList<TNEFAttribute>();
public HMEFMessage(InputStream inp) throws IOException {
// Check the signature matches
- long sig = LittleEndian.readInt(inp);
+ int sig = LittleEndian.readInt(inp);
if(sig != HEADER_SIGNATURE) {
throw new IllegalArgumentException(
"TNEF signature not detected in file, " +
fileId = LittleEndian.readUShort(inp);
// Now begin processing the contents
- process(inp, 0);
+ process(inp);
}
- private void process(InputStream inp, int lastLevel) throws IOException {
- // Fetch the level
- int level = inp.read();
- if(level == TNEFProperty.LEVEL_END_OF_FILE) {
- return;
+ private void process(InputStream inp) throws IOException {
+ int level;
+ do {
+ // Fetch the level
+ level = inp.read();
+
+ // Decide what to attach it to, based on the levels and IDs
+ switch (level) {
+ case TNEFProperty.LEVEL_MESSAGE:
+ processMessage(inp);
+ break;
+ case TNEFProperty.LEVEL_ATTACHMENT:
+ processAttachment(inp);
+ break;
+ // ignore trailing newline
+ case '\r':
+ case '\n':
+ case TNEFProperty.LEVEL_END_OF_FILE:
+ break;
+ default:
+ throw new IllegalStateException("Unhandled level " + level);
+ }
+ } while (level != TNEFProperty.LEVEL_END_OF_FILE);
+ }
+
+ void processMessage(InputStream inp) throws IOException {
+ // Build the attribute
+ TNEFAttribute attr = TNEFAttribute.create(inp);
+
+ messageAttributes.add(attr);
+
+ if (attr instanceof TNEFMAPIAttribute) {
+ TNEFMAPIAttribute tnefMAPI = (TNEFMAPIAttribute) attr;
+ mapiAttributes.addAll(tnefMAPI.getMAPIAttributes());
}
-
+ }
+
+ void processAttachment(InputStream inp) throws IOException {
// Build the attribute
TNEFAttribute attr = TNEFAttribute.create(inp);
-
- // Decide what to attach it to, based on the levels and IDs
- if(level == TNEFProperty.LEVEL_MESSAGE) {
- messageAttributes.add(attr);
-
- if(attr instanceof TNEFMAPIAttribute) {
- TNEFMAPIAttribute tnefMAPI = (TNEFMAPIAttribute)attr;
- mapiAttributes.addAll( tnefMAPI.getMAPIAttributes() );
- }
- } else if(level == TNEFProperty.LEVEL_ATTACHMENT) {
- // Previous attachment or a new one?
- if(attachments.size() == 0 || attr.getProperty() == TNEFProperty.ID_ATTACHRENDERDATA) {
- attachments.add(new Attachment());
- }
-
- // Save the attribute for it
- Attachment attach = attachments.get(attachments.size()-1);
- attach.addAttribute(attr);
- } else {
- throw new IllegalStateException("Unhandled level " + level);
+
+ // Previous attachment or a new one?
+ if (attachments.isEmpty()
+ || attr.getProperty() == TNEFProperty.ID_ATTACHRENDERDATA) {
+ attachments.add(new Attachment());
}
-
- // Handle the next one down
- process(inp, level);
+
+ // Save the attribute for it
+ Attachment attach = attachments.get(attachments.size() - 1);
+ attach.addAttribute(attr);
}
/**
import java.util.List;
import org.apache.poi.hmef.HMEFMessage;
-import org.apache.poi.hmef.attribute.TNEFAttribute;
import org.apache.poi.hmef.attribute.MAPIAttribute;
+import org.apache.poi.hmef.attribute.TNEFAttribute;
import org.apache.poi.hmef.attribute.TNEFDateAttribute;
import org.apache.poi.hmef.attribute.TNEFProperty;
import org.apache.poi.hmef.attribute.TNEFStringAttribute;
this.inp = inp;
// Check the signature matches
- long sig = LittleEndian.readInt(inp);
+ int sig = LittleEndian.readInt(inp);
if(sig != HMEFMessage.HEADER_SIGNATURE) {
throw new IllegalArgumentException(
"TNEF signature not detected in file, " +
--- /dev/null
+package org.apache.poi.hmef;\r
+\r
+import junit.framework.TestCase;\r
+\r
+import org.apache.poi.POIDataSamples;\r
+import org.apache.poi.hmef.attribute.MAPIAttribute;\r
+import org.apache.poi.hmef.attribute.TNEFAttribute;\r
+import org.apache.poi.hmef.attribute.TNEFProperty;\r
+import org.apache.poi.hsmf.datatypes.MAPIProperty;\r
+import org.apache.poi.util.LittleEndian;\r
+\r
+public class TestBugs extends TestCase {\r
+ public void test52400ReadSimpleTNEF() throws Exception {\r
+ POIDataSamples samples = POIDataSamples.getHMEFInstance();\r
+ String testFile = "bug52400-winmail-simple.dat";\r
+ HMEFMessage tnefDat = new HMEFMessage(samples.openResourceAsStream(testFile));\r
+ MAPIAttribute bodyHtml = tnefDat.getMessageMAPIAttribute(MAPIProperty.BODY_HTML);\r
+ String bodyStr = new String(bodyHtml.getData(), getEncoding(tnefDat));\r
+ assertTrue(bodyStr.contains("This is the message body."));\r
+ }\r
+ \r
+ public void test52400ReadAttachedTNEF() throws Exception {\r
+ POIDataSamples samples = POIDataSamples.getHMEFInstance();\r
+ String testFile = "bug52400-winmail-with-attachments.dat";\r
+ HMEFMessage tnefDat = new HMEFMessage(samples.openResourceAsStream(testFile));\r
+ MAPIAttribute bodyHtml = tnefDat.getMessageMAPIAttribute(MAPIProperty.BODY_HTML);\r
+ String bodyStr = new String(bodyHtml.getData(), getEncoding(tnefDat));\r
+ assertTrue(bodyStr.contains("There are also two attachments."));\r
+ assertEquals(2, tnefDat.getAttachments().size());\r
+ }\r
+ \r
+ private String getEncoding(HMEFMessage tnefDat) {\r
+ TNEFAttribute oemCP = tnefDat.getMessageAttribute(TNEFProperty.ID_OEMCODEPAGE);\r
+ MAPIAttribute cpId = tnefDat.getMessageMAPIAttribute(MAPIProperty.INTERNET_CPID);\r
+ int codePage = 1252;\r
+ if (oemCP != null) {\r
+ codePage = LittleEndian.getInt(oemCP.getData());\r
+ } else if (cpId != null) {\r
+ codePage = LittleEndian.getInt(cpId.getData());\r
+ }\r
+ switch (codePage) {\r
+ // see http://en.wikipedia.org/wiki/Code_page for more\r
+ case 1252: return "Windows-1252";\r
+ case 20127: return "US-ASCII";\r
+ default: return "cp"+codePage;\r
+ }\r
+ }\r
+}\r
package org.apache.poi.hmef;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
import org.apache.poi.hmef.attribute.MAPIRtfAttribute;
import org.apache.poi.hmef.attribute.TNEFProperty;
import org.apache.poi.hsmf.datatypes.MAPIProperty;
// It's all low bytes
byte[] contentsBytes = contents.getBytes("ASCII");
assertContents("message.rtf", contentsBytes);
+
+ // try to get a message id that does not exist
+ assertNull(msg.getMessageMAPIAttribute(MAPIProperty.AB_DEFAULT_DIR));
+ }
+
+ public void testMessageSample1() throws Exception {
+ HMEFMessage msg = new HMEFMessage(
+ _samples.openResourceAsStream("winmail-sample1.dat"));
+
+ // Firstly by byte
+ MAPIRtfAttribute rtf = (MAPIRtfAttribute) msg
+ .getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
+ // assertContents("message.rtf", rtf.getData());
+ assertNotNull(rtf);
+
+ // Then by String
+ String contents = msg.getBody();
+ //System.out.println(contents);
+ // It's all low bytes
+ byte[] contentsBytes = contents.getBytes("ASCII");
+ // assertContents("message.rtf", contentsBytes);
+ assertNotNull(contentsBytes);
+
+ assertNotNull(msg.getSubject());
+ assertNotNull(msg.getBody());
+ }
+
+ public void testInvalidMessage() throws Exception {
+ InputStream str = new ByteArrayInputStream(new byte[] {0, 0, 0, 0});
+ try {
+ assertNotNull(new HMEFMessage(str));
+ fail("Should catch an exception here");
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("TNEF signature not detected in file, expected 574529400 but got 0"));
+ }
+ }
+
+
+ public void testNoData() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ // Header
+ LittleEndian.putInt(HMEFMessage.HEADER_SIGNATURE, out);
+
+ // field
+ LittleEndian.putUShort(0, out);
+
+ byte[] bytes = out.toByteArray();
+ InputStream str = new ByteArrayInputStream(bytes);
+ HMEFMessage msg = new HMEFMessage(str);
+ assertNull(msg.getSubject());
+ assertNull(msg.getBody());
+ }
+
+ public void testInvalidLevel() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ // Header
+ LittleEndian.putInt(HMEFMessage.HEADER_SIGNATURE, out);
+
+ // field
+ LittleEndian.putUShort(0, out);
+
+ // invalid level
+ LittleEndian.putUShort(90, out);
+
+ byte[] bytes = out.toByteArray();
+ InputStream str = new ByteArrayInputStream(bytes);
+ try {
+ assertNotNull(new HMEFMessage(str));
+ fail("Should catch an exception here");
+ } catch (IllegalStateException e) {
+ assertTrue(e.getMessage().contains("Unhandled level 90"));
+ }
}
}
+