poi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From n...@apache.org
Subject svn commit: r1076607 - in /poi/trunk/src/scratchpad: src/org/apache/poi/hmef/attribute/ src/org/apache/poi/hmef/extractor/ testcases/org/apache/poi/hmef/
Date Thu, 03 Mar 2011 13:01:07 GMT
Author: nick
Date: Thu Mar  3 13:01:07 2011
New Revision: 1076607

URL: http://svn.apache.org/viewvc?rev=1076607&view=rev
Log:
Add a TNEF extractor class, which can be run from the command line to extract out the message
body and attachments

Added:
    poi/trunk/src/scratchpad/src/org/apache/poi/hmef/extractor/
    poi/trunk/src/scratchpad/src/org/apache/poi/hmef/extractor/HMEFContentsExtractor.java
Modified:
    poi/trunk/src/scratchpad/src/org/apache/poi/hmef/attribute/MAPIRtfAttribute.java
    poi/trunk/src/scratchpad/testcases/org/apache/poi/hmef/TestCompressedRTF.java

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hmef/attribute/MAPIRtfAttribute.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hmef/attribute/MAPIRtfAttribute.java?rev=1076607&r1=1076606&r2=1076607&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hmef/attribute/MAPIRtfAttribute.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hmef/attribute/MAPIRtfAttribute.java Thu Mar
 3 13:01:07 2011
