]> source.dussan.org Git - poi.git/commitdiff
Bug 52400: fix handling some types of TNEF files, make HMEFMessage.HEADER_SIGNATURE...
authorDominik Stadler <centic@apache.org>
Sun, 3 Nov 2013 12:43:42 +0000 (12:43 +0000)
committerDominik Stadler <centic@apache.org>
Sun, 3 Nov 2013 12:43:42 +0000 (12:43 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1538353 13f79535-47bb-0310-9956-ffa450edef68

src/scratchpad/src/org/apache/poi/hmef/HMEFMessage.java
src/scratchpad/src/org/apache/poi/hmef/dev/HMEFDumper.java
src/scratchpad/testcases/org/apache/poi/hmef/TestBugs.java [new file with mode: 0644]
src/scratchpad/testcases/org/apache/poi/hmef/TestHMEFMessage.java
test-data/hmef/bug52400-winmail-simple.dat [new file with mode: 0644]
test-data/hmef/bug52400-winmail-with-attachments.dat [new file with mode: 0644]
test-data/hmef/winmail-sample1.dat [new file with mode: 0644]

index b53543680da01cce2ce47d08861b952ecd312d16..cf88534366a9ce5a4913601a1a69384b70824599 100644 (file)
@@ -39,7 +39,7 @@ import org.apache.poi.util.LittleEndian;
  *   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>();
@@ -48,7 +48,7 @@ public final class HMEFMessage {
    
    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, " +
@@ -60,42 +60,59 @@ public final class HMEFMessage {
       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);
    }
    
    /**
index 7addb6b84e6480ce194eaffbccebd642107e76fd..3d7bcfefe68f2e582b20b03dc18a7e3cbe7adc1f 100644 (file)
@@ -23,8 +23,8 @@ import java.io.InputStream;
 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;
@@ -62,7 +62,7 @@ public final class HMEFDumper {
       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, " +
diff --git a/src/scratchpad/testcases/org/apache/poi/hmef/TestBugs.java b/src/scratchpad/testcases/org/apache/poi/hmef/TestBugs.java
new file mode 100644 (file)
index 0000000..79529a7
--- /dev/null
@@ -0,0 +1,48 @@
+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
index ee14efc1dc85a55e1697b8e70e07824f1259f747..d9344b1bdaafb61c0b9c13b9eebe7107882c74d4 100644 (file)
 
 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;
@@ -119,5 +123,80 @@ public final class TestHMEFMessage extends HMEFTest {
       // 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"));
+          }
    }
 }
+
diff --git a/test-data/hmef/bug52400-winmail-simple.dat b/test-data/hmef/bug52400-winmail-simple.dat
new file mode 100644 (file)
index 0000000..cb9f5f5
Binary files /dev/null and b/test-data/hmef/bug52400-winmail-simple.dat differ
diff --git a/test-data/hmef/bug52400-winmail-with-attachments.dat b/test-data/hmef/bug52400-winmail-with-attachments.dat
new file mode 100644 (file)
index 0000000..9f18a8a
Binary files /dev/null and b/test-data/hmef/bug52400-winmail-with-attachments.dat differ
diff --git a/test-data/hmef/winmail-sample1.dat b/test-data/hmef/winmail-sample1.dat
new file mode 100644 (file)
index 0000000..b9f6295
Binary files /dev/null and b/test-data/hmef/winmail-sample1.dat differ