diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-04-08 11:45:06 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2010-04-08 11:45:06 +0300 |
commit | 7287e840118d680efe1795e053500c999a950ade (patch) | |
tree | de3410b78f6eff36135fd1acab54ada7ec8331d2 | |
parent | b2c1b1ff400a604fa41c168351630bac3238177e (diff) | |
download | mailutils-7287e840118d680efe1795e053500c999a950ade.tar.gz mailutils-7287e840118d680efe1795e053500c999a950ade.tar.bz2 |
Improve MIME parameter parsing.
* mailbox/mimehdr.c (_header_get_param): Improve error checking.
Allow for optional whitespace around the '='.
* mailbox/rfc2047.c (mu_rfc2047_decode): tocode=NULL is OK.
-rw-r--r-- | mailbox/mimehdr.c | 66 | ||||
-rw-r--r-- | mailbox/rfc2047.c | 2 |
2 files changed, 51 insertions, 17 deletions
diff --git a/mailbox/mimehdr.c b/mailbox/mimehdr.c index 848842b26..0c04c23f9 100644 --- a/mailbox/mimehdr.c +++ b/mailbox/mimehdr.c @@ -84,7 +84,11 @@ RFCs. ENOMEM , if unable to allocate memory. */ - + +/* Internal flag used by _header_get_param to delay increasing + estimated continuation index. */ +#define _MU_MIMEHDR_INCR_CIND 0x8000 + int _header_get_param (const char *field_body, const char *disp, @@ -117,7 +121,7 @@ _header_get_param (const char *field_body, while (p && *p) { - char *v, *e; + char *v, *e, *ep, *cp; size_t len, escaped_chars = 0; if (*p != ';') @@ -128,9 +132,10 @@ _header_get_param (const char *field_body, /* walk upto start of param */ p = mu_str_skip_class (p + 1, MU_CTYPE_SPACE); - if ((v = strchr (p, '=')) == NULL) + if ((ep = strchr (p, '=')) == NULL) break; - v++; + /* Allow for optional whitespace after '=' */ + v = mu_str_skip_class (ep + 1, MU_CTYPE_SPACE); /* Find end of the parameter */ if (*v == '"') { @@ -171,18 +176,15 @@ _header_get_param (const char *field_body, continue; } - res = 0; /* Indicate success */ - - if (p[param_len] == '*') + cp = p + param_len; + + if (*cp == '*') { - char *cp = p + param_len + 1; - + cp++; /* It is a parameter value continuation (RFC 2231, Section 3) or parameter value character set and language information (ibid., Section 4). */ - if (*cp == '=') - flags |= MU_MIMEHDR_CSINFO; - else if (mu_isdigit (*cp)) + if (mu_isdigit (*cp)) { /* See if the index is OK */ @@ -194,16 +196,48 @@ _header_get_param (const char *field_body, flags |= MU_MIMEHDR_CSINFO; end++; } - if (*end != '=' || n != cind) + if (n != cind) { res = MU_ERR_PARSE; break; } - /* Everything OK, increase the estimation */ - flags |= MU_MIMEHDR_MULTILINE; - cind++; + /* Everything OK, mark this as a multiline (continued) + parameter. We also need to increment the estimation, + but it cannot be done right now because its value is + used below to decide whether to do flag cleanup + on error. So we set _MU_MIMEHDR_INCR_CIND flag instead + and increment cind later. */ + flags |= (MU_MIMEHDR_MULTILINE|_MU_MIMEHDR_INCR_CIND); + /* And point cp to the last character: there are more + checks ahead. */ + cp = end; } + else + flags |= MU_MIMEHDR_CSINFO; } + /* Allow for optional whitespace before '=' */ + cp = mu_str_skip_class (cp, MU_CTYPE_SPACE); + /* cp must now point to the equals sign */ + if (cp != ep) + { + /* Clean up everything, unless we're in the middle of a + parameter continuation. */ + if (cind == 0) + flags = 0; + + /* Try next parameter */ + p = strchr (e, ';'); + continue; + } + + if (flags & _MU_MIMEHDR_INCR_CIND) + { + /* Increase the estimation. */ + flags &= ~_MU_MIMEHDR_INCR_CIND; + cind++; + } + + res = 0; /* Indicate success */ /* Prepare P for the next iteration */ p = e; diff --git a/mailbox/rfc2047.c b/mailbox/rfc2047.c index bf23b7e1f..540f80e68 100644 --- a/mailbox/rfc2047.c +++ b/mailbox/rfc2047.c @@ -92,7 +92,7 @@ mu_rfc2047_decode (const char *tocode, const char *input, char **ptostr) } \ } while (0) - if (!tocode || !input) + if (!input) return EINVAL; if (!ptostr) return MU_ERR_OUT_PTR_NULL; |