aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCameron Paul <cpaul37@gmail.com>2025-03-28 19:19:15 -0500
committerRodrigo Arias Mallo <rodarima@gmail.com>2025-05-01 00:56:42 +0200
commitb9f549d16bb062e3ee930d03aca3794f7607ded1 (patch)
tree06519dd92d84c47d34ad77cacc09feb8b0d41507
parentb6deab2d160b119264acd804523b8320e90e62e1 (diff)
Re-enable failing tests and fix them
-rw-r--r--src/misc.c41
-rw-r--r--test/unit/disposition.c28
2 files changed, 50 insertions, 19 deletions
diff --git a/src/misc.c b/src/misc.c
index bc5e1b8a..1791e4c7 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -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?=" },
};