aboutsummaryrefslogtreecommitdiffstats
path: root/tools/rfc822parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/rfc822parse.c')
-rw-r--r--tools/rfc822parse.c51
1 files changed, 49 insertions, 2 deletions
diff --git a/tools/rfc822parse.c b/tools/rfc822parse.c
index ac6ecb17c..4d0668007 100644
--- a/tools/rfc822parse.c
+++ b/tools/rfc822parse.c
@@ -86,6 +86,7 @@ struct part
struct part *down; /* A contained part. */
HDR_LINE hdr_lines; /* Header lines os that part. */
HDR_LINE *hdr_lines_tail; /* Helper for adding lines. */
+ const char *last_hdr_line;/* NULL or a ptr to the last inserted hdr. */
char *boundary; /* Only used in the first part. */
};
typedef struct part *part_t;
@@ -237,6 +238,15 @@ release_handle_data (rfc822parse_t msg)
}
+/* Wrapper around free becuase in this moulde we use a plain free. */
+void
+rfc822_free (void *a)
+{
+ if (a)
+ free (a);
+}
+
+
/* Check that the header name is valid. We allow all lower and
* uppercase letters and, except for the first character, digits and
* the dash. The check stops at the first colon or at string end.
@@ -292,6 +302,22 @@ rfc822_capitalize_header_name (char *name)
}
+/* This is an strcmp which considers a colon also as end-of-string.
+ * Use this function to compare capitalized header names. */
+int
+rfc822_cmp_header_name (const char *a, const char *b)
+{
+ for (; *a && *a != ':' && *b && *b != ':'; a++, b++)
+ {
+ if (*a != *b )
+ break;
+ }
+ if (*a == *b || (!*a && *b == ':') || (!*b && *a == ':'))
+ return 0;
+ else
+ return (*(signed char *)a - *(signed char *)b);
+}
+
/* Create a new parsing context for an entire rfc822 message and
return it. CB and CB_VALUE may be given to callback for certain
@@ -488,6 +514,7 @@ static int
insert_header (rfc822parse_t msg, const unsigned char *line, size_t length)
{
HDR_LINE hdr;
+ int new_hdr = 0;
if (!msg->current_part)
{
@@ -515,11 +542,19 @@ insert_header (rfc822parse_t msg, const unsigned char *line, size_t length)
/* Transform a field name into canonical format. */
if (!hdr->cont && strchr (line, ':'))
- rfc822_capitalize_header_name (hdr->line);
+ {
+ rfc822_capitalize_header_name (hdr->line);
+ msg->current_part->last_hdr_line = hdr->line;
+ new_hdr = 1;
+ }
+ else
+ msg->current_part->last_hdr_line = NULL;
*msg->current_part->hdr_lines_tail = hdr;
msg->current_part->hdr_lines_tail = &hdr->next;
+ if (new_hdr)
+ do_callback (msg, RFC822PARSE_HEADER_SEEN);
/* Lets help the caller to prevent mail loops and issue an event for
* every Received header. */
if (length >= 9 && !memcmp (line, "Received:", 9))
@@ -588,6 +623,18 @@ rfc822parse_finish (rfc822parse_t msg)
}
+/* If the last inserted line was a header and not a continuation of a
+ * header line, return a pointer to that line. This function may be
+ * used on the RFC822PARSE_HEADER_SEEN event to get the name of the
+ * current header. Returns NULL if no header is available. */
+const char *
+rfc822parse_last_header_line (rfc822parse_t msg)
+{
+ if (!msg || !msg->current_part)
+ return NULL;
+ return msg->current_part->last_hdr_line;
+}
+
/****************
* Get a copy of a header line. The line is returned as one long
@@ -697,7 +744,7 @@ rfc822parse_enum_header_lines (rfc822parse_t msg, void **context)
*
* which -1 : Retrieve the last field
* >0 : Retrieve the n-th field
-
+ *
* RPREV may be used to return the predecessor of the returned field;
* which may be NULL for the very first one. It has to be initialized
* to either NULL in which case the search start at the first header line,