]> git.notmuchmail.org Git - notmuch/commitdiff
Make Received: header special in notmuch_message_file_get_header
authorDirk Hohndel <hohndel@infradead.org>
Mon, 26 Apr 2010 19:58:34 +0000 (12:58 -0700)
committerCarl Worth <cworth@cworth.org>
Mon, 26 Apr 2010 21:44:06 +0000 (14:44 -0700)
With this patch the Received: header becomes special in the way
we treat headers - this is the only header for which we concatenate
all the instances we find (instead of just returning the first one).

This will be used in the From guessing code for replies as we need to
be able to walk ALL of the Received: headers in a message to have a
good chance to guess which mailbox this email was delivered to.

Signed-off-by: Dirk Hohndel <hohndel@infradead.org>
lib/message-file.c
lib/notmuch-private.h

index 0c152a3973ac719a8dc7bf51f1050c8a52604ceb..7722832e9158411e8101f21cb163f0f0051b9854 100644 (file)
@@ -209,17 +209,24 @@ copy_header_unfolding (header_value_closure_t *value,
 
 /* As a special-case, a value of NULL for header_desired will force
  * the entire header to be parsed if it is not parsed already. This is
- * used by the _notmuch_message_file_get_headers_end function. */
+ * used by the _notmuch_message_file_get_headers_end function.
+ * Another special case is the Received: header. For this header we
+ * want to concatenate all instances of the header instead of just
+ * hashing the first instance as we use this when analyzing the path
+ * the mail has taken from sender to recipient.
+ */
 const char *
 notmuch_message_file_get_header (notmuch_message_file_t *message,
                                 const char *header_desired)
 {
     int contains;
-    char *header, *decoded_value;
+    char *header, *decoded_value, *header_sofar, *combined_header;
     const char *s, *colon;
-    int match;
+    int match, newhdr, hdrsofar, is_received;
     static int initialized = 0;
 
+    is_received = (strcmp(header_desired,"received") == 0);
+
     if (! initialized) {
        g_mime_init (0);
        initialized = 1;
@@ -312,22 +319,39 @@ notmuch_message_file_get_header (notmuch_message_file_t *message,
 
        NEXT_HEADER_LINE (&message->value);
 
-       if (header_desired == 0)
+       if (header_desired == NULL)
            match = 0;
        else
            match = (strcasecmp (header, header_desired) == 0);
 
        decoded_value = g_mime_utils_header_decode_text (message->value.str);
-       if (g_hash_table_lookup (message->headers, header) == NULL) {
-           /* Only insert if we don't have a value for this header, yet.
-            * This way we always return the FIRST instance of any header
-            * we search for
-            * FIXME: we should be returning ALL instances of a header
-            *        or at least provide a way to iterate over them
-            */
-           g_hash_table_insert (message->headers, header, decoded_value);
+       header_sofar = (char *)g_hash_table_lookup (message->headers, header);
+       /* we treat the Received: header special - we want to concat ALL of 
+        * the Received: headers we encounter.
+        * for everything else we return the first instance of a header */
+       if (is_received) {
+           if (header_sofar == NULL) {
+               /* first Received: header we encountered; just add it */
+               g_hash_table_insert (message->headers, header, decoded_value);
+           } else {
+               /* we need to add the header to those we already collected */
+               newhdr = strlen(decoded_value);
+               hdrsofar = strlen(header_sofar);
+               combined_header = xmalloc(hdrsofar + newhdr + 2);
+               strncpy(combined_header,header_sofar,hdrsofar);
+               *(combined_header+hdrsofar) = ' ';
+               strncpy(combined_header+hdrsofar+1,decoded_value,newhdr+1);
+               g_hash_table_insert (message->headers, header, combined_header);
+           }
+       } else {
+           if (header_sofar == NULL) {
+               /* Only insert if we don't have a value for this header, yet. */
+               g_hash_table_insert (message->headers, header, decoded_value);
+           }
        }
-       if (match)
+       /* if we found a match we can bail - unless of course we are
+        * collecting all the Received: headers */
+       if (match && !is_received)
            return decoded_value;
     }
 
@@ -347,6 +371,14 @@ notmuch_message_file_get_header (notmuch_message_file_t *message,
        message->value.len = 0;
     }
 
+    /* For the Received: header we actually might end up here even
+     * though we found the header (as we force continued parsing
+     * in that case). So let's check if that's the header we were
+     * looking for and return the value that we found (if any)
+     */
+    if (is_received)
+       return (char *)g_hash_table_lookup (message->headers, "received");
+
     /* We've parsed all headers and never found the one we're looking
      * for. It's probably just not there, but let's check that we
      * didn't make a mistake preventing us from seeing it. */
index 6e83cc376c2588ea842967fd9bd5b730dc052bbf..3768d6f88d034bd3fe4401fa8993b56d6cd0deb5 100644 (file)
@@ -344,6 +344,9 @@ notmuch_message_file_restrict_headersv (notmuch_message_file_t *message,
  *
  * The header name is case insensitive.
  *
+ * The Received: header is special - for it all Received: headers in
+ * the message are concatenated
+ *
  * The returned value is owned by the notmuch message and is valid
  * only until the message is closed. The caller should copy it if
  * needing to modify the value or to hold onto it for longer.