Author: nick
Date: Wed Jan 12 16:45:02 2011
New Revision: 1058226

URL: http://svn.apache.org/viewvc?rev=1058226&view=rev
Log:
Start to decode the MAPI Properties in the TNEF stream for HMEF

Added:
    poi/trunk/src/scratchpad/src/org/apache/poi/hmef/MAPIAttribute.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hmef/MAPIStringAttribute.java
Modified:
    poi/trunk/src/scratchpad/src/org/apache/poi/hmef/Attachment.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hmef/HMEFMessage.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hmef/dev/HMEFDumper.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hmef/Attachment.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hmef/Attachment.java?rev=1058226&r1=1058225&r2=1058226&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hmef/Attachment.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hmef/Attachment.java Wed Jan 12 
16:45:02 2011
@@ -26,12 +26,21 @@ import java.util.List;
  */
 public final class Attachment {
    private final List<Attribute> attributes = new ArrayList<Attribute>();
+   private final List<MAPIAttribute> mapiAttributes = new 
ArrayList<MAPIAttribute>();
    
    protected void addAttribute(Attribute attr) {
       attributes.add(attr);
    }
    
+   protected void addAttribute(MAPIAttribute attr) {
+      mapiAttributes.add(attr);
+   }
+   
    public List<Attribute> getAttributes() {
       return attributes;
    }
+   
+   public List<MAPIAttribute> getMAPIAttributes() {
+      return mapiAttributes;
+   }
 }

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hmef/HMEFMessage.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hmef/HMEFMessage.java?rev=1058226&r1=1058225&r2=1058226&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hmef/HMEFMessage.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hmef/HMEFMessage.java Wed Jan 
12 16:45:02 2011
@@ -37,6 +37,7 @@ public final class HMEFMessage {
    
    private int fileId; 
    private List<Attribute> messageAttributes = new ArrayList<Attribute>();
+   private List<MAPIAttribute> mapiAttributes = new ArrayList<MAPIAttribute>();
    private List<Attachment> attachments = new ArrayList<Attachment>();
    
    public HMEFMessage(InputStream inp) throws IOException {
@@ -54,6 +55,24 @@ public final class HMEFMessage {
       
       // Now begin processing the contents
       process(inp, 0);
+      
+      // Finally expand out the MAPI Attributes
+      for(Attribute attr : messageAttributes) {
+         if(attr.getId() == Attribute.ID_MAPIPROPERTIES) {
+            mapiAttributes.addAll( 
+                  MAPIAttribute.create(attr) 
+            );
+         }
+      }
+      for(Attachment attachment : attachments) {
+         for(Attribute attr : attachment.getAttributes()) {
+            if(attr.getId() == Attribute.ID_MAPIPROPERTIES) {
+               attachment.getMAPIAttributes().addAll(
+                     MAPIAttribute.create(attr) 
+               );
+            }
+         }
+      }
    }
    
    private void process(InputStream inp, int lastLevel) throws IOException {

Added: poi/trunk/src/scratchpad/src/org/apache/poi/hmef/MAPIAttribute.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hmef/MAPIAttribute.java?rev=1058226&view=auto
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hmef/MAPIAttribute.java (added)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hmef/MAPIAttribute.java Wed Jan 
12 16:45:02 2011
@@ -0,0 +1,170 @@
+/* ====================================================================
+   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;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.hsmf.datatypes.MAPIProperty;
+import org.apache.poi.hsmf.datatypes.Types;
+import org.apache.poi.util.HexDump;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.LittleEndian;
+
+/**
+ * A pure-MAPI attribute which applies to a {...@link HMEFMessage}
+ *  or one of its {...@link Attachment}s.
+ */
+public class MAPIAttribute {
+   private final MAPIProperty property;
+   private final int type;
+   private final byte[] data;
+   
+   /**
+    * Constructs a single new attribute from
+    *  the contents of the stream
+    */
+   public MAPIAttribute(MAPIProperty property, int type, byte[] data) {
+      this.property = property;
+      this.type = type;
+      this.data = data;
+   }
+
+   public MAPIProperty getProperty() {
+      return property;
+   }
+
+   public int getType() {
+      return type;
+   }
+
+   public byte[] getData() {
+      return data;
+   }
+   
+   public String toString() {
+      return property.toString() + " " + HexDump.toHex(data);
+   }
+   
+   /**
+    * Parses a MAPI Properties TNEF Attribute, and returns
+    *  the list of MAPI Attributes contained within it
+    */
+   public static List<MAPIAttribute> create(Attribute parent) throws 
IOException {
+      if(parent.getId() != Attribute.ID_MAPIPROPERTIES) {
+         throw new IllegalArgumentException(
+               "Can only create from a MAPIProperty attribute, " +
+               "instead received a " + parent.getId() + " one"
+         );
+      }
+      ByteArrayInputStream inp = new ByteArrayInputStream(parent.getData());
+      
+      // First up, get the number of attributes
+      int count = LittleEndian.readInt(inp);
+      List<MAPIAttribute> attrs = new ArrayList<MAPIAttribute>();
+      
+      // Now, read each one in in turn
+      for(int i=0; i<count; i++) {
+         int typeAndMV = LittleEndian.readUShort(inp);
+         int id = LittleEndian.readUShort(inp);
+         
+         // Is it either Multi-Valued or Variable-Length?
+         boolean isMV = false;
+         boolean isVL = false;
+         int type = typeAndMV;
+         if( (typeAndMV & Types.MULTIVALUED_FLAG) > 0 ) {
+            isMV = true;
+            type -= Types.MULTIVALUED_FLAG;
+         }
+         if(type == Types.ASCII_STRING || type == Types.UNICODE_STRING ||
+               type == Types.BINARY || type == Types.DIRECTORY) {
+            isVL = true;
+         }
+         
+         // If it's a named property, rather than a standard
+         //  MAPI property, grab the details of it
+         MAPIProperty prop = MAPIProperty.get(id);
+         if(id >= 0x8000 && id <= 0xFFFF) {
+            // TODO
+            throw new UnsupportedOperationException("Not yet implemented for 
id " + id);
+         }
+         
+         // Now read in the value(s)
+         int values = 1;
+         if(isMV || isVL) {
+            values = LittleEndian.readInt(inp);
+         }
+         for(int j=0; j<values; j++) {
+            int len = getLength(type, inp);
+            byte[] data = new byte[len];
+            IOUtils.readFully(inp, data);
+            
+            // Create
+            MAPIAttribute attr;
+            if(type == Types.UNICODE_STRING || type == Types.ASCII_STRING) {
+               attr = new MAPIStringAttribute(prop, type, data);
+            } else {
+               attr = new MAPIAttribute(prop, type, data);
+            }
+            attrs.add(attr);
+            
+            // Data is always padded out to a 4 byte boundary
+            if(len % 4 != 0) {
+               byte[] padding = new byte[len % 4];
+               IOUtils.readFully(inp, padding);
+            }
+         }
+         break;
+      }
+      
+      // All done
+      return attrs;
+   }
+   private static int getLength(int type, InputStream inp) throws IOException {
+      switch(type) {
+         case Types.NULL:
+            return 0;
+         case Types.BOOLEAN:
+         case Types.SHORT:
+            return 2;
+         case Types.LONG:
+         case Types.FLOAT:
+         case Types.ERROR:
+            return 4;
+         case Types.LONG_LONG:
+         case Types.DOUBLE:
+         case Types.APP_TIME:
+         case Types.TIME:
+         case Types.CURRENCY:
+            return 8;
+         case Types.CLS_ID:
+            return 16;
+         case Types.ASCII_STRING:
+         case Types.UNICODE_STRING:
+         case Types.DIRECTORY:
+         case Types.BINARY:
+            // Need to read the length, as it varies
+            return LittleEndian.readInt(inp);
+         default:
+            throw new IllegalArgumentException("Unknown type " + type);
+      }
+   }
+}

Added: poi/trunk/src/scratchpad/src/org/apache/poi/hmef/MAPIStringAttribute.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hmef/MAPIStringAttribute.java?rev=1058226&view=auto
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hmef/MAPIStringAttribute.java 
(added)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hmef/MAPIStringAttribute.java 
Wed Jan 12 16:45:02 2011
@@ -0,0 +1,71 @@
+/* ====================================================================
+   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;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.poi.util.HexDump;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.StringUtil;
+import org.apache.poi.hmef.Attribute.AttributeID;
+import org.apache.poi.hsmf.datatypes.MAPIProperty;
+import org.apache.poi.hsmf.datatypes.Types;
+
+/**
+ * A pure-MAPI attribute holding a String, which applies 
+ *  to a {...@link HMEFMessage} or one of its {...@link Attachment}s.
+ */
+public final class MAPIStringAttribute extends MAPIAttribute {
+   private static final String CODEPAGE = "CP1252";
+   private final String data;
+   
+   public MAPIStringAttribute(MAPIProperty property, int type, byte[] data) {
+      super(property, type, data);
+      
+      String tmpData = null;
+      if(type == Types.ASCII_STRING) {
+         try {
+            tmpData = new String(data, CODEPAGE);
+         } catch(UnsupportedEncodingException e) {
+            throw new RuntimeException("JVM Broken - core encoding " + 
CODEPAGE + " missing");
+         }
+      } else if(type == Types.UNICODE_STRING) {
+         tmpData = StringUtil.getFromUnicodeLE(data);
+      } else {
+         throw new IllegalArgumentException("Not a string type " + type);
+      }
+      
+      // Strip off the null terminator if present
+      if(tmpData.endsWith("\0")) {
+         tmpData = tmpData.substring(0, tmpData.length()-1);
+      }
+      this.data = tmpData;
+   }
+   
+   public String toString() {
+      return getProperty().toString() + " " + data;
+   }
+}

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hmef/dev/HMEFDumper.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hmef/dev/HMEFDumper.java?rev=1058226&r1=1058225&r2=1058226&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hmef/dev/HMEFDumper.java 
(original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hmef/dev/HMEFDumper.java Wed 
Jan 12 16:45:02 2011
@@ -20,9 +20,11 @@ package org.apache.poi.hmef.dev;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.List;
 
 import org.apache.poi.hmef.Attribute;
 import org.apache.poi.hmef.HMEFMessage;
+import org.apache.poi.hmef.MAPIAttribute;
 import org.apache.poi.util.HexDump;
 import org.apache.poi.util.LittleEndian;
 
@@ -104,6 +106,14 @@ public final class HMEFDumper {
             }
          }
          System.out.println();
+         
+         if(attr.getId() == Attribute.ID_MAPIPROPERTIES) {
+            List<MAPIAttribute> attrs = MAPIAttribute.create(attr);
+            for(MAPIAttribute ma : attrs) {
+               System.out.println(indent + indent + ma);
+            }
+            System.out.println();
+         }
       }
    }
 }

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java?rev=1058226&r1=1058225&r2=1058226&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java 
(original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java Wed 
Jan 12 16:45:02 2011
@@ -65,7 +65,7 @@ public final class Types {
    public static final int UNICODE_STRING = 0x001F;
 
    /** MultiValued - Value part contains multiple values */
-   public static final int MULTIVALUED_FLAT = 0x1000;
+   public static final int MULTIVALUED_FLAG = 0x1000;
 
 
    public static String asFileEnding(int type) {



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to