]> git.notmuchmail.org Git - notmuch/blobdiff - lib/message-file.c
util: Fix two corner-cases in boolean term quoting function
[notmuch] / lib / message-file.c
index 75caba6d8b055e5c3b57b2d72d1926381ff11fc8..a2850c278b5a10ba9a5041a6662aab4ed09e3861 100644 (file)
@@ -111,7 +111,7 @@ _notmuch_message_file_open_ctx (void *ctx, const char *filename)
     message->headers = g_hash_table_new_full (strcase_hash,
                                              strcase_equal,
                                              free,
-                                             free);
+                                             g_free);
 
     message->parsing_started = 0;
     message->parsing_finished = 0;
@@ -209,19 +209,26 @@ 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);
+       g_mime_init (GMIME_ENABLE_RFC2047_WORKAROUNDS);
        initialized = 1;
     }
 
@@ -238,7 +245,7 @@ notmuch_message_file_get_header (notmuch_message_file_t *message,
        return decoded_value;
 
     if (message->parsing_finished)
-       return NULL;
+       return "";
 
 #define NEXT_HEADER_LINE(closure)                              \
     while (1) {                                                        \
@@ -282,7 +289,7 @@ notmuch_message_file_get_header (notmuch_message_file_t *message,
                message->good_headers < 5)
            {
                message->parsing_finished = 1;
-               continue;
+               break;
            }
            NEXT_HEADER_LINE (NULL);
            continue;
@@ -312,19 +319,52 @@ 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);
-
-       g_hash_table_insert (message->headers, header, decoded_value);
-
-       if (match)
+       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 (strcasecmp(header, "received") == 0) {
+           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 = g_malloc(hdrsofar + newhdr + 2);
+               strncpy(combined_header,header_sofar,hdrsofar);
+               *(combined_header+hdrsofar) = ' ';
+               strncpy(combined_header+hdrsofar+1,decoded_value,newhdr+1);
+               g_free (decoded_value);
+               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);
+           } else {
+               free (header);
+               g_free (decoded_value);
+               decoded_value = header_sofar;
+           }
+       }
+       /* 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;
     }
 
+    if (message->parsing_finished) {
+        fclose (message->file);
+        message->file = NULL;
+    }
+
     if (message->line)
        free (message->line);
     message->line = NULL;
@@ -336,6 +376,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. */
@@ -348,5 +396,5 @@ notmuch_message_file_get_header (notmuch_message_file_t *message,
                        header_desired);
     }
 
-    return NULL;
+    return "";
 }