From a1bedb6db8934e6788075a1e1cda001356cf1d8b Mon Sep 17 00:00:00 2001 Message-Id: From: Mark Wooding Date: Fri, 11 Jan 2008 11:16:54 +0000 Subject: [PATCH] More tests for mime.c Organization: Straylight/Edgeware From: Richard Kettlewell --- lib/mime.c | 38 +++++++++++++++++++------------------- lib/mime.h | 4 ++++ lib/t-mime.c | 27 ++++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/lib/mime.c b/lib/mime.c index 0e7d097..d79cc2a 100644 --- a/lib/mime.c +++ b/lib/mime.c @@ -51,7 +51,7 @@ static int whitespace(int c) { } /** @brief Match RFC2045 tspecial characters */ -static int tspecial(int c) { +int mime_tspecial(int c) { switch(c) { case '(': case ')': @@ -75,7 +75,7 @@ static int tspecial(int c) { } /** @brief Match RFC2616 separator characters */ -static int http_separator(int c) { +int mime_http_separator(int c) { switch(c) { case '(': case ')': @@ -151,7 +151,7 @@ static const char *skipwhite(const char *s, int rfc822_comments) { /** @brief Test for a word character * @param c Character to test - * @param special tspecial() (MIME/RFC2405) or http_separator() (HTTP/RFC2616) + * @param special mime_tspecial() (MIME/RFC2405) or mime_http_separator() (HTTP/RFC2616) * @return 1 if @p c is a word character, else 0 */ static int iswordchar(int c, int (*special)(int)) { @@ -161,13 +161,13 @@ static int iswordchar(int c, int (*special)(int)) { /** @brief Parse an RFC1521/RFC2616 word * @param s Pointer to start of word * @param valuep Where to store value - * @param special tspecial() (MIME/RFC2405) or http_separator() (HTTP/RFC2616) + * @param special mime_tspecial() (MIME/RFC2405) or mime_http_separator() (HTTP/RFC2616) * @return Pointer just after end of word or NULL if there's no word * * A word is a token or a quoted-string. */ -static const char *parseword(const char *s, char **valuep, - int (*special)(int)) { +const char *mime_parse_word(const char *s, char **valuep, + int (*special)(int)) { struct dynstr value[1]; int c; @@ -201,14 +201,14 @@ static const char *parseword(const char *s, char **valuep, /** @brief Parse an RFC1521/RFC2616 token * @param s Pointer to start of token * @param valuep Where to store value - * @param special tspecial() (MIME/RFC2405) or http_separator() (HTTP/RFC2616) + * @param special mime_tspecial() (MIME/RFC2405) or mime_http_separator() (HTTP/RFC2616) * @return Pointer just after end of token or NULL if there's no token */ static const char *parsetoken(const char *s, char **valuep, int (*special)(int)) { if(*s == '"') return 0; - return parseword(s, valuep, special); + return mime_parse_word(s, valuep, special); } /** @brief Parse a MIME content-type field @@ -231,7 +231,7 @@ int mime_content_type(const char *s, return -1; if(!*s) return -1; - while(*s && !tspecial(*s) && !whitespace(*s)) + while(*s && !mime_tspecial(*s) && !whitespace(*s)) dynstr_append(&type, tolower((unsigned char)*s++)); if(!(s = skipwhite(s, 1))) return -1; @@ -240,7 +240,7 @@ int mime_content_type(const char *s, dynstr_append(&type, '/'); if(!(s = skipwhite(s, 1))) return -1; - while(*s && !tspecial(*s) && !whitespace(*s)) + while(*s && !mime_tspecial(*s) && !whitespace(*s)) dynstr_append(&type, tolower((unsigned char)*s++)); if(!(s = skipwhite(s, 1))) return -1; @@ -252,7 +252,7 @@ int mime_content_type(const char *s, return -1; if(!*s) return -1; - while(*s && !tspecial(*s) && !whitespace(*s)) + while(*s && !mime_tspecial(*s) && !whitespace(*s)) dynstr_append(¶metername, tolower((unsigned char)*s++)); if(!(s = skipwhite(s, 1))) return -1; @@ -260,7 +260,7 @@ int mime_content_type(const char *s, return -1; if(!(s = skipwhite(s, 1))) return -1; - if(!(s = parseword(s, ¶metervalue, tspecial))) + if(!(s = mime_parse_word(s, ¶metervalue, mime_tspecial))) return -1; if(!(s = skipwhite(s, 1))) return -1; @@ -294,7 +294,7 @@ const char *mime_parse(const char *s, while(*s && !iscrlf(s)) { dynstr_init(&name); dynstr_init(&value); - while(*s && !tspecial(*s) && !whitespace(*s)) + while(*s && !mime_tspecial(*s) && !whitespace(*s)) dynstr_append(&name, tolower((unsigned char)*s++)); if(!(s = skipwhite(s, 1))) return 0; @@ -421,7 +421,7 @@ int mime_rfc2388_content_disposition(const char *s, return -1; if(!*s) return -1; - while(*s && !tspecial(*s) && !whitespace(*s)) + while(*s && !mime_tspecial(*s) && !whitespace(*s)) dynstr_append(&disposition, tolower((unsigned char)*s++)); if(!(s = skipwhite(s, 1))) return -1; @@ -433,7 +433,7 @@ int mime_rfc2388_content_disposition(const char *s, return -1; if(!*s) return -1; - while(*s && !tspecial(*s) && !whitespace(*s)) + while(*s && !mime_tspecial(*s) && !whitespace(*s)) dynstr_append(¶metername, tolower((unsigned char)*s++)); if(!(s = skipwhite(s, 1))) return -1; @@ -441,7 +441,7 @@ int mime_rfc2388_content_disposition(const char *s, return -1; if(!(s = skipwhite(s, 1))) return -1; - if(!(s = parseword(s, parametervaluep, tspecial))) + if(!(s = mime_parse_word(s, parametervaluep, mime_tspecial))) return -1; if(!(s = skipwhite(s, 1))) return -1; @@ -523,13 +523,13 @@ int parse_cookie(const char *s, s = skipwhite(s, 0); continue; } - if(!(s = parsetoken(s, &n, http_separator))) + if(!(s = parsetoken(s, &n, mime_http_separator))) return -1; s = skipwhite(s, 0); if(*s++ != '=') return -1; s = skipwhite(s, 0); - if(!(s = parseword(s, &v, http_separator))) + if(!(s = mime_parse_word(s, &v, mime_http_separator))) return -1; if(n[0] == '$') { /* Some bit of meta-information */ @@ -597,7 +597,7 @@ char *quote822(const char *s, int force) { if(!force) { /* See if we need to quote */ for(t = s; (c = (unsigned char)*t); ++t) { - if(tspecial(c) || http_separator(c) || whitespace(c)) + if(mime_tspecial(c) || mime_http_separator(c) || whitespace(c)) break; } if(*t) diff --git a/lib/mime.h b/lib/mime.h index d9c28ac..434b373 100644 --- a/lib/mime.h +++ b/lib/mime.h @@ -96,6 +96,10 @@ char *mime_to_qp(const char *text); const char *mime_encode_text(const char *text, const char **charsetp, const char **encodingp); +const char *mime_parse_word(const char *s, char **valuep, + int (*special)(int)); +int mime_http_separator(int c); +int mime_tspecial(int c); #endif /* MIME_H */ diff --git a/lib/t-mime.c b/lib/t-mime.c index 05ae8b5..eb5ee7c 100644 --- a/lib/t-mime.c +++ b/lib/t-mime.c @@ -38,7 +38,7 @@ void test_mime(void) { char *t, *n, *v; struct vector parts[1]; struct kvp *k; - const char *s; + const char *s, *cs, *enc; hash *h; fprintf(stderr, "test_mime\n"); @@ -308,6 +308,31 @@ void test_mime(void) { check_string(*(char **)hash_find(h, "content-type"), "text/plain"); check_string(*(char **)hash_find(h, "content-transfer-encoding"), "BASE64"); check_string(s, "wibble\r\n"); + +#define CHECK_QUOTE(INPUT, EXPECT) do { \ + s = quote822(INPUT, 0); \ + insist(s != 0); \ + check_string(s, EXPECT); \ + s = mime_parse_word(s, &t, mime_http_separator); \ + check_string(t, INPUT); \ +} while(0) + CHECK_QUOTE("wibble", "wibble"); + CHECK_QUOTE("wibble spong", "\"wibble spong\""); + CHECK_QUOTE("wibble\\spong", "\"wibble\\\\spong\""); + CHECK_QUOTE("wibble\"spong", "\"wibble\\\"spong\""); + CHECK_QUOTE("(wibble)", "\"(wibble)\""); + + s = mime_encode_text("wibble\n", &cs, &enc); + insist(s != 0); + check_string(s, "wibble\n"); + check_string(cs, "us-ascii"); + check_string(enc, "7bit"); + + s = mime_encode_text("wibble\xC3\xB7\n", &cs, &enc); + insist(s != 0); + check_string(s, "wibble=C3=B7\n"); + check_string(cs, "utf-8"); + check_string(enc, "quoted-printable"); } /* -- [mdw]