* @see #guess7BitEncoding()
*/
public void set7BitEncoding(String charset) {
- for(Chunk c : mainChunks.getAll()) {
+ for(Chunk c : mainChunks.getChunks()) {
if(c instanceof StringChunk) {
((StringChunk)c).set7BitEncoding(charset);
}
}
if (nameIdChunks!=null) {
- for(Chunk c : nameIdChunks.getAll()) {
+ for(Chunk c : nameIdChunks.getChunks()) {
if(c instanceof StringChunk) {
((StringChunk)c).set7BitEncoding(charset);
}
* are stored as 7 bit rather than unicode?
*/
public boolean has7BitEncodingStrings() {
- for(Chunk c : mainChunks.getAll()) {
+ for(Chunk c : mainChunks.getChunks()) {
if(c instanceof StringChunk) {
if( ((StringChunk)c).getType() == Types.ASCII_STRING ) {
return true;
}
if (nameIdChunks!=null) {
- for(Chunk c : nameIdChunks.getAll()) {
+ for(Chunk c : nameIdChunks.getChunks()) {
if(c instanceof StringChunk) {
if( ((StringChunk)c).getType() == Types.ASCII_STRING ) {
return true;
// And add to the main list
allChunks.add(chunk);
}
-
+
+ /**
+ * Used to flag that all the chunks of the attachment
+ * have now been located.
+ */
+ public void chunksComplete() {
+ // Currently, we don't need to do anything special once
+ // all the chunks have been located
+ }
+
+
/**
* Orders by the attachment number.
*/
--- /dev/null
+/* ====================================================================
+ 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.hsmf.datatypes;
+
+
+/**
+ * A variable length {@link PropertyValue} that is
+ * backed by a {@link Chunk}
+ * TODO Provide a way to link these up with the chunks
+ */
+public class ChunkBasedPropertyValue extends PropertyValue {
+ public ChunkBasedPropertyValue(MAPIProperty property, long flags, byte[] offsetData) {
+ super(property, flags, offsetData);
+ }
+
+ @Override
+ public Chunk getValue() {
+ // TODO Decode the value into an offset
+ // TODO Look up the chunk based on that
+ return null;
+ }
+
+ /**
+ * Stores the offset of the chunk as the property value
+ */
+ public void setValue(Chunk chunk) {
+ // TODO
+ }
+}
* Called by the parser whenever a chunk is found.
*/
public void record(Chunk chunk);
+
+ /**
+ * Called by the parser when all chunks have been found.
+ */
+ public void chunksComplete();
}
package org.apache.poi.hsmf.datatypes;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* http://msdn.microsoft.com/en-us/library/ms526356%28v=exchg.10%29.aspx
*/
public final class Chunks implements ChunkGroup {
- /** Holds all the chunks that were found. */
- private List<Chunk> allChunks = new ArrayList<Chunk>();
+ /** Holds all the chunks that were found, indexed by their MAPIProperty */
+ private Map<MAPIProperty,List<Chunk>> allChunks = new HashMap<MAPIProperty,List<Chunk>>();
/** Type of message that the MSG represents (ie. IPM.Note) */
public StringChunk messageClass;
/** The message properties */
public MessagePropertiesChunk messageProperties;
-
- public Chunk[] getAll() {
- return allChunks.toArray(new Chunk[allChunks.size()]);
+ public Map<MAPIProperty,List<Chunk>> getAll() {
+ return allChunks;
}
public Chunk[] getChunks() {
- return getAll();
+ ArrayList<Chunk> chunks = new ArrayList<Chunk>(allChunks.size());
+ for (List<Chunk> c : allChunks.values()) {
+ chunks.addAll(c);
+ }
+ return chunks.toArray(new Chunk[chunks.size()]);
}
/**
* Called by the parser whenever a chunk is found.
*/
public void record(Chunk chunk) {
- if(chunk.getChunkId() == MAPIProperty.MESSAGE_CLASS.id) {
+ // Work out what MAPIProperty this corresponds to
+ MAPIProperty prop = MAPIProperty.get(chunk.getChunkId());
+
+ // Assign it for easy lookup, as best we can
+ if(prop == MAPIProperty.MESSAGE_CLASS) {
messageClass = (StringChunk)chunk;
}
- else if(chunk.getChunkId() == MAPIProperty.INTERNET_MESSAGE_ID.id) {
+ else if(prop == MAPIProperty.INTERNET_MESSAGE_ID) {
messageId = (StringChunk)chunk;
}
- else if(chunk.getChunkId() == MAPIProperty.MESSAGE_SUBMISSION_ID.id) {
+ else if(prop == MAPIProperty.MESSAGE_SUBMISSION_ID) {
// TODO - parse
submissionChunk = (MessageSubmissionChunk)chunk;
}
- else if(chunk.getChunkId() == MAPIProperty.RECEIVED_BY_ADDRTYPE.id) {
+ else if(prop == MAPIProperty.RECEIVED_BY_ADDRTYPE) {
sentByServerType = (StringChunk)chunk;
}
- else if(chunk.getChunkId() == MAPIProperty.TRANSPORT_MESSAGE_HEADERS.id) {
+ else if(prop == MAPIProperty.TRANSPORT_MESSAGE_HEADERS) {
messageHeaders = (StringChunk)chunk;
}
- else if(chunk.getChunkId() == MAPIProperty.CONVERSATION_TOPIC.id) {
+ else if(prop == MAPIProperty.CONVERSATION_TOPIC) {
conversationTopic = (StringChunk)chunk;
}
- else if(chunk.getChunkId() == MAPIProperty.SUBJECT.id) {
+ else if(prop == MAPIProperty.SUBJECT) {
subjectChunk = (StringChunk)chunk;
}
- else if(chunk.getChunkId() == MAPIProperty.ORIGINAL_SUBJECT.id) {
+ else if(prop == MAPIProperty.ORIGINAL_SUBJECT) {
// TODO
}
- else if(chunk.getChunkId() == MAPIProperty.DISPLAY_TO.id) {
+ else if(prop == MAPIProperty.DISPLAY_TO) {
displayToChunk = (StringChunk)chunk;
}
- else if(chunk.getChunkId() == MAPIProperty.DISPLAY_CC.id) {
+ else if(prop == MAPIProperty.DISPLAY_CC) {
displayCCChunk = (StringChunk)chunk;
}
- else if(chunk.getChunkId() == MAPIProperty.DISPLAY_BCC.id) {
+ else if(prop == MAPIProperty.DISPLAY_BCC) {
displayBCCChunk = (StringChunk)chunk;
}
- else if(chunk.getChunkId() == MAPIProperty.SENDER_EMAIL_ADDRESS.id) {
+ else if(prop == MAPIProperty.SENDER_EMAIL_ADDRESS) {
emailFromChunk = (StringChunk)chunk;
}
- else if(chunk.getChunkId() == MAPIProperty.SENDER_NAME.id) {
+ else if(prop == MAPIProperty.SENDER_NAME) {
displayFromChunk = (StringChunk)chunk;
}
- else if(chunk.getChunkId() == MAPIProperty.BODY.id) {
+ else if(prop == MAPIProperty.BODY) {
textBodyChunk = (StringChunk)chunk;
}
- else if(chunk.getChunkId() == MAPIProperty.BODY_HTML.id) {
+ else if(prop == MAPIProperty.BODY_HTML) {
if(chunk instanceof StringChunk) {
htmlBodyChunkString = (StringChunk)chunk;
}
htmlBodyChunkBinary = (ByteChunk)chunk;
}
}
- else if(chunk.getChunkId() == MAPIProperty.RTF_COMPRESSED.id) {
+ else if(prop == MAPIProperty.RTF_COMPRESSED) {
rtfBodyChunk = (ByteChunk)chunk;
}
- else if(chunk.getChunkId() == MAPIProperty.UNKNOWN.id &&
- chunk instanceof MessagePropertiesChunk) {
- // TODO Should we maybe collect the contents of this?
+ else if(chunk instanceof MessagePropertiesChunk) {
messageProperties = (MessagePropertiesChunk) chunk;
}
// And add to the main list
- allChunks.add(chunk);
+ if (allChunks.get(prop) == null) {
+ allChunks.put(prop, new ArrayList<Chunk>());
+ }
+ allChunks.get(prop).add(chunk);
+ }
+
+ public void chunksComplete() {
+ // TODO Match variable sized properties to their chunks + index
}
}
private long recipientCount;
private long attachmentCount;
- public MessagePropertiesChunk() {
- super();
+ public MessagePropertiesChunk(ChunkGroup parentGroup) {
+ super(parentGroup);
}
public long getNextRecipientId() {
public void record(Chunk chunk) {
allChunks.add(chunk);
}
+
+ /**
+ * Used to flag that all the chunks of the NameID
+ * have now been located.
+ */
+ public void chunksComplete() {
+ // Currently, we don't need to do anything special once
+ // all the chunks have been located
+ }
}
import java.util.List;
import java.util.Map;
+import org.apache.poi.hsmf.datatypes.PropertyValue.LongLongPropertyValue;
+import org.apache.poi.hsmf.datatypes.PropertyValue.TimePropertyValue;
import org.apache.poi.hsmf.datatypes.Types.MAPIType;
-import org.apache.poi.hsmf.datatypes.PropertyValue.*;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndian.BufferUnderrunException;
private Map<MAPIProperty, List<PropertyValue>> properties =
new HashMap<MAPIProperty, List<PropertyValue>>();
+ /**
+ * The ChunkGroup that these properties apply to. Used when
+ * matching chunks to variable sized properties
+ * TODO Make use of this
+ */
+ private ChunkGroup parentGroup;
+
/**
* Creates a Properties Chunk.
*/
- protected PropertiesChunk() {
+ protected PropertiesChunk(ChunkGroup parentGroup) {
super(NAME, -1, Types.UNKNOWN);
+ this.parentGroup = parentGroup;
}
@Override
// Wrap and store
PropertyValue propVal = null;
if (isPointer) {
- // TODO Pointer type which can do lookup
+ propVal = new ChunkBasedPropertyValue(prop, flags, data);
}
else if (type == Types.LONG_LONG) {
propVal = new LongLongPropertyValue(prop, flags, data);
* as in recipientNameChunk
*/
public StringChunk recipientDisplayNameChunk;
-
+ /**
+ * Holds the fixed sized properties, and the
+ * pointers to the data of variable sized ones
+ */
+ private PropertiesChunk recipientProperties;
public RecipientChunks(String name) {
recipientNumber = -1;
else if(chunk.getChunkId() == DELIVERY_TYPE.id) {
deliveryTypeChunk = (StringChunk)chunk;
}
+ else if(chunk instanceof PropertiesChunk) {
+ recipientProperties = (PropertiesChunk) chunk;
+ }
// And add to the main list
allChunks.add(chunk);
}
+ public void chunksComplete() {
+ // TODO Match variable sized properties to their chunks + index
+ }
+
/**
* Orders by the recipient number.
*/
* This only has a 8 byte header
*/
public class StoragePropertiesChunk extends PropertiesChunk {
- public StoragePropertiesChunk() {
- super();
+ public StoragePropertiesChunk(ChunkGroup parentGroup) {
+ super(parentGroup);
}
@Override
// Now do the top level chunks
processChunks(node, mainChunks);
+ // All chunks are now processed, have the ChunkGroup
+ // match up variable-length properties and their chunks
+ for (ChunkGroup group : groups) {
+ // TODO
+ }
+
// Finish
return groups.toArray(new ChunkGroup[groups.size()]);
}
if (entryName.equals(PropertiesChunk.NAME)) {
if (grouping instanceof Chunks) {
// These should be the properties for the message itself
- chunk = new MessagePropertiesChunk();
+ chunk = new MessagePropertiesChunk(grouping);
} else {
// Will be properties on an attachment or recipient
- chunk = new StoragePropertiesChunk();
+ chunk = new StoragePropertiesChunk(grouping);
}
} else {
// Check it's a regular chunk