aboutsummaryrefslogtreecommitdiff
path: root/src/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/misc.c')
-rw-r--r--src/misc.c41
1 files changed, 36 insertions, 5 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';
+ }
}
}
}