diff options
-rw-r--r-- | src/misc.c | 41 | ||||
-rw-r--r-- | test/unit/disposition.c | 28 |
2 files changed, 50 insertions, 19 deletions
@@ -362,6 +362,7 @@ int a_Misc_content_type_check(const char *EntryType, const char *DetectedType) void a_Misc_parse_content_disposition(const char *disposition, char **type, char **filename) { static const char tspecials_space[] = "()<>@,;:\\\"/[]?= "; + const char terminators[] = " ;\t"; const char *str, *s; if (type) @@ -371,13 +372,22 @@ void a_Misc_parse_content_disposition(const char *disposition, char **type, char if (!(str = disposition)) return; - for (s = str; *s && d_isascii(*s) && !iscntrl(*s) && + for (s = str; *s && d_isascii((uchar_t)*s) && !iscntrl((uchar_t)*s) && !strchr(tspecials_space, *s); s++) ; - if (type) + if (type && !(s == str)) *type = dStrndup(str, s - str); + if (!*type) { + return; + } + + if (!strchr(terminators, *s)) { + *type = NULL; + return; + } + if (*s == ';') { - const char terminators[] = " ;\t"; + bool_t quoted = FALSE; const char key[] = "filename"; if ((s = dStriAsciiStr(str, key)) && @@ -388,6 +398,7 @@ void a_Misc_parse_content_disposition(const char *disposition, char **type, char size_t len = 0; for (++s; *s == ' ' || *s == '\t'; ++s); if (*s == '"') { + quoted = TRUE; s++; for ( ; *s == '.'; ++s); bool_t escaped = FALSE; @@ -408,11 +419,31 @@ void a_Misc_parse_content_disposition(const char *disposition, char **type, char } const char invalid_characters[] = "/\\|~"; - for (char *s = *filename; s < *filename + len; s++) { + char *s = *filename, *d = *filename; + + for ( ; s < *filename + len; s++) { if (strchr(invalid_characters, *s)) { - *s = '_'; + // If this is a backslash preceding a quote, we want to just + // skip past it without advancing the destination pointer or + // copying anything. + if (!(*s == '\\' && *(s+1) == '"')) { + *d = '_'; + d++; + } + } else if (!quoted && (!d_isascii((uchar_t)*s) || *s == '=')) { + *filename = NULL; + return; + } else { + *d = *s; + d++; } } + + // Truncate filename to deal with the string being shorter if we + // skipped over any backslash characters in the above loop + if (s != d) { + *d = '\0'; + } } } } diff --git a/test/unit/disposition.c b/test/unit/disposition.c index c49a541f..08ac929e 100644 --- a/test/unit/disposition.c +++ b/test/unit/disposition.c @@ -39,18 +39,18 @@ struct testcase cases[] = { /* See http://test.greenbytes.de/tech/tc2231/ */ { "inline", "inline", NULL }, - // FIXME: { "\"inline\"", NULL, NULL }, + { "\"inline\"", NULL, NULL }, { "inline; filename=\"foo.html\"", "inline", "foo.html" }, { "inline; filename=\"Not an attachment!\"", "inline", "Not an attachment!" }, { "inline; filename=\"foo.pdf\"", "inline", "foo.pdf" }, - // FIXME: { "\"attachment\"", NULL, NULL }, + { "\"attachment\"", NULL, NULL }, { "attachment", "attachment", NULL }, { "ATTACHMENT", "ATTACHMENT", NULL }, { "attachment; filename=\"foo.html\"", "attachment", "foo.html" }, { "attachment; filename=\"0000000000111111111122222\"", "attachment", "0000000000111111111122222" }, { "attachment; filename=\"00000000001111111111222222222233333\"", "attachment", "00000000001111111111222222222233333" }, { "attachment; filename=\"f\\oo.html\"", "attachment", "f_oo.html" }, - // FIXME: { "attachment; filename=\"\\\"quoting\\\" tested.html\"", "attachment", "\"quoting\" tested.html" }, + { "attachment; filename=\"\\\"quoting\\\" tested.html\"", "attachment", "\"quoting\" tested.html" }, { "attachment; filename=\"Here's a semicolon;.html\"", "attachment", "Here's a semicolon;.html" }, { "attachment; foo=\"bar\"; filename=\"foo.html\"", "attachment", "foo.html" }, { "attachment; foo=\"\\\"\\\\\";filename=\"foo.html\"", "attachment", "foo.html" }, @@ -72,15 +72,15 @@ struct testcase cases[] = { { "attachment; filename =\"foo.html\"", "attachment", "foo.html" }, { "attachment; filename=\"foo.html\"; filename=\"bar.html\"", "attachment", "foo.html" }, { "attachment; filename=foo[1](2).html", "attachment", "foo[1](2).html" }, - // FIXME: { "attachment; filename=foo-ä.html", "attachment", NULL }, - // FIXME: { "attachment; filename=filename=foo-ä.html", "attachment", NULL }, - // FIXME: { "filename=foo.html", NULL, NULL }, - // FIXME: { "x=y; filename=foo.html", NULL, NULL }, - // FIXME: {"\"foo; filename=bar;baz\"; filename=qux", NULL, NULL }, - // FIXME: { "filename=foo.html, filename=bar.html", NULL, NULL }, - // FIXME: { "; filename=foo.html", NULL, NULL }, - // FIXME: { ": inline; attachment; filename=foo.html", NULL, NULL }, - // FIXME: { "inline; attachment; filename=foo.html", NULL, NULL }, + { "attachment; filename=foo-ä.html", "attachment", NULL }, + { "attachment; filename=filename=foo-ä.html", "attachment", NULL }, + { "filename=foo.html", NULL, NULL }, + { "x=y; filename=foo.html", NULL, NULL }, + {"\"foo; filename=bar;baz\"; filename=qux", NULL, NULL }, + { "filename=foo.html, filename=bar.html", NULL, NULL }, + { "; filename=foo.html", NULL, NULL }, + { ": inline; attachment; filename=foo.html", NULL, NULL }, + { "inline; attachment; filename=foo.html", "inline", "foo.html" }, { "attachment; inline; filename=foo.html", "attachment", "foo.html" }, { "attachment; filename=\"foo.html\".txt", "attachment", "foo.html" }, { "attachment; filename=\"bar", "attachment", NULL }, @@ -89,14 +89,14 @@ struct testcase cases[] = { { "attachment; foo=foo filename=bar", "attachment", "bar" }, { "attachment; filename=bar foo=foo ", "attachment", "bar" }, { "attachment filename=bar", "attachment", NULL }, - // FIXME: { "filename=foo.html; attachment", NULL, NULL }, + { "filename=foo.html; attachment", NULL, NULL }, { "attachment; xfilename=foo.html", "attachment", NULL }, { "attachment; filename=\"/foo.html\"", "attachment", "_foo.html" }, { "attachment; filename=\"\\\\foo.html\"", "attachment", "__foo.html" }, { "foobar", "foobar", NULL }, { "attachment; example=\"filename=example.txt\"", "attachment", NULL }, { "attachment; filename=\"foo-ae.html\"; filename*=UTF-8''foo-%c3%a4.html", "attachment", "foo-ae.html" }, - // FIXME: { "attachment; filename==?ISO-8859-1?Q?foo-=E4.html?=", "attachment", NULL }, + { "attachment; filename==?ISO-8859-1?Q?foo-=E4.html?=", "attachment", NULL }, { "attachment; filename=\"=?ISO-8859-1?Q?foo-=E4.html?=\"", "attachment", "=?ISO-8859-1?Q?foo-=E4.html?=" }, }; |