From 182eac4abcec91590c421fbc6ae27b4b7d9e6e9b Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Wed, 12 Jan 2011 16:45:02 +0000 Subject: [PATCH] Start to decode the MAPI Properties in the TNEF stream for HMEF git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1058226 13f79535-47bb-0310-9956-ffa450edef68 --- .../src/org/apache/poi/hmef/Attachment.java | 9 + .../src/org/apache/poi/hmef/HMEFMessage.java | 19 ++ .../org/apache/poi/hmef/MAPIAttribute.java | 170 ++++++++++++++++++ .../apache/poi/hmef/MAPIStringAttribute.java | 71 ++++++++ .../org/apache/poi/hmef/dev/HMEFDumper.java | 10 ++ .../org/apache/poi/hsmf/datatypes/Types.java | 2 +- 6 files changed, 280 insertions(+), 1 deletion(-) create mode 100644 src/scratchpad/src/org/apache/poi/hmef/MAPIAttribute.java create mode 100644 src/scratchpad/src/org/apache/poi/hmef/MAPIStringAttribute.java diff --git a/src/scratchpad/src/org/apache/poi/hmef/Attachment.java b/src/scratchpad/src/org/apache/poi/hmef/Attachment.java index 4da794c633..a7c4d71f16 100644 --- a/src/scratchpad/src/org/apache/poi/hmef/Attachment.java +++ b/src/scratchpad/src/org/apache/poi/hmef/Attachment.java @@ -26,12 +26,21 @@ import java.util.List; */ public final class Attachment { private final List attributes = new ArrayList(); + private final List mapiAttributes = new ArrayList(); protected void addAttribute(Attribute attr) { attributes.add(attr); } + protected void addAttribute(MAPIAttribute attr) { + mapiAttributes.add(attr); + } + public List getAttributes() { return attributes; } + + public List getMAPIAttributes() { + return mapiAttributes; + } } diff --git a/src/scratchpad/src/org/apache/poi/hmef/HMEFMessage.java b/src/scratchpad/src/org/apache/poi/hmef/HMEFMessage.java index d9eaac3937..d86e6afad6 100644 --- a/src/scratchpad/src/org/apache/poi/hmef/HMEFMessage.java +++ b/src/scratchpad/src/org/apache/poi/hmef/HMEFMessage.java @@ -37,6 +37,7 @@ public final class HMEFMessage { private int fileId; private List messageAttributes = new ArrayList(); + private List mapiAttributes = new ArrayList(); private List attachments = new ArrayList(); 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 { diff --git a/src/scratchpad/src/org/apache/poi/hmef/MAPIAttribute.java b/src/scratchpad/src/org/apache/poi/hmef/MAPIAttribute.java new file mode 100644 index 0000000000..81629e1db5 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hmef/MAPIAttribute.java @@ -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 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 attrs = new ArrayList(); + + // Now, read each one in in turn + for(int i=0; i 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 attrs = MAPIAttribute.create(attr); + for(MAPIAttribute ma : attrs) { + System.out.println(indent + indent + ma); + } + System.out.println(); + } } } } diff --git a/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java index 604cfadc77..bd76e14f9c 100644 --- a/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java +++ b/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Types.java @@ -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) { -- 2.39.5