You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ni...@apache.org on 2010/01/08 14:42:54 UTC

svn commit: r897201 - in /poi/trunk/src/scratchpad: src/org/apache/poi/hsmf/ src/org/apache/poi/hsmf/datatypes/ src/org/apache/poi/hsmf/parsers/ testcases/org/apache/poi/hsmf/parsers/

Author: nick
Date: Fri Jan  8 13:42:53 2010
New Revision: 897201

URL: http://svn.apache.org/viewvc?rev=897201&view=rev
Log:
Support fetching the message date from the submission id

Added:
    poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/MessageSubmissionChunk.java
Modified:
    poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/ByteChunk.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java
    poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java
    poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/parsers/TestPOIFSChunkParser.java

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java?rev=897201&r1=897200&r2=897201&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java Fri Jan  8 13:42:53 2010
@@ -22,6 +22,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Calendar;
 
 import org.apache.poi.hsmf.datatypes.AttachmentChunks;
 import org.apache.poi.hsmf.datatypes.ChunkGroup;
@@ -192,6 +193,17 @@
 	public String getMessageClass() throws ChunkNotFoundException {
 		return getStringFromChunk(mainChunks.messageClass);
 	}
+	
+	/**
+	 * Gets the date that the message was accepted by the
+	 *  server on.
+	 */
+	public Calendar getMessageDate() throws ChunkNotFoundException {
+	   if(mainChunks.submissionChunk != null) {
+	      return mainChunks.submissionChunk.getAcceptedAtTime();
+	   }
+	   throw new ChunkNotFoundException();
+	}
 
 	
 	/**

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/ByteChunk.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/ByteChunk.java?rev=897201&r1=897200&r2=897201&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/ByteChunk.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/ByteChunk.java Fri Jan  8 13:42:53 2010
@@ -23,7 +23,11 @@
 import org.apache.poi.util.IOUtils;
 
 /**
- * A Chunk made up of a ByteArrayOutputStream.
+ * A Chunk that holds binary data, normally
+ *  unparsed.
+ * Generally as we know how to make sense of the
+ *  contents, we create a new Chunk class and add
+ *  a special case in the parser for them.
  */
 
 public class ByteChunk extends Chunk {

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java?rev=897201&r1=897200&r2=897201&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/Chunks.java Fri Jan  8 13:42:53 2010
@@ -30,7 +30,9 @@
    /* String parts of Outlook Messages that are currently known */
    public static final int MESSAGE_CLASS       = 0x001A;
    public static final int SUBJECT             = 0x0037;
-   public static final int DATE                = 0x0047;
+   // "PidTagMessageSubmissionId" as given by accepting server
+   public static final int SUBMISSION_ID_DATE  = 0x0047;
+   // 0x0050 -> 0x006F seem to be routing info or similar
    public static final int CONVERSATION_TOPIC  = 0x0070;
    public static final int SENT_BY_SERVER_TYPE = 0x0075;
    // RECEIVEDEMAIL = 76
@@ -39,7 +41,9 @@
    public static final int EMAIL_FROM          = 0x0C1F;
    public static final int DISPLAY_CC          = 0x0E03;
    public static final int DISPLAY_BCC         = 0x0E02;
+   // 0x0E1D seems a duplicate of 0x0070 !
    public static final int TEXT_BODY           = 0x1000;
+   public static final int MESSAGE_ID          = 0x1035;
    
    /** Holds all the chunks that were found. */
    private List<Chunk> allChunks = new ArrayList<Chunk>();
@@ -63,9 +67,11 @@
    /** Type of server that the message originated from (SMTP, etc). */
    public StringChunk sentByServerType;
    /** TODO */
-   public ByteChunk dateChunk; 
+   public MessageSubmissionChunk submissionChunk; 
    /** TODO */
    public StringChunk emailFromChunk; 
+   /** The message ID */
+   public StringChunk messageId;
 
    public Chunk[] getAll() {
       return allChunks.toArray(new Chunk[allChunks.size()]);
@@ -82,12 +88,15 @@
       case MESSAGE_CLASS:
          messageClass = (StringChunk)chunk;
          break;
+      case MESSAGE_ID:
+         messageId = (StringChunk)chunk;
+         break;
       case SUBJECT:
          subjectChunk = (StringChunk)chunk;
          break;
-      case DATE:
+      case SUBMISSION_ID_DATE:
          // TODO - parse
-         dateChunk = (ByteChunk)chunk;
+         submissionChunk = (MessageSubmissionChunk)chunk;
          break;
       case CONVERSATION_TOPIC:
          conversationTopic = (StringChunk)chunk;

Added: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/MessageSubmissionChunk.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/MessageSubmissionChunk.java?rev=897201&view=auto
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/MessageSubmissionChunk.java (added)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/datatypes/MessageSubmissionChunk.java Fri Jan  8 13:42:53 2010
@@ -0,0 +1,121 @@
+/* ====================================================================
+   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;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Calendar;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.poi.util.IOUtils;
+
+/**
+ * A Chunk that holds the details given back by the
+ *  server at submission time.
+ * This includes the date the message was given to the
+ *  server, and an ID that's used if you want to cancel
+ *  a message or similar
+ */
+
+public class MessageSubmissionChunk extends Chunk {
+	private String rawId;
+	private Calendar date;
+	
+	private static final Pattern datePatern = 
+	   Pattern.compile("(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)(\\d\\d)Z?"); 
+	
+	/**
+	 * Creates a Byte Chunk.
+	 */
+	public MessageSubmissionChunk(String entryName) {
+		super(entryName);
+	}
+	
+	/**
+	 * Create a Byte Chunk, with the specified
+	 *  type.
+	 */
+	public MessageSubmissionChunk(int chunkId, int type) {
+	   super(chunkId, type);
+	}
+
+   public void readValue(InputStream value) throws IOException {
+      // Stored in the file as us-ascii
+      try {
+         byte[] data = IOUtils.toByteArray(value); 
+         rawId = new String(data, "ASCII");
+      } catch(UnsupportedEncodingException e) {
+         throw new RuntimeException("Core encoding not found, JVM broken?", e);
+      }
+      
+      // Now process the date
+      String[] parts = rawId.split(";");
+      for(String part : parts) {
+         if(part.startsWith("l=")) {
+            // Format of this bit appears to be l=<id>-<time>-<number>
+            if(part.indexOf('-') != -1 && 
+                  part.indexOf('-') != part.lastIndexOf('-')) {
+               String dateS = part.substring(part.indexOf('-')+1, part.lastIndexOf('-'));
+               
+               // Should be yymmddhhmmssZ
+               Matcher m = datePatern.matcher(dateS);
+               if(m.matches()) {
+                  date = Calendar.getInstance();
+                  date.set(Calendar.YEAR,  Integer.parseInt(m.group(1)) + 2000);
+                  date.set(Calendar.MONTH, Integer.parseInt(m.group(2)) - 1); // Java is 0 based
+                  date.set(Calendar.DATE,  Integer.parseInt(m.group(3)));
+                  date.set(Calendar.HOUR_OF_DAY, Integer.parseInt(m.group(4)));
+                  date.set(Calendar.MINUTE,      Integer.parseInt(m.group(5)));
+                  date.set(Calendar.SECOND,      Integer.parseInt(m.group(6)));
+                  date.set(Calendar.MILLISECOND, 0);
+               } else {
+                  System.err.println("Warning - unable to make sense of date " + dateS);
+               }
+            }
+         }
+      }
+   }
+
+   public void writeValue(OutputStream out) throws IOException {
+      try {
+         byte[] data = rawId.getBytes("ASCII"); 
+         out.write(data);
+      } catch(UnsupportedEncodingException e) {
+         throw new RuntimeException("Core encoding not found, JVM broken?", e);
+      }
+   }
+   
+   /**
+    * Returns the date that the server accepted the
+    *  message, as found from the message ID it generated.
+    * @return
+    */
+   public Calendar getAcceptedAtTime() {
+      return date;
+   }
+   
+   /**
+    * Returns the full ID that the server generated when
+    *  it accepted the message.
+    */
+   public String getSubmissionId() {
+      return rawId;
+   }
+}

Modified: poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java?rev=897201&r1=897200&r2=897201&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java (original)
+++ poi/trunk/src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java Fri Jan  8 13:42:53 2010
@@ -25,6 +25,7 @@
 import org.apache.poi.hsmf.datatypes.Chunk;
 import org.apache.poi.hsmf.datatypes.ChunkGroup;
 import org.apache.poi.hsmf.datatypes.Chunks;
+import org.apache.poi.hsmf.datatypes.MessageSubmissionChunk;
 import org.apache.poi.hsmf.datatypes.NameIdChunks;
 import org.apache.poi.hsmf.datatypes.RecipientChunks;
 import org.apache.poi.hsmf.datatypes.StringChunk;
@@ -111,19 +112,31 @@
       }
       
       // See if we can get a type for it
-      String ending = entry.getName().substring(entry.getName().length()-4);
+      String idType = entry.getName().substring(entry.getName().length()-8);
+      String idS = idType.substring(0, 4);
+      String typeS = idType.substring(4); 
       try {
-         int type = Integer.parseInt(ending, 16);
+         int id = Integer.parseInt(idS, 16);
+         int type = Integer.parseInt(typeS, 16);
          Chunk chunk = null;
          
-         switch(type) {
-         case Types.BINARY:
-            chunk = new ByteChunk(entry.getName());
-            break;
-         case Types.ASCII_STRING:
-         case Types.UNICODE_STRING:
-            chunk = new StringChunk(entry.getName());
+         // Special cases based on the ID
+         switch(id) {
+         case Chunks.SUBMISSION_ID_DATE:
+            chunk = new MessageSubmissionChunk(entry.getName());
             break;
+         default:
+            // Nothing special about this ID
+            // So, do the usual thing which is by type
+            switch(type) {
+            case Types.BINARY:
+               chunk = new ByteChunk(entry.getName());
+               break;
+            case Types.ASCII_STRING:
+            case Types.UNICODE_STRING:
+               chunk = new StringChunk(entry.getName());
+               break;
+            }
          }
          
          if(chunk != null) {

Modified: poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/parsers/TestPOIFSChunkParser.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/parsers/TestPOIFSChunkParser.java?rev=897201&r1=897200&r2=897201&view=diff
==============================================================================
--- poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/parsers/TestPOIFSChunkParser.java (original)
+++ poi/trunk/src/scratchpad/testcases/org/apache/poi/hsmf/parsers/TestPOIFSChunkParser.java Fri Jan  8 13:42:53 2010
@@ -20,6 +20,8 @@
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
 
 import org.apache.poi.hsmf.MAPIMessage;
 import org.apache.poi.hsmf.datatypes.AttachmentChunks;
@@ -67,6 +69,16 @@
       } catch(ChunkNotFoundException e) {
          fail();
       }
+      
+      // Check date too
+      try {
+         SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+         
+         Calendar c = msg.getMessageDate();
+         assertEquals( "2007-06-14 09:42:55", f.format(c.getTime()) );
+      } catch(ChunkNotFoundException e) {
+         fail();
+      }
    }
    
    public void testFindsRecips() throws IOException {



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