1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

tools: New support functions for the mail parser.

* tools/rfc822parse.h (RFC822PARSE_HEADER_SEEN): New.
* tools/rfc822parse.c (rfc822_cmp_header_name): New.
(insert_header): Run header seen callback.
(rfc822parse_last_header_line): New.
(rfc822_free): New.
* tools/wks-receive.c (t2body): Use it here.
* tools/mime-parser.c (parse_message_cb): and here.
This commit is contained in:
Werner Koch 2024-06-28 17:50:23 +02:00
parent c4ff9c5def
commit 675b12ddd8
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
6 changed files with 58 additions and 6 deletions

View File

@ -1317,6 +1317,7 @@ gpgtar_create (char **inpattern, const char *files_from, int null_names,
xfree (argv); xfree (argv);
if (err) if (err)
goto leave; goto leave;
/* Note that OUTSTREAM is our tar output which is fed to gpg. */
gnupg_process_get_streams (proc, 0, &outstream, NULL, NULL); gnupg_process_get_streams (proc, 0, &outstream, NULL, NULL);
es_set_binary (outstream); es_set_binary (outstream);
} }

View File

@ -216,8 +216,8 @@ find_part (part_t root, unsigned int partid)
} }
/* Create a boundary string. Outr codes is aware of the general /* Create a boundary string. Our codes is aware of the general
* structure of that string (gebins with "=-=") so that * structure of that string (begins with "=-=") so that
* it can protect against accidentally-used boundaries within the * it can protect against accidentally-used boundaries within the
* content. */ * content. */
static char * static char *

View File

@ -416,7 +416,7 @@ parse_message_cb (void *opaque, rfc822parse_event_t event, rfc822parse_t msg)
if (!ctx->b64state) if (!ctx->b64state)
rc = gpg_error_from_syserror (); rc = gpg_error_from_syserror ();
} }
free (value); /* Right, we need a plain free. */ rfc822_free (value);
} }
} }

View File

@ -86,6 +86,7 @@ struct part
struct part *down; /* A contained part. */ struct part *down; /* A contained part. */
HDR_LINE hdr_lines; /* Header lines os that part. */ HDR_LINE hdr_lines; /* Header lines os that part. */
HDR_LINE *hdr_lines_tail; /* Helper for adding lines. */ 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. */ char *boundary; /* Only used in the first part. */
}; };
typedef struct part *part_t; 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 /* Check that the header name is valid. We allow all lower and
* uppercase letters and, except for the first character, digits and * uppercase letters and, except for the first character, digits and
* the dash. The check stops at the first colon or at string end. * 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 /* Create a new parsing context for an entire rfc822 message and
return it. CB and CB_VALUE may be given to callback for certain 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) insert_header (rfc822parse_t msg, const unsigned char *line, size_t length)
{ {
HDR_LINE hdr; HDR_LINE hdr;
int new_hdr = 0;
if (!msg->current_part) 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. */ /* Transform a field name into canonical format. */
if (!hdr->cont && strchr (line, ':')) 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;
msg->current_part->hdr_lines_tail = &hdr->next; 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 /* Lets help the caller to prevent mail loops and issue an event for
* every Received header. */ * every Received header. */
if (length >= 9 && !memcmp (line, "Received:", 9)) 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 * 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 * which -1 : Retrieve the last field
* >0 : Retrieve the n-th field * >0 : Retrieve the n-th field
*
* RPREV may be used to return the predecessor of the returned 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 * 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, * to either NULL in which case the search start at the first header line,

View File

@ -29,6 +29,7 @@ typedef enum
RFC822PARSE_CANCEL, RFC822PARSE_CANCEL,
RFC822PARSE_T2BODY, RFC822PARSE_T2BODY,
RFC822PARSE_FINISH, RFC822PARSE_FINISH,
RFC822PARSE_HEADER_SEEN,
RFC822PARSE_RCVD_SEEN, RFC822PARSE_RCVD_SEEN,
RFC822PARSE_LEVEL_DOWN, RFC822PARSE_LEVEL_DOWN,
RFC822PARSE_LEVEL_UP, RFC822PARSE_LEVEL_UP,
@ -48,8 +49,10 @@ typedef int (*rfc822parse_cb_t) (void *opaque,
rfc822parse_event_t event, rfc822parse_event_t event,
rfc822parse_t msg); rfc822parse_t msg);
void rfc822_free (void *);
int rfc822_valid_header_name_p (const char *name); int rfc822_valid_header_name_p (const char *name);
void rfc822_capitalize_header_name (char *name); void rfc822_capitalize_header_name (char *name);
int rfc822_cmp_header_name (const char *a, const char *b);
rfc822parse_t rfc822parse_open (rfc822parse_cb_t cb, void *opaque_value); rfc822parse_t rfc822parse_open (rfc822parse_cb_t cb, void *opaque_value);
@ -60,6 +63,7 @@ int rfc822parse_finish (rfc822parse_t msg);
int rfc822parse_insert (rfc822parse_t msg, int rfc822parse_insert (rfc822parse_t msg,
const unsigned char *line, size_t length); const unsigned char *line, size_t length);
const char *rfc822parse_last_header_line (rfc822parse_t msg);
char *rfc822parse_get_field (rfc822parse_t msg, const char *name, int which, char *rfc822parse_get_field (rfc822parse_t msg, const char *name, int which,
size_t *valueoff); size_t *valueoff);

View File

@ -279,7 +279,7 @@ t2body (void *cookie, int level)
{ {
if (atoi(value+valueoff) >= 2 ) if (atoi(value+valueoff) >= 2 )
ctx->draft_version_2 = 1; ctx->draft_version_2 = 1;
free (value); rfc822_free (value);
} }
} }
} }