Title: [286427] trunk
Revision
286427
Author
commit-qu...@webkit.org
Date
2021-12-02 07:34:01 -0800 (Thu, 02 Dec 2021)

Log Message

File inputs in non-multipart form submissions show up as string values in the formdata event
https://bugs.webkit.org/show_bug.cgi?id=233725

Patch by Andreu Botella <and...@andreubotella.com> on 2021-12-02
Reviewed by Chris Dumez.

LayoutTests/imported/w3c:

Added tests in web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set.html
to check that file inputs show up as File entries in the formdata event.

* web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set-expected.txt:
* web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set.html:
* web-platform-tests/html/semantics/forms/form-submission-0/text-plain.window-expected.txt:
* web-platform-tests/html/semantics/forms/form-submission-0/urlencoded2.window-expected.txt:

Source/WebCore:

When a form's entry list was constructed form a non-multipart/form-data form submission,
file inputs were added to the DOMFormData object as string values consisting of the file's
filename. Before r280310, this optimization was unobservable, since the DOMFormData object
was never exposed to the user halfway through a form submission.

r280310 changed this by adding the formdata event, which fires at the end of the "construct
the entry list" algorithm and can be used to both inspect and modify the DOMFormData object.
This means that it is now observable that file inputs in urlencoded and text/plain form
submissions are encoded as their filenames, and that any new File entries added to the
DOMFormData object the event listeners will be skipped when building the form payload.

This change fixes that by always adding file inputs to DOMFormData as File entries, and
using a File's filename as the string value in FormData::appendNonMultipartKeyValuePairItems

Tests: imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set.html
       imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/text-plain.window.html
       imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/urlencoded2.window.html

* html/FileInputType.cpp:
(WebCore::FileInputType::appendFormData const): Changed to always add File entries to the
DOMFormData object, rather than adding the filenames as string values when `multipart` is
false.
* platform/network/FormData.cpp:
(WebCore::FormData::appendNonMultiPartKeyValuePairItems): Changed to encode File entry
values as their filenames, rather than skipping them.

Modified Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (286426 => 286427)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2021-12-02 15:25:52 UTC (rev 286426)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2021-12-02 15:34:01 UTC (rev 286427)
@@ -1,3 +1,18 @@
+2021-12-02  Andreu Botella  <and...@andreubotella.com>
+
+        File inputs in non-multipart form submissions show up as string values in the formdata event
+        https://bugs.webkit.org/show_bug.cgi?id=233725
+
+        Reviewed by Chris Dumez.
+
+        Added tests in web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set.html
+        to check that file inputs show up as File entries in the formdata event.
+
+        * web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set-expected.txt:
+        * web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set.html:
+        * web-platform-tests/html/semantics/forms/form-submission-0/text-plain.window-expected.txt:
+        * web-platform-tests/html/semantics/forms/form-submission-0/urlencoded2.window-expected.txt:
+
 2021-12-02  Alexey Shvayka  <ashva...@apple.com>
 
         Add a fast path for empty string to setInnerHTML()

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set-expected.txt (286426 => 286427)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set-expected.txt	2021-12-02 15:25:52 UTC (rev 286426)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set-expected.txt	2021-12-02 15:34:01 UTC (rev 286427)
@@ -5,6 +5,9 @@
 
 
 
+
+
+
   close  button  reset  submit
 
 PASS FormData constructor always produces UTF-8 _charset_ value.
@@ -12,6 +15,9 @@
 PASS The button cannot be setted if it is not a submitter.
 PASS "formdata" event bubbles, and is not cancelable.
 PASS "formdata" event bubbles in an orphan tree.
