X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=lib%2Fmessage-file.c;h=915aba8bf97bb1b1e1251c3a3c4a161d81912bd8;hp=0c152a3973ac719a8dc7bf51f1050c8a52604ceb;hb=0c950146a14fa2bb0a0bf542073b2cdca141afd1;hpb=8cbb5114a20c1217f23977fd5edca99a0b7a2955 diff --git a/lib/message-file.c b/lib/message-file.c index 0c152a39..915aba8b 100644 --- a/lib/message-file.c +++ b/lib/message-file.c @@ -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,44 @@ 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 (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 = xmalloc(hdrsofar + newhdr + 2); + strncpy(combined_header,header_sofar,hdrsofar); + *(combined_header+hdrsofar) = ' '; + strncpy(combined_header+hdrsofar+1,decoded_value,newhdr+1); + 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); + free (decoded_value); + decoded_value = header_sofar; + } } - 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 +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. */