X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=lib-mime%2Frfc2231.c;h=e1eec1e6c1100c373e41052e4fa1bcbef3cdbce3;hp=b0fbd59613fc9ee1352819750a4efe40ff46579d;hb=108f3c7ab59844591f7540347914ea57be5245e2;hpb=86cf852af75aa1f893b25a5fd615ac1fdb1b6033 diff --git a/lib-mime/rfc2231.c b/lib-mime/rfc2231.c index b0fbd59..e1eec1e 100644 --- a/lib-mime/rfc2231.c +++ b/lib-mime/rfc2231.c @@ -47,53 +47,26 @@ #include #include "charset.h" -#include "rfc2047.h" -typedef struct rfc2231_parameter { +typedef struct rfc2231_param { + struct rfc2231_param *next; + char *attribute; char *value; int idx; int encoded; - struct rfc2231_parameter *next; -} rfc2231_parameter; +} rfc2231_param; -DO_INIT(rfc2231_parameter, rfc2231_parameter); -static inline void rfc2231_parameter_wipe(rfc2231_parameter *param) +DO_INIT(rfc2231_param, rfc2231_param); +static inline void rfc2231_param_wipe(rfc2231_param *param) { p_delete(¶m->attribute); p_delete(¶m->value); } -DO_NEW(rfc2231_parameter, rfc2231_parameter); -DO_DELETE(rfc2231_parameter, rfc2231_parameter); - - -/* insert parameter into an ordered list. - * - * Primary sorting key: attribute - * Secondary sorting key: idx - */ -static void -rfc2231_list_insert(rfc2231_parameter **list, rfc2231_parameter *par) -{ - rfc2231_parameter **last = list; - rfc2231_parameter *p = *list, *q; - int c; - - while (p) { - last = &p->next; - q = p; - p = p->next; - - c = m_strcmp(par->value, q->value); - if ((c > 0) || (c == 0 && par->idx >= q->idx)) - break; - } - - par->next = p; - *last = par; -} - +DO_NEW(rfc2231_param, rfc2231_param); +DO_DELETE(rfc2231_param, rfc2231_param); +/* TODO: MC: replace with a str_unescape */ static void rfc2231_decode_one(char *dst, const char *src) { while (*src) { @@ -112,8 +85,7 @@ static void rfc2231_decode_one(char *dst, const char *src) *dst = '\0'; } -/* ---------------- TODO FIXME READ MARK ---------------- */ - +/* read the 'foo' part into charset, and skip that */ static char *rfc2231_get_charset(char *value, char *charset, size_t chslen) { char *t, *u; @@ -135,42 +107,120 @@ static char *rfc2231_get_charset(char *value, char *charset, size_t chslen) } -static void rfc2231_join_continuations(PARAMETER **, rfc2231_parameter *); +/* insert parameter into an ordered list. + * + * Primary sorting key: attribute + * Secondary sorting key: idx + * + * XXX: MC: looks very unclear to me + */ +static void +rfc2231_list_insert(rfc2231_param **list, rfc2231_param *par) +{ + int c; + + while (*list) { + rfc2231_param *q = *list; + + list = &(*list)->next; + + c = m_strcmp(par->value, q->value); + if ((c > 0) || (c == 0 && par->idx >= q->idx)) + break; + } -static void purge_empty_parameters (PARAMETER **headp) + par->next = *list; + *list = par; +} + +static void purge_empty_parameters(PARAMETER **headp) { - PARAMETER *p, *q, **last; + while (*headp) { + PARAMETER *p = *headp; - for (last = headp, p = *headp; p; p = q) { - q = p->next; if (!p->attribute || !p->value) { - *last = q; + *headp = p->next; p->next = NULL; - mutt_free_parameter (&p); + parameter_list_wipe(&p); + } else { + headp = &(*headp)->next; } + } +} + +/* process continuation parameters */ +/* XXX: MC: not read */ +static void +rfc2231_join_continuations(PARAMETER **head, rfc2231_param *par) +{ + rfc2231_param *q; + + char attribute[STRING]; + char charset[STRING]; + char *value = NULL; + char *valp; + int encoded; + + size_t l, vl; + + while (par) { + value = NULL; + l = 0; + + m_strcpy(attribute, sizeof(attribute), par->attribute); + + if ((encoded = par->encoded)) + valp = rfc2231_get_charset (par->value, charset, sizeof (charset)); else - last = &p->next; + valp = par->value; + + do { + if (encoded && par->encoded) + rfc2231_decode_one (par->value, valp); + + vl = m_strlen(par->value); + + p_realloc(&value, l + vl + 1); + strcpy (value + l, par->value); /* __STRCPY_CHECKED__ */ + l += vl; + + q = par->next; + rfc2231_param_delete (&par); + if ((par = q)) + valp = par->value; + } while (par && !m_strcmp(par->attribute, attribute)); + + if (value) { + if (encoded) + mutt_convert_string (&value, charset, Charset, M_ICONV_HOOK_FROM); + *head = parameter_new(); + (*head)->attribute = m_strdup(attribute); + (*head)->value = value; + head = &(*head)->next; + } } } +/****************************************************************************/ +/* Public API */ +/****************************************************************************/ +/* XXX: MC: not read */ void rfc2231_decode_parameters (PARAMETER ** headp) { PARAMETER *head = NULL; PARAMETER **last; PARAMETER *p, *q; - rfc2231_parameter *conthead = NULL; - rfc2231_parameter *conttmp; + rfc2231_param *conthead = NULL; + rfc2231_param *conttmp; char *s, *t; char charset[STRING]; int encoded; int idx; - short dirty = 0; /* set to 1 when we may have created - * empty parameters. - */ + short dirty = 0; /* 1 when we may have created empty parameters. */ if (!headp) return; @@ -192,8 +242,8 @@ void rfc2231_decode_parameters (PARAMETER ** headp) if (option (OPTRFC2047PARAMS) && p->value && strstr (p->value, "=?")) rfc2047_decode (&p->value); else if (!option (OPTSTRICTMIME)) { - if (ascii_strcasecmp (AssumedCharset, "us-ascii")) - mutt_convert_nonmime_string (&p->value); + if (mime_which_token(AssumedCharset, -1) == MIME_US_ASCII) + mutt_convert_nonmime_string(&p->value); } *last = p; @@ -222,7 +272,7 @@ void rfc2231_decode_parameters (PARAMETER ** headp) idx = atoi (s); - conttmp = rfc2231_parameter_new (); + conttmp = rfc2231_param_new (); conttmp->attribute = p->attribute; conttmp->value = p->value; conttmp->encoded = encoded; @@ -247,121 +297,64 @@ void rfc2231_decode_parameters (PARAMETER ** headp) purge_empty_parameters (headp); } -/* process continuation parameters */ +#define RFC2231_SPECIALS "@.,;:<>[]\\\"()?/= \t*'%" -static void -rfc2231_join_continuations(PARAMETER **head, rfc2231_parameter *par) +int rfc2231_encode_string(char **s) { - rfc2231_parameter *q; - - char attribute[STRING]; - char charset[STRING]; - char *value = NULL; - char *valp; - int encoded; - - size_t l, vl; - - while (par) { - value = NULL; - l = 0; - - m_strcpy(attribute, sizeof(attribute), par->attribute); - - if ((encoded = par->encoded)) - valp = rfc2231_get_charset (par->value, charset, sizeof (charset)); - else - valp = par->value; + char *charset = NULL; + char *e, *p, *t, *d = NULL; + int escapes = 0; + ssize_t dlen = 0; - do { - if (encoded && par->encoded) - rfc2231_decode_one (par->value, valp); - - vl = m_strlen(par->value); - - p_realloc(&value, l + vl + 1); - strcpy (value + l, par->value); /* __STRCPY_CHECKED__ */ - l += vl; - - q = par->next; - rfc2231_parameter_delete (&par); - if ((par = q)) - valp = par->value; - } while (par && !m_strcmp(par->attribute, attribute)); - - if (value) { - if (encoded) - mutt_convert_string (&value, charset, Charset, M_ICONV_HOOK_FROM); - *head = mutt_new_parameter (); - (*head)->attribute = m_strdup(attribute); - (*head)->value = value; - head = &(*head)->next; - } - } -} - -int rfc2231_encode_string (char **pd) -{ - int ext = 0, encode = 0; - char *charset, *s, *t, *e, *d = 0; - size_t slen, dlen = 0; - - /* + /* * A shortcut to detect pure 7bit data. - * - * This should prevent the worst when character set handling - * is flawed. + * + * This should prevent the worst when character set handling is flawed. */ - for (s = *pd; *s; s++) - if (*s & 0x80) + for (p = *s; ; p++) { + if (*p & 0x80) break; + if (!*p) + return 0; + } - if (!*s) - return 0; + if (Charset && SendCharset) { + charset = mutt_choose_charset(Charset, SendCharset, + *s, m_strlen(*s), &d, &dlen); + } - if (!Charset || !SendCharset || - !(charset = mutt_choose_charset (Charset, SendCharset, - *pd, m_strlen(*pd), &d, &dlen))) { + if (!charset) { charset = m_strdup(Charset ? Charset : "unknown-8bit"); - d = *pd; + d = *s; dlen = m_strlen(d); } - if (!mutt_is_us_ascii (charset)) - encode = 1; - - for (s = d, slen = dlen; slen; s++, slen--) - if (*s < 0x20 || *s >= 0x7f) - encode = 1, ++ext; - else if (strchr (MimeSpecials, *s) || strchr ("*'%", *s)) - ++ext; - - if (encode) { - e = p_new(char, dlen + 2 * ext + m_strlen(charset) + 3); - sprintf (e, "%s''", charset); /* __SPRINTF_CHECKED__ */ - t = e + m_strlen(e); - for (s = d, slen = dlen; slen; s++, slen--) - if (*s < 0x20 || *s >= 0x7f || - strchr (MimeSpecials, *s) || strchr ("*'%", *s)) { - sprintf (t, "%%%02X", (unsigned char) *s); - t += 3; - } - else - *t++ = *s; - *t = '\0'; - - if (d != *pd) - p_delete(&d); - p_delete(pd); - *pd = e; + for (p = d; *p; p++) { + if (*p < 0x20 || *p >= 0x7f || strchr(RFC2231_SPECIALS, *p)) { + ++escapes; + } } - else if (d != *pd) { - p_delete(pd); - *pd = d; + + e = p_new(char, dlen + 2 * escapes + m_strlen(charset) + 3); + + t = e + sprintf(e, "%s''", charset); + for (p = d; *p; p++) { + if (*p < 0x20 || *p >= 0x7f || strchr(RFC2231_SPECIALS, *p)) { + *t++ = '%'; + *t++ = __m_b36chars_upper[*p >> 4]; + *t++ = __m_b36chars_upper[*p & 0xf]; + } else { + *t++ = *p; + } } + *t = '\0'; + if (d != *s) + p_delete(&d); + p_delete(s); p_delete(&charset); - return encode; + *s = e; + return 1; }