+PASS Files in a application/x-www-form-urlencoded form show up as File objects in the "formData" IDL attribute
+PASS Files in a multipart/form-data form show up as File objects in the "formData" IDL attribute
+PASS Files in a text/plain form show up as File objects in the "formData" IDL attribute
 PASS "formData" IDL attribute should have entries for form-associated elements in the first event handler, and the second handler can read entries set by the first handler.
 PASS Entries added to "formData" IDL attribute should be submitted.
 PASS Entries added to the "formdata" IDL attribute shouldn't be newline normalized in the resulting FormData

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set.html (286426 => 286427)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set.html	2021-12-02 15:25:52 UTC (rev 286426)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set.html	2021-12-02 15:34:01 UTC (rev 286427)
@@ -77,6 +77,26 @@
   assert_true(didCallHandler);
 }, '"formdata" event bubbles in an orphan tree.');
 
+for (const enctype of ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"]) {
+  test((t) => {
+    let form = populateForm('<input name=file type=file><input name=empty type=file>');
+    form.enctype = enctype;
+
+    const file = new File([], "filename");
+    const dataTransfer = new DataTransfer();
+    dataTransfer.items.add(file);
+    form.querySelector('input[name=file]').files = dataTransfer.files;
+
+    form.addEventListener('formdata', t.step_func(e => {
+      assert_true(e.formData.has('file'));
+      assert_equals(e.formData.get('file'), file);
+      assert_true(e.formData.has('empty'));
+      assert_true(e.formData.get('empty') instanceof File);
+    }));
+    form.submit();
+  }, `Files in a ${enctype} form show up as File objects in the "formData" IDL attribute`);
+}
+
 test(() => {
   let listener1ok = false;
   let listeern2ok = false;

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/text-plain.window-expected.txt (286426 => 286427)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/text-plain.window-expected.txt	2021-12-02 15:25:52 UTC (rev 286426)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/text-plain.window-expected.txt	2021-12-02 15:34:01 UTC (rev 286427)
@@ -2,13 +2,13 @@
 PASS text/plain: Basic test (normal form)
 PASS text/plain: Basic test (formdata event)
 PASS text/plain: Basic File test (normal form)
-FAIL text/plain: Basic File test (formdata event) assert_equals: expected "basic=file-test.txt\r\n" but got ""
+PASS text/plain: Basic File test (formdata event)
 PASS text/plain: 0x00 in name (normal form)
 PASS text/plain: 0x00 in name (formdata event)
 PASS text/plain: 0x00 in value (normal form)
 PASS text/plain: 0x00 in value (formdata event)
 PASS text/plain: 0x00 in filename (normal form)
-FAIL text/plain: 0x00 in filename (formdata event) assert_equals: expected "a=b\0c\r\n" but got ""
+PASS text/plain: 0x00 in filename (formdata event)
 PASS text/plain: \n in name (normal form)
 PASS text/plain: \n in name (formdata event)
 PASS text/plain: \r in name (normal form)
@@ -26,37 +26,37 @@
 PASS text/plain: \n\r in value (normal form)
 PASS text/plain: \n\r in value (formdata event)
 PASS text/plain: \n in filename (normal form)
-FAIL text/plain: \n in filename (formdata event) assert_equals: expected "a=b\r\nc\r\n" but got ""
+PASS text/plain: \n in filename (formdata event)
 PASS text/plain: \r in filename (normal form)
-FAIL text/plain: \r in filename (formdata event) assert_equals: expected "a=b\r\nc\r\n" but got ""
+PASS text/plain: \r in filename (formdata event)
 PASS text/plain: \r\n in filename (normal form)
-FAIL text/plain: \r\n in filename (formdata event) assert_equals: expected "a=b\r\nc\r\n" but got ""
+PASS text/plain: \r\n in filename (formdata event)
 PASS text/plain: \n\r in filename (normal form)
-FAIL text/plain: \n\r in filename (formdata event) assert_equals: expected "a=b\r\n\r\nc\r\n" but got ""
+PASS text/plain: \n\r in filename (formdata event)
 PASS text/plain: double quote in name (normal form)
 PASS text/plain: double quote in name (formdata event)
 PASS text/plain: double quote in value (normal form)
 PASS text/plain: double quote in value (formdata event)
 PASS text/plain: double quote in filename (normal form)
-FAIL text/plain: double quote in filename (formdata event) assert_equals: expected "a=b\"c\r\n" but got ""
+PASS text/plain: double quote in filename (formdata event)
 PASS text/plain: single quote in name (normal form)
 PASS text/plain: single quote in name (formdata event)
 PASS text/plain: single quote in value (normal form)
 PASS text/plain: single quote in value (formdata event)
 PASS text/plain: single quote in filename (normal form)
-FAIL text/plain: single quote in filename (formdata event) assert_equals: expected "a=b'c\r\n" but got ""
+PASS text/plain: single quote in filename (formdata event)
 PASS text/plain: backslash in name (normal form)
 PASS text/plain: backslash in name (formdata event)
 PASS text/plain: backslash in value (normal form)
 PASS text/plain: backslash in value (formdata event)
 PASS text/plain: backslash in filename (normal form)
-FAIL text/plain: backslash in filename (formdata event) assert_equals: expected "a=b\\c\r\n" but got ""
+PASS text/plain: backslash in filename (formdata event)
 PASS text/plain: non-ASCII in name and value (normal form)
 PASS text/plain: non-ASCII in name and value (formdata event)
 PASS text/plain: non-ASCII in filename (normal form)
-FAIL text/plain: non-ASCII in filename (formdata event) assert_equals: expected "a=ə.txt\r\n" but got ""
+PASS text/plain: non-ASCII in filename (formdata event)
 PASS text/plain: characters not in encoding in name and value (normal form)
 PASS text/plain: characters not in encoding in name and value (formdata event)
 PASS text/plain: character not in encoding in filename (normal form)
-FAIL text/plain: character not in encoding in filename (formdata event) assert_equals: expected "á=&#128169;\r\n" but got ""
+PASS text/plain: character not in encoding in filename (formdata event)
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/urlencoded2.window-expected.txt (286426 => 286427)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/urlencoded2.window-expected.txt	2021-12-02 15:25:52 UTC (rev 286426)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/urlencoded2.window-expected.txt	2021-12-02 15:34:01 UTC (rev 286427)
@@ -2,13 +2,13 @@
 PASS application/x-www-form-urlencoded: Basic test (normal form)
 PASS application/x-www-form-urlencoded: Basic test (formdata event)
 PASS application/x-www-form-urlencoded: Basic File test (normal form)
-FAIL application/x-www-form-urlencoded: Basic File test (formdata event) assert_equals: expected "basic=file-test.txt" but got ""
+PASS application/x-www-form-urlencoded: Basic File test (formdata event)
 PASS application/x-www-form-urlencoded: 0x00 in name (normal form)
 PASS application/x-www-form-urlencoded: 0x00 in name (formdata event)
 PASS application/x-www-form-urlencoded: 0x00 in value (normal form)
 PASS application/x-www-form-urlencoded: 0x00 in value (formdata event)
 PASS application/x-www-form-urlencoded: 0x00 in filename (normal form)
-FAIL application/x-www-form-urlencoded: 0x00 in filename (formdata event) assert_equals: expected "a=b%00c" but got ""
+PASS application/x-www-form-urlencoded: 0x00 in filename (formdata event)
 PASS application/x-www-form-urlencoded: \n in name (normal form)
 PASS application/x-www-form-urlencoded: \n in name (formdata event)
 PASS application/x-www-form-urlencoded: \r in name (normal form)
@@ -26,37 +26,37 @@
 PASS application/x-www-form-urlencoded: \n\r in value (normal form)
 PASS application/x-www-form-urlencoded: \n\r in value (formdata event)
 PASS application/x-www-form-urlencoded: \n in filename (normal form)
-FAIL application/x-www-form-urlencoded: \n in filename (formdata event) assert_equals: expected "a=b%0D%0Ac" but got ""
+PASS application/x-www-form-urlencoded: \n in filename (formdata event)
 PASS application/x-www-form-urlencoded: \r in filename (normal form)
-FAIL application/x-www-form-urlencoded: \r in filename (formdata event) assert_equals: expected "a=b%0D%0Ac" but got ""
+PASS application/x-www-form-urlencoded: \r in filename (formdata event)
 PASS application/x-www-form-urlencoded: \r\n in filename (normal form)
-FAIL application/x-www-form-urlencoded: \r\n in filename (formdata event) assert_equals: expected "a=b%0D%0Ac" but got ""
+PASS application/x-www-form-urlencoded: \r\n in filename (formdata event)
 PASS application/x-www-form-urlencoded: \n\r in filename (normal form)
-FAIL application/x-www-form-urlencoded: \n\r in filename (formdata event) assert_equals: expected "a=b%0D%0A%0D%0Ac" but got ""
+PASS application/x-www-form-urlencoded: \n\r in filename (formdata event)
 PASS application/x-www-form-urlencoded: double quote in name (normal form)
 PASS application/x-www-form-urlencoded: double quote in name (formdata event)
 PASS application/x-www-form-urlencoded: double quote in value (normal form)
 PASS application/x-www-form-urlencoded: double quote in value (formdata event)
 PASS application/x-www-form-urlencoded: double quote in filename (normal form)
-FAIL application/x-www-form-urlencoded: double quote in filename (formdata event) assert_equals: expected "a=b%22c" but got ""
+PASS application/x-www-form-urlencoded: double quote in filename (formdata event)
 PASS application/x-www-form-urlencoded: single quote in name (normal form)
 PASS application/x-www-form-urlencoded: single quote in name (formdata event)
 PASS application/x-www-form-urlencoded: single quote in value (normal form)
 PASS application/x-www-form-urlencoded: single quote in value (formdata event)
 PASS application/x-www-form-urlencoded: single quote in filename (normal form)
-FAIL application/x-www-form-urlencoded: single quote in filename (formdata event) assert_equals: expected "a=b%27c" but got ""
+PASS application/x-www-form-urlencoded: single quote in filename (formdata event)
 PASS application/x-www-form-urlencoded: backslash in name (normal form)
 PASS application/x-www-form-urlencoded: backslash in name (formdata event)
 PASS application/x-www-form-urlencoded: backslash in value (normal form)
 PASS application/x-www-form-urlencoded: backslash in value (formdata event)
 PASS application/x-www-form-urlencoded: backslash in filename (normal form)
-FAIL application/x-www-form-urlencoded: backslash in filename (formdata event) assert_equals: expected "a=b%5Cc" but got ""
+PASS application/x-www-form-urlencoded: backslash in filename (formdata event)
 PASS application/x-www-form-urlencoded: non-ASCII in name and value (normal form)
 PASS application/x-www-form-urlencoded: non-ASCII in name and value (formdata event)
 PASS application/x-www-form-urlencoded: non-ASCII in filename (normal form)
-FAIL application/x-www-form-urlencoded: non-ASCII in filename (formdata event) assert_equals: expected "a=%C9%99.txt" but got ""
+PASS application/x-www-form-urlencoded: non-ASCII in filename (formdata event)
 PASS application/x-www-form-urlencoded: characters not in encoding in name and value (normal form)
 PASS application/x-www-form-urlencoded: characters not in encoding in name and value (formdata event)
 PASS application/x-www-form-urlencoded: character not in encoding in filename (normal form)
-FAIL application/x-www-form-urlencoded: character not in encoding in filename (formdata event) assert_equals: expected "%E1=%26%23128169%3B" but got ""
+PASS application/x-www-form-urlencoded: character not in encoding in filename (formdata event)
 

Modified: trunk/Source/WebCore/ChangeLog (286426 => 286427)


--- trunk/Source/WebCore/ChangeLog	2021-12-02 15:25:52 UTC (rev 286426)
+++ trunk/Source/WebCore/ChangeLog	2021-12-02 15:34:01 UTC (rev 286427)
@@ -1,3 +1,36 @@
+2021-12-02  Andreu Botella  <and...@andreubotella.com>
+
+        File inputs in non-multipart form submissions show up as string values in the formdata event
+        https://bugs.webkit.org/show_bug.cgi?id=233725
+
+        Reviewed by Chris Dumez.
+
+        When a form's entry list was constructed form a non-multipart/form-data form submission,
+        file inputs were added to the DOMFormData object as string values consisting of the file's
+        filename. Before r280310, this optimization was unobservable, since the DOMFormData object
+        was never exposed to the user halfway through a form submission.
+
+        r280310 changed this by adding the formdata event, which fires at the end of the "construct
+        the entry list" algorithm and can be used to both inspect and modify the DOMFormData object.
+        This means that it is now observable that file inputs in urlencoded and text/plain form
+        submissions are encoded as their filenames, and that any new File entries added to the
+        DOMFormData object the event listeners will be skipped when building the form payload.
+
+        This change fixes that by always adding file inputs to DOMFormData as File entries, and
+        using a File's filename as the string value in FormData::appendNonMultipartKeyValuePairItems
+
+        Tests: imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set.html
+               imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/text-plain.window.html
+               imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/urlencoded2.window.html
+
+        * html/FileInputType.cpp:
+        (WebCore::FileInputType::appendFormData const): Changed to always add File entries to the 
+        DOMFormData object, rather than adding the filenames as string values when `multipart` is
+        false.
+        * platform/network/FormData.cpp:
+        (WebCore::FormData::appendNonMultiPartKeyValuePairItems): Changed to encode File entry
+        values as their filenames, rather than skipping them.
+
 2021-12-02  Tyler Wilcock  <tyle...@apple.com>
 
         AX Isolated Tree: Document links should be stored in web areas, not the root

Modified: trunk/Source/WebCore/html/FileInputType.cpp (286426 => 286427)


--- trunk/Source/WebCore/html/FileInputType.cpp	2021-12-02 15:25:52 UTC (rev 286426)
+++ trunk/Source/WebCore/html/FileInputType.cpp	2021-12-02 15:34:01 UTC (rev 286427)
@@ -158,7 +158,7 @@
     filesChosen(filesFromFormControlState(state));
 }
 
-bool FileInputType::appendFormData(DOMFormData& formData, bool multipart) const
+bool FileInputType::appendFormData(DOMFormData& formData, bool) const
 {
     ASSERT(element());
     RefPtr fileList = element()->files();
@@ -166,18 +166,6 @@
 
     auto name = element()->name();
 
-    if (!multipart) {
-        // Send only the basenames.
-        // 4.10.16.4 and 4.10.16.6 sections in HTML5.
-
-        if (fileList->isEmpty())
-            formData.append(name, emptyString());
-
-        for (auto& file : fileList->files())
-            formData.append(name, file->name());
-        return true;
-    }
-
     // If no filename at all is entered, return successful but empty.
     // Null would be more logical, but Netscape posts an empty file. Argh.
     if (fileList->isEmpty()) {

Modified: trunk/Source/WebCore/platform/network/FormData.cpp (286426 => 286427)


--- trunk/Source/WebCore/platform/network/FormData.cpp	2021-12-02 15:25:52 UTC (rev 286426)
+++ trunk/Source/WebCore/platform/network/FormData.cpp	2021-12-02 15:34:01 UTC (rev 286427)
@@ -273,15 +273,16 @@
 
     Vector<char> encodedData;
     for (auto& item : formData.items()) {
-        // FIXME: The expected behavior is to convert files to string for enctype "text/plain". Conversion may be added at "void DOMFormData::set(const String& name, Blob& blob, const String& filename)" or here.
-        // FIXME: Remove the following if statement when fixed.
-        if (!std::holds_alternative<String>(item.data))
-            continue;
-        
-        ASSERT(std::holds_alternative<String>(item.data));
+        String stringValue = WTF::switchOn(item.data,
+            [](const String& string) {
+                return string;
+            }, [](const RefPtr<File>& file) {
+                return file->name();
+            }
+        );
 
         auto normalizedName = normalizeStringData(encoding, item.name);
-        auto normalizedStringData = normalizeStringData(encoding, std::get<String>(item.data));
+        auto normalizedStringData = normalizeStringData(encoding, stringValue);
         FormDataBuilder::addKeyValuePairAsFormData(encodedData, normalizedName, normalizedStringData, encodingType);
     }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to