diff options
author | Patrick Griffis <pgriffis@igalia.com> | 2021-07-15 12:00:01 -0500 |
---|---|---|
committer | Patrick Griffis <pgriffis@igalia.com> | 2021-07-15 12:00:01 -0500 |
commit | 1d37844399452f66938183db40f1caca5e8c3911 (patch) | |
tree | 480af420e35d00de44f00b660ec7b1d508410f57 | |
parent | 2f92f5fb9310903872a0eaaee25918825ef49e2e (diff) | |
download | libsoup-1d37844399452f66938183db40f1caca5e8c3911.tar.gz |
headers: Support invalid content-disposition without disposition-type
-rw-r--r-- | libsoup/soup-message-headers.c | 40 | ||||
-rw-r--r-- | tests/header-parsing-test.c | 36 |
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, + ¶ms)) { + 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, + ¶ms)) { + 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 */ |