[libsoup/pgriffis/content-disposition] headers: Support invalid content-disposition with only directives




commit 1161072c5401fe1b96ff0b8214656357f9d03c8b
Author: Patrick Griffis <pgriffis igalia com>
Date:   Wed Jul 14 11:41:19 2021 -0500

    headers: Support invalid content-disposition with only directives

 libsoup/soup-message-headers.c | 42 +++++++++++++++++++++++++++---------------
 tests/header-parsing-test.c    | 16 ++++++++++++++++
 2 files changed, 43 insertions(+), 15 deletions(-)
---
diff --git a/libsoup/soup-message-headers.c b/libsoup/soup-message-headers.c
index 88c7e29a..dc3621d9 100644
--- a/libsoup/soup-message-headers.c
+++ b/libsoup/soup-message-headers.c
@@ -1442,26 +1442,38 @@ parse_content_foo (SoupMessageHeaders *hdrs,
 {
        const char *header;
        char *semi;
+        char *equal;
 
        header = soup_message_headers_get_one_common (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 ((!semi && equal) || (equal && 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 {
+                        semi = strchr (header, ';');
+                        if (semi)
+                                semi++;
+                }
+        }
 
        if (!params)
                return TRUE;
diff --git a/tests/header-parsing-test.c b/tests/header-parsing-test.c
index 0e5f252a..33ab519e 100644
--- a/tests/header-parsing-test.c
+++ b/tests/header-parsing-test.c
@@ -1032,6 +1032,7 @@ 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\""
 
 static void
 do_content_disposition_tests (void)
@@ -1100,6 +1101,21 @@ 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);
+
        soup_message_headers_unref (hdrs);
 
        /* Ensure that soup-multipart always quotes filename */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]