From ac30449867320bd59e2158722ce47e4b62ae54b0 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 29 Aug 2024 17:42:19 +0200 Subject: [PATCH] tools: Improve rfc822parse to allow access to headers for longer. * tools/rfc822parse.c (struct rfc822parse_context): Add field this_part. (release_handle_data): Clear this_part. (rfc822parse_open): Set this_part. (set_current_part_to_parent): Ditto. (insert_header): Ditto. (rfc822parse_enum_header_lines): Replace current_part by this_part. (find_header): Ditto. * tools/rfc822parse.c (my_strcasecmp): Remove. (same_header_name): New. (rfc822_capitalize_header_name): Use new function instead. -- With this change the header function can now be sued after the transition to the body. Thus up until thenext MIME block is reached the headers of the former MIME block are returned. This also fixes a problem with the "MIME-Version" header name capitalization. --- tools/rfc822parse.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/tools/rfc822parse.c b/tools/rfc822parse.c index 4d0668007..5aa233b12 100644 --- a/tools/rfc822parse.c +++ b/tools/rfc822parse.c @@ -100,6 +100,8 @@ struct rfc822parse_context int in_preamble; /* Whether we are before the first boundary. */ part_t parts; /* The tree of parts. */ part_t current_part; /* Whom we are processing (points into parts). */ + part_t this_part; /* Same as current_part but kept until new + * headers are processed. */ const char *boundary; /* Current boundary. */ }; @@ -147,19 +149,21 @@ my_toupper (int c) return c; } -/* This is the same as ascii_strcasecmp. */ +/* This is like ascii_strcasecmp but stops at the first colon and + * returns true if A and B are the same. */ static int -my_strcasecmp (const char *a, const char *b) +same_header_name (const char *a, const char *b) { if (a == b) - return 0; + return 1; - for (; *a && *b; a++, b++) - { - if (*a != *b && my_toupper(*a) != my_toupper(*b)) - break; - } - return *a == *b? 0 : (my_toupper (*a) - my_toupper (*b)); + for (; *a && *a != ':' && *b && *b != ':' + && (*a == *b || my_toupper(*a) == my_toupper(*b)); a++,b++) + ; + if ((!*a || *a == ':') && (!*b || *b == ':')) + return 1; + + return 0; } @@ -234,6 +238,7 @@ release_handle_data (rfc822parse_t msg) release_part (msg->parts); msg->parts = NULL; msg->current_part = NULL; + msg->this_part = NULL; msg->boundary = NULL; } @@ -279,9 +284,9 @@ rfc822_capitalize_header_name (char *name) int first = 1; /* Special cases first. */ - if (!my_strcasecmp (name, "MIME-Version")) + if (same_header_name (name, "MIME-Version")) { - strcpy (name, "MIME-Version"); + memcpy (name, "MIME-Version", 12); return; } @@ -328,7 +333,7 @@ rfc822parse_open (rfc822parse_cb_t cb, void *cb_value) rfc822parse_t msg = calloc (1, sizeof *msg); if (msg) { - msg->parts = msg->current_part = new_part (); + msg->parts = msg->current_part = msg->this_part = new_part (); if (!msg->parts) { free (msg); @@ -411,7 +416,7 @@ set_current_part_to_parent (rfc822parse_t msg) assert (part); } #endif - msg->current_part = parent; + msg->current_part = msg->this_part = parent; parent = find_parent (msg->parts, parent); msg->boundary = parent? parent->boundary: NULL; @@ -559,6 +564,8 @@ insert_header (rfc822parse_t msg, const unsigned char *line, size_t length) * every Received header. */ if (length >= 9 && !memcmp (line, "Received:", 9)) do_callback (msg, RFC822PARSE_RCVD_SEEN); + + msg->this_part = msg->current_part; return 0; } @@ -718,14 +725,15 @@ const char * rfc822parse_enum_header_lines (rfc822parse_t msg, void **context) { HDR_LINE l; + part_t part; if (!msg) /* Close. */ return NULL; - if (*context == msg || !msg->current_part) + if (*context == msg || !msg->this_part) return NULL; - l = *context ? (HDR_LINE) *context : msg->current_part->hdr_lines; + l = *context ? (HDR_LINE) *context : msg->this_part->hdr_lines; if (l) { @@ -759,7 +767,7 @@ find_header (rfc822parse_t msg, const char *name, int which, HDR_LINE *rprev) int found = 0; int glob = 0; - if (!msg->current_part) + if (!msg->this_part) return NULL; namelen = strlen (name); @@ -769,7 +777,7 @@ find_header (rfc822parse_t msg, const char *name, int which, HDR_LINE *rprev) glob = 1; } - hdr = msg->current_part->hdr_lines; + hdr = msg->this_part->hdr_lines; if (rprev && *rprev) { /* spool forward to the requested starting place.