summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Griffis <pgriffis@igalia.com>2021-07-15 12:00:01 -0500
committerPatrick Griffis <pgriffis@igalia.com>2021-07-15 12:00:01 -0500
commit1d37844399452f66938183db40f1caca5e8c3911 (patch)
tree480af420e35d00de44f00b660ec7b1d508410f57
parent2f92f5fb9310903872a0eaaee25918825ef49e2e (diff)
downloadlibsoup-1d37844399452f66938183db40f1caca5e8c3911.tar.gz
headers: Support invalid content-disposition without disposition-type
-rw-r--r--libsoup/soup-message-headers.c40
-rw-r--r--tests/header-parsing-test.c36
2 files changed, 60 insertions, 16 deletions
diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c
index 5c8c7cb9..aaf496e7 100644
--- a/libsoup/soup-message-headers.c
+++ b/libsoup/soup-message-headers.c
@@ -1272,26 +1272,36 @@ parse_content_foo (SoupMessageHeaders *hdrs, const char *header_name,
{
const char *header;
char *semi;
+ char *equal;
header = soup_message_headers_get_one (hdrs, header_name);
if (!header)
return FALSE;
- if (foo) {
- *foo = g_strdup (header);
- semi = strchr (*foo, ';');
- if (semi) {
- char *p = semi;
-
- *semi++ = '\0';
- while (p - 1 > *foo && g_ascii_isspace(p[-1]))
- *(--p) = '\0';
- }
- } else {
- semi = strchr (header, ';');
- if (semi)
- semi++;
- }
+ /* Some websites send an invalid disposition that only contains parameters;
+ * We can be flexible about handling these by detecting if the first word
+ * is a parameter (foo=bar). */
+ equal = strchr (header, '=');
+ semi = strchr (header, ';');
+ if (equal && (!semi || (equal < semi))) {
+ semi = (char *)header;
+ if (foo)
+ *foo = NULL;
+ } else if (foo) {
+ *foo = g_strdup (header);
+ semi = strchr (*foo, ';');
+ if (semi) {
+ char *p = semi;
+
+ *semi++ = '\0';
+ while (p - 1 > *foo && g_ascii_isspace(p[-1]))
+ *(--p) = '\0';
+ }
+ } else {
+ /* Skip type, we don't store it */
+ if (semi)
+ semi++;
+ }
if (!params)
return TRUE;
diff --git a/tests/header-parsing-test.c b/tests/header-parsing-test.c
index 31edfd02..946f1188 100644
--- a/tests/header-parsing-test.c
+++ b/tests/header-parsing-test.c
@@ -1032,13 +1032,15 @@ do_param_list_tests (void)
#define RFC5987_TEST_HEADER_UTF8 "attachment; filename*=UTF-8''t%C3%A9st.txt; filename=\"test.txt\""
#define RFC5987_TEST_HEADER_ISO "attachment; filename=\"test.txt\"; filename*=iso-8859-1''t%E9st.txt"
#define RFC5987_TEST_HEADER_FALLBACK "attachment; filename*=Unknown''t%FF%FF%FFst.txt; filename=\"test.txt\""
+#define RFC5987_TEST_HEADER_NO_TYPE "filename=\"test.txt\""
+#define RFC5987_TEST_HEADER_NO_TYPE_2 "filename=\"test.txt\"; foo=bar"
static void
do_content_disposition_tests (void)
{
SoupMessageHeaders *hdrs;
GHashTable *params;
- const char *header, *filename;
+ const char *header, *filename, *parameter2;
char *disposition;
SoupBuffer *buffer;
SoupMultipart *multipart;
@@ -1101,6 +1103,38 @@ do_content_disposition_tests (void)
g_assert_cmpstr (filename, ==, RFC5987_TEST_FALLBACK_FILENAME);
g_hash_table_destroy (params);
+ /* Invalid disposition with only a filename still works */
+ soup_message_headers_clear (hdrs);
+ soup_message_headers_append (hdrs, "Content-Disposition",
+ RFC5987_TEST_HEADER_NO_TYPE);
+ if (!soup_message_headers_get_content_disposition (hdrs,
+ &disposition,
+ &params)) {
+ soup_test_assert (FALSE, "filename-only decoding FAILED");
+ return;
+ }
+ g_assert_null (disposition);
+ filename = g_hash_table_lookup (params, "filename");
+ g_assert_cmpstr (filename, ==, RFC5987_TEST_FALLBACK_FILENAME);
+ g_hash_table_destroy (params);
+
+ /* Invalid disposition with only two parameters still works */
+ soup_message_headers_clear (hdrs);
+ soup_message_headers_append (hdrs, "Content-Disposition",
+ RFC5987_TEST_HEADER_NO_TYPE_2);
+ if (!soup_message_headers_get_content_disposition (hdrs,
+ &disposition,
+ &params)) {
+ soup_test_assert (FALSE, "only two parameters decoding FAILED");
+ return;
+ }
+ g_assert_null (disposition);
+ filename = g_hash_table_lookup (params, "filename");
+ g_assert_cmpstr (filename, ==, RFC5987_TEST_FALLBACK_FILENAME);
+ parameter2 = g_hash_table_lookup (params, "foo");
+ g_assert_cmpstr (parameter2, ==, "bar");
+ g_hash_table_destroy (params);
+
soup_message_headers_free (hdrs);
/* Ensure that soup-multipart always quotes filename */