@@ -31,17 +31,35 @@ import org.apache.poi.util.StringUtil;
  *  to a {@link HMEFMessage} or one of its {@link Attachment}s.
  */
 public final class MAPIRtfAttribute extends MAPIAttribute {
+   private final byte[] decompressed;
    private final String data;
    
    public MAPIRtfAttribute(MAPIProperty property, int type, byte[] data) throws IOException
{
       super(property, type, data);
       
       CompressedRTF rtf = new CompressedRTF();
-      byte[] decomp = rtf.decompress(new ByteArrayInputStream(data));
+      this.decompressed = rtf.decompress(new ByteArrayInputStream(data));
       
-      this.data = StringUtil.getFromCompressedUnicode(decomp, 0, decomp.length);
+      this.data = StringUtil.getFromCompressedUnicode(decompressed, 0, decompressed.length);
    }
    
+   /**
+    * Returns the original, compressed RTF
+    */
+   public byte[] getRawData() {
+      return super.getData();
+   }
+   
+   /**
+    * Returns the raw uncompressed RTF data
+    */
+   public byte[] getData() {
+      return decompressed;
+   }
+   
+   /**
+    * Returns the uncompressed RTF as a string
+    */
    public String getDataString() {
       return data;
    }

Added: poi/trunk/src/scratchpad/src/org/apache/poi/hmef/extractor/HMEFContentsExtractor.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hmef/extractor/HMEFContentsExtractor.java?rev=1076607&view=auto
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hmef/extractor/HMEFContentsExtractor.java
(added)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hmef/extractor/HMEFContentsExtractor.java
Thu Mar  3 13:01:07 2011
@@ -0,0 +1,109 @@
+/* ====================================================================
+   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.hmef.extractor;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.poi.hmef.Attachment;
+import org.apache.poi.hmef.HMEFMessage;
+import org.apache.poi.hmef.attribute.MAPIRtfAttribute;
+import org.apache.poi.hsmf.datatypes.MAPIProperty;
+
+/**
+ * A utility for extracting out the message body, and all attachments
+ *  from a HMEF/TNEF/winmail.dat file
+ */
+public final class HMEFContentsExtractor {
+   public static void main(String[] args) throws Exception {
+      if(args.length < 2) {
+         System.err.println("Use:");
+         System.err.println("  HMEFContentsExtractor <filename> <output dir>");
+         System.err.println("");
+         System.err.println("");
+         System.err.println("Where <filename> is the winmail.dat file to extract,");
+         System.err.println(" and <output dir> is where to place the extracted files");
+         System.exit(2);
+      }
+      
+      HMEFContentsExtractor ext = new HMEFContentsExtractor(new File(args[0]));
+      
+      File dir = new File(args[1]);
+      File rtf = new File(dir, "message.rtf");
+      if(! dir.exists()) {
+         throw new FileNotFoundException("Output directory " + dir.getName() + " not found");
+      }
+      
+      System.out.println("Extracting...");
+      ext.extractMessageBody(rtf);
+      ext.extractAttachments(dir);
+      System.out.println("Extraction completed");
+   }
+   
+   private HMEFMessage message;
+   public HMEFContentsExtractor(File filename) throws IOException {
+      this(new HMEFMessage(new FileInputStream(filename)));
+   }
+   public HMEFContentsExtractor(HMEFMessage message) {
+      this.message = message;
+   }
+   
+   /**
+    * Extracts the RTF message body to the supplied file
+    */
+   public void extractMessageBody(File dest) throws IOException {
+      FileOutputStream fout = new FileOutputStream(dest);
+      
+      MAPIRtfAttribute body = (MAPIRtfAttribute)
+         message.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
+      fout.write(body.getData());
+      
+      fout.close();
+   }
+   
+   /**
+    * Extracts all the message attachments to the supplied directory
+    */
+   public void extractAttachments(File dir) throws IOException {
+      int count = 0;
+      for(Attachment att : message.getAttachments()) {
+         count++;
+         
+         // Decide what to call it
+         String filename = att.getLongFilename();
+         if(filename == null || filename.length() == 0) {
+            filename = att.getFilename();
+         }
+         if(filename == null || filename.length() == 0) {
+            filename = "attachment" + count;
+            if(att.getExtension() != null) {
+               filename += att.getExtension();
+            }
+         }
+         
+         // Save it
+         File file = new File(dir, filename);
+         FileOutputStream fout = new FileOutputStream(file);
+         fout.write( att.getContents() );
+         fout.close();
+      }
+   }
+}

Modified: poi/trunk/src/scratchpad/testcases/org/apache/poi/hmef/TestCompressedRTF.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hmef/TestCompressedRTF.java?rev=1076607&r1=1076606&r2=1076607&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/testcases/org/apache/poi/hmef/TestCompressedRTF.java (original)
+++ poi/trunk/src/scratchpad/testcases/org/apache/poi/hmef/TestCompressedRTF.java Thu Mar
 3 13:01:07 2011
@@ -48,44 +48,45 @@ public final class TestCompressedRTF ext
        assertTrue(rtfAttr instanceof MAPIRtfAttribute);
        
        // Check the start of the compressed version
-       assertEquals(5907, rtfAttr.getData().length);
+       byte[] data = ((MAPIRtfAttribute)rtfAttr).getRawData();
+       assertEquals(5907, data.length);
        
        // First 16 bytes is header stuff
        // Check it has the length + compressed marker
-       assertEquals(5907-4, LittleEndian.getShort(rtfAttr.getData()));
+       assertEquals(5907-4, LittleEndian.getShort(data));
        assertEquals(
              "LZFu", 
-             StringUtil.getFromCompressedUnicode(rtfAttr.getData(), 8, 4)
+             StringUtil.getFromCompressedUnicode(data, 8, 4)
        );
              
        
        // Now Look at the code
-       assertEquals((byte)0x07, rtfAttr.getData()[16+0]);  // Flag: cccUUUUU
-       assertEquals((byte)0x00, rtfAttr.getData()[16+1]);  //  c1a: offset 0 / 0x000
-       assertEquals((byte)0x06, rtfAttr.getData()[16+2]);  //  c1b: length 6+2  -> {\rtf1\a
-       assertEquals((byte)0x01, rtfAttr.getData()[16+3]);  //  c2a: offset 16 / 0x010
-       assertEquals((byte)0x01, rtfAttr.getData()[16+4]);  //  c2b: length 1+2  ->  def
-       assertEquals((byte)0x0b, rtfAttr.getData()[16+5]);  //  c3a: offset 182 / 0xb6
-       assertEquals((byte)0x60, rtfAttr.getData()[16+6]);  //  c3b: length 0+2  -> la

-       assertEquals((byte)0x6e, rtfAttr.getData()[16+7]);  // n
-       assertEquals((byte)0x67, rtfAttr.getData()[16+8]);  // g
-       assertEquals((byte)0x31, rtfAttr.getData()[16+9]);  // 1
-       assertEquals((byte)0x30, rtfAttr.getData()[16+10]); // 0
-       assertEquals((byte)0x32, rtfAttr.getData()[16+11]); // 2
-       
-       assertEquals((byte)0x66, rtfAttr.getData()[16+12]); // Flag:  UccUUccU
-       assertEquals((byte)0x35, rtfAttr.getData()[16+13]); // 5 
-       assertEquals((byte)0x00, rtfAttr.getData()[16+14]); //  c2a: offset 6 / 0x006
-       assertEquals((byte)0x64, rtfAttr.getData()[16+15]); //  c2b: length 4+2  -> \ansi\a
-       assertEquals((byte)0x00, rtfAttr.getData()[16+16]); //  c3a: offset 7 / 0x007
-       assertEquals((byte)0x72, rtfAttr.getData()[16+17]); //  c3b: length 2+2  -> nsi
-       assertEquals((byte)0x63, rtfAttr.getData()[16+18]); // c 
-       assertEquals((byte)0x70, rtfAttr.getData()[16+19]); // p
-       assertEquals((byte)0x0d, rtfAttr.getData()[16+20]); //  c6a: offset 221 / 0x0dd
-       assertEquals((byte)0xd0, rtfAttr.getData()[16+21]); //  c6b: length 0+2  -> g1
-       assertEquals((byte)0x0e, rtfAttr.getData()[16+22]); //  c7a: offset 224 / 0x0e0
-       assertEquals((byte)0x00, rtfAttr.getData()[16+23]); //  c7b: length 0+2  -> 25
-       assertEquals((byte)0x32, rtfAttr.getData()[16+24]); // 2
+       assertEquals((byte)0x07, data[16+0]);  // Flag: cccUUUUU
+       assertEquals((byte)0x00, data[16+1]);  //  c1a: offset 0 / 0x000
+       assertEquals((byte)0x06, data[16+2]);  //  c1b: length 6+2  -> {\rtf1\a
+       assertEquals((byte)0x01, data[16+3]);  //  c2a: offset 16 / 0x010
+       assertEquals((byte)0x01, data[16+4]);  //  c2b: length 1+2  ->  def
+       assertEquals((byte)0x0b, data[16+5]);  //  c3a: offset 182 / 0xb6
+       assertEquals((byte)0x60, data[16+6]);  //  c3b: length 0+2  -> la 
+       assertEquals((byte)0x6e, data[16+7]);  // n
+       assertEquals((byte)0x67, data[16+8]);  // g
+       assertEquals((byte)0x31, data[16+9]);  // 1
+       assertEquals((byte)0x30, data[16+10]); // 0
+       assertEquals((byte)0x32, data[16+11]); // 2
+       
+       assertEquals((byte)0x66, data[16+12]); // Flag:  UccUUccU
+       assertEquals((byte)0x35, data[16+13]); // 5 
+       assertEquals((byte)0x00, data[16+14]); //  c2a: offset 6 / 0x006
+       assertEquals((byte)0x64, data[16+15]); //  c2b: length 4+2  -> \ansi\a
+       assertEquals((byte)0x00, data[16+16]); //  c3a: offset 7 / 0x007
+       assertEquals((byte)0x72, data[16+17]); //  c3b: length 2+2  -> nsi
+       assertEquals((byte)0x63, data[16+18]); // c 
+       assertEquals((byte)0x70, data[16+19]); // p
+       assertEquals((byte)0x0d, data[16+20]); //  c6a: offset 221 / 0x0dd
+       assertEquals((byte)0xd0, data[16+21]); //  c6b: length 0+2  -> g1
+       assertEquals((byte)0x0e, data[16+22]); //  c7a: offset 224 / 0x0e0
+       assertEquals((byte)0x00, data[16+23]); //  c7b: length 0+2  -> 25
+       assertEquals((byte)0x32, data[16+24]); // 2
     }
 
     /**
@@ -97,12 +98,13 @@ public final class TestCompressedRTF ext
              _samples.openResourceAsStream("quick-winmail.dat")
        );
        
-       MAPIAttribute rtfAttr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
-       assertNotNull(rtfAttr);
+       MAPIAttribute attr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
+       assertNotNull(attr);
+       MAPIRtfAttribute rtfAttr = (MAPIRtfAttribute)attr;
 
        // Truncate to header + flag + data for flag
        byte[] data = new byte[16+12];
-       System.arraycopy(rtfAttr.getData(), 0, data, 0, data.length);
+       System.arraycopy(rtfAttr.getRawData(), 0, data, 0, data.length);
        
        // Decompress it
        CompressedRTF comp = new CompressedRTF();
@@ -124,12 +126,13 @@ System.err.println(decompStr);       
              _samples.openResourceAsStream("quick-winmail.dat")
        );
 
-       MAPIAttribute rtfAttr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
-       assertNotNull(rtfAttr);
+       MAPIAttribute attr = msg.getMessageMAPIAttribute(MAPIProperty.RTF_COMPRESSED);
+       assertNotNull(attr);
+       MAPIRtfAttribute rtfAttr = (MAPIRtfAttribute)attr;
 
        // Truncate to header + flag + data for flag + flag + data
        byte[] data = new byte[16+12+13];
-       System.arraycopy(rtfAttr.getData(), 0, data, 0, data.length);
+       System.arraycopy(rtfAttr.getRawData(), 0, data, 0, data.length);
        
        // Decompress it
        CompressedRTF comp = new CompressedRTF();



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org


Mime
View raw message