X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/1388183fc96a86e5fbbb9d43cebdedd9f44ab64f..d205d39a:/sbr/fmt_rfc2047.c?ds=sidebyside diff --git a/sbr/fmt_rfc2047.c b/sbr/fmt_rfc2047.c index 9d5b6d3c..bd703b43 100644 --- a/sbr/fmt_rfc2047.c +++ b/sbr/fmt_rfc2047.c @@ -1,8 +1,4 @@ - -/* - * fmt_rfc2047.c -- decode RFC-2047 header format - * - * $Id$ +/* fmt_rfc2047.c -- decode RFC-2047 header format * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for @@ -13,7 +9,6 @@ #include #ifdef HAVE_ICONV # include -# include #endif static signed char hexindex[] = { @@ -24,6 +19,14 @@ static signed char hexindex[] = { -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 }; @@ -40,8 +43,12 @@ static signed char index_64[128] = { #define char64(c) (((unsigned char) (c) > 127) ? -1 : index_64[(unsigned char) (c)]) -static int -unqp (unsigned char byte1, unsigned char byte2) +/* + * Decode two quoted-pair characters + */ + +int +decode_qp (unsigned char byte1, unsigned char byte2) { if (hexindex[byte1] == -1 || hexindex[byte2] == -1) return -1; @@ -63,7 +70,7 @@ int decode_rfc2047 (char *str, char *dst, size_t dstlen) { char *p, *q, *pp; - char *startofmime, *endofmime; + char *startofmime, *endofmime, *endofcharset; int c, quoted_printable; int encoding_found = 0; /* did we decode anything? */ int between_encodings = 0; /* are we between two encodings? */ @@ -71,7 +78,7 @@ decode_rfc2047 (char *str, char *dst, size_t dstlen) int whitespace = 0; /* how much whitespace between encodings? */ #ifdef HAVE_ICONV int use_iconv = 0; /* are we converting encoding with iconv? */ - iconv_t cd; + iconv_t cd = NULL; int fromutf8 = 0; char *saveq, *convbuf = NULL; size_t savedstlen; @@ -119,7 +126,7 @@ decode_rfc2047 (char *str, char *dst, size_t dstlen) equals_pending = 1; /* we have a '=' pending */ /* Check for initial =? */ - if (*p == '=' && p[1] && p[1] == '?' && p[2]) { + if (*p == '=' && p[1] == '?' && p[2]) { startofmime = p + 2; /* Scan ahead for the next '?' character */ @@ -129,13 +136,27 @@ decode_rfc2047 (char *str, char *dst, size_t dstlen) if (!*pp) continue; + /* + * RFC 2231 specifies that language information can appear + * in a charset specification like so: + * + * =?us-ascii*en?Q?Foo?= + * + * Right now we don't use language information, so ignore it. + */ + + for (endofcharset = startofmime; + *endofcharset != '*' && endofcharset < pp; + endofcharset++) + ; + /* Check if character set can be handled natively */ - if (!check_charset(startofmime, pp - startofmime)) { + if (!check_charset(startofmime, endofcharset - startofmime)) { #ifdef HAVE_ICONV /* .. it can't. We'll use iconv then. */ - *pp = '\0'; + *endofcharset = '\0'; cd = iconv_open(get_charset(), startofmime); - fromutf8 = !mh_strcasecmp(startofmime, "UTF-8"); + fromutf8 = !strcasecmp(startofmime, "UTF-8"); *pp = '?'; if (cd == (iconv_t)-1) continue; use_iconv = 1; @@ -168,9 +189,9 @@ decode_rfc2047 (char *str, char *dst, size_t dstlen) */ endofmime = NULL; for (pp = startofmime; *pp && *(pp+1); pp++) { - if (is_lws(*pp)) { + if (is_lws(*pp)) break; - } else if (*pp == '?' && pp[1] == '=') { + if (*pp == '?' && pp[1] == '=') { endofmime = pp; break; } @@ -223,7 +244,7 @@ decode_rfc2047 (char *str, char *dst, size_t dstlen) if (quoted_printable) { for (pp = startofmime; pp < endofmime; pp++) { if (*pp == '=') { - c = unqp (pp[1], pp[2]); + c = decode_qp (pp[1], pp[2]); if (c == -1) continue; if (c != 0) @@ -238,6 +259,7 @@ decode_rfc2047 (char *str, char *dst, size_t dstlen) } else { /* base64 */ int c1, c2, c3, c4; + c1 = c2 = c3 = c4 = -1; pp = startofmime; while (pp < endofmime) { @@ -304,8 +326,10 @@ decode_rfc2047 (char *str, char *dst, size_t dstlen) break; /* skip to next input character */ if (fromutf8) { - for (start++;(start < q) && ((*start & 192) == 128);start++) - inbytes--; + for (++start, --inbytes; + start < q && (*start & 192) == 128; + ++start, --inbytes) + continue; } else start++, inbytes--; if (start >= q)