From f03928b16c4fb00077d22d8ec141575ef6d26913 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 15 Oct 2018 11:32:19 +0200 Subject: [PATCH] tools: Replace duplicated code in mime-maker. * tools/rfc822parse.c (HEADER_NAME_CHARS): New. Taken from mime-maker.c. (rfc822_valid_header_name_p): New. Based on code from mime-maker.c. (rfc822_capitalize_header_name): New. Copied from mime-maker.c. (capitalize_header_name): Remove. Replace calls by new func. (my_toupper, my_strcasecmp): New. * tools/mime-maker.c: Include rfc822parse.h. (HEADER_NAME_CHARS, capitalize_header_name): Remove. (add_header): Replace check and capitalization by new functions. -- This is a straightforward change with two minor chnages: - In rfc822parse.c the capitalization handles MIME-Version special. - The check in mime-maker bow detects a zero-length name as invalid. my_toupper and my_strcasecmp are introduced to allow standalone use of that file. Signed-off-by: Werner Koch --- tools/mime-maker.c | 47 ++------------------ tools/rfc822parse.c | 105 +++++++++++++++++++++++++++++++++++--------- tools/rfc822parse.h | 2 + 3 files changed, 91 insertions(+), 63 deletions(-) diff --git a/tools/mime-maker.c b/tools/mime-maker.c index 0edc14d78..91eab8258 100644 --- a/tools/mime-maker.c +++ b/tools/mime-maker.c @@ -25,14 +25,10 @@ #include "../common/util.h" #include "../common/zb32.h" +#include "rfc822parse.h" #include "mime-maker.h" -/* All valid characters in a header name. */ -#define HEADER_NAME_CHARS ("abcdefghijklmnopqrstuvwxyz" \ - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ - "-01234567890") - /* An object to store an header. Also used for a list of headers. */ struct header_s { @@ -269,38 +265,6 @@ ensure_part (mime_maker_t ctx, part_t *r_parent) } -/* Transform a header name into a standard capitalized format. - * "Content-Type". Conversion stops at the colon. */ -static void -capitalize_header_name (char *name) -{ - unsigned char *p = name; - int first = 1; - - /* Special cases first. */ - if (!ascii_strcasecmp (name, "MIME-Version")) - { - strcpy (name, "MIME-Version"); - return; - } - - /* Regular cases. */ - for (; *p && *p != ':'; p++) - { - if (*p == '-') - first = 1; - else if (first) - { - if (*p >= 'a' && *p <= 'z') - *p = *p - 'a' + 'A'; - first = 0; - } - else if (*p >= 'A' && *p <= 'Z') - *p = *p - 'A' + 'a'; - } -} - - /* Check whether a header with NAME has already been set into PART. * NAME must be in canonical capitalized format. Return true or * false. */ @@ -344,17 +308,14 @@ add_header (part_t part, const char *name, const char *value) memcpy (hdr->name, name, namelen); hdr->name[namelen] = 0; - /* Check that the header name is valid. We allow all lower and - * uppercase letters and, except for the first character, digits and - * the dash. */ - if (strspn (hdr->name, HEADER_NAME_CHARS) != namelen - || strchr ("-0123456789", *hdr->name)) + /* Check that the header name is valid. */ + if (!rfc822_valid_header_name_p (hdr->name)) { xfree (hdr); return gpg_error (GPG_ERR_INV_NAME); } - capitalize_header_name (hdr->name); + rfc822_capitalize_header_name (hdr->name); hdr->value = xtrystrdup (value); if (!hdr->value) { diff --git a/tools/rfc822parse.c b/tools/rfc822parse.c index e8cdb0215..0a4e2bc94 100644 --- a/tools/rfc822parse.c +++ b/tools/rfc822parse.c @@ -41,6 +41,12 @@ #include "rfc822parse.h" +/* All valid characters in a header name. */ +#define HEADER_NAME_CHARS ("abcdefghijklmnopqrstuvwxyz" \ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ + "-01234567890") + + enum token_type { tSPACE, @@ -131,28 +137,31 @@ lowercase_string (unsigned char *string) *string = *string - 'A' + 'a'; } -/* Transform a header name into a standard capitalized format; i.e - "Content-Type". Conversion stops at the colon. As usual we don't - use the localized versions of ctype.h. - */ -static void -capitalize_header_name (unsigned char *name) -{ - int first = 1; - for (; *name && *name != ':'; name++) - if (*name == '-') - first = 1; - else if (first) - { - if (*name >= 'a' && *name <= 'z') - *name = *name - 'a' + 'A'; - first = 0; - } - else if (*name >= 'A' && *name <= 'Z') - *name = *name - 'A' + 'a'; +static int +my_toupper (int c) +{ + if (c >= 'a' && c <= 'z') + c &= ~0x20; + return c; } +/* This is the same as ascii_strcasecmp. */ +static int +my_strcasecmp (const char *a, const char *b) +{ + if (a == b) + return 0; + + 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)); +} + + #ifndef HAVE_STPCPY static char * my_stpcpy (char *a,const char *b) @@ -228,6 +237,62 @@ release_handle_data (rfc822parse_t msg) } +/* 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. + * Returns true if the name is valid. */ +int +rfc822_valid_header_name_p (const char *name) +{ + const char *s; + size_t namelen; + + if ((s=strchr (name, ':'))) + namelen = s - name; + else + namelen = strlen (name); + + if (!namelen + || strspn (name, HEADER_NAME_CHARS) != namelen + || strchr ("-0123456789", *name)) + return 0; + return 1; +} + + +/* Transform a header NAME into a standard capitalized format. + * Conversion stops at the colon. */ +void +rfc822_capitalize_header_name (char *name) +{ + unsigned char *p = name; + int first = 1; + + /* Special cases first. */ + if (!my_strcasecmp (name, "MIME-Version")) + { + strcpy (name, "MIME-Version"); + return; + } + + /* Regular cases. */ + for (; *p && *p != ':'; p++) + { + if (*p == '-') + first = 1; + else if (first) + { + if (*p >= 'a' && *p <= 'z') + *p = *p - 'a' + 'A'; + first = 0; + } + else if (*p >= 'A' && *p <= 'Z') + *p = *p - 'A' + 'a'; + } +} + + + /* Create a new parsing context for an entire rfc822 message and return it. CB and CB_VALUE may be given to callback for certain events. NULL is returned on error with errno set appropriately. */ @@ -432,7 +497,7 @@ insert_header (rfc822parse_t msg, const unsigned char *line, size_t length) /* Transform a field name into canonical format. */ if (!hdr->cont && strchr (line, ':')) - capitalize_header_name (hdr->line); + rfc822_capitalize_header_name (hdr->line); *msg->current_part->hdr_lines_tail = hdr; msg->current_part->hdr_lines_tail = &hdr->next; diff --git a/tools/rfc822parse.h b/tools/rfc822parse.h index 177d8271a..e2f2bedac 100644 --- a/tools/rfc822parse.h +++ b/tools/rfc822parse.h @@ -48,6 +48,8 @@ typedef int (*rfc822parse_cb_t) (void *opaque, rfc822parse_event_t event, rfc822parse_t msg); +int rfc822_valid_header_name_p (const char *name); +void rfc822_capitalize_header_name (char *name); rfc822parse_t rfc822parse_open (rfc822parse_cb_t cb, void *opaque_value);