Changeset 286427 in webkit


Ignore:
Timestamp:
Dec 2, 2021 7:34:01 AM (8 months ago)
Author:
commit-queue@webkit.org
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 <andreu@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.

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r286425 r286427  
     12021-12-02  Andreu Botella  <andreu@andreubotella.com>
     2
     3        File inputs in non-multipart form submissions show up as string values in the formdata event
     4        https://bugs.webkit.org/show_bug.cgi?id=233725
     5
     6        Reviewed by Chris Dumez.
     7
     8        Added tests in web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set.html
     9        to check that file inputs show up as File entries in the formdata event.
     10
     11        * web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set-expected.txt:
     12        * web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set.html:
     13        * web-platform-tests/html/semantics/forms/form-submission-0/text-plain.window-expected.txt:
     14        * web-platform-tests/html/semantics/forms/form-submission-0/urlencoded2.window-expected.txt:
     15
    1162021-12-02  Alexey Shvayka  <ashvayka@apple.com>
    217
  • trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set-expected.txt

    r280310 r286427  
     1
     2
     3
    14
    25
     
    1316PASS "formdata" event bubbles, and is not cancelable.
    1417PASS "formdata" event bubbles in an orphan tree.
     18PASS Files in a application/x-www-form-urlencoded form show up as File objects in the "formData" IDL attribute
     19PASS Files in a multipart/form-data form show up as File objects in the "formData" IDL attribute
     20PASS Files in a text/plain form show up as File objects in the "formData" IDL attribute
    1521PASS "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.
    1622PASS Entries added to "formData" IDL attribute should be submitted.
  • trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set.html

    r279427 r286427  
    7878}, '"formdata" event bubbles in an orphan tree.');
    7979
     80for (const enctype of ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"]) {
     81  test((t) => {
     82    let form = populateForm('<input name=file type=file><input name=empty type=file>');
     83    form.enctype = enctype;
     84
     85    const file = new File([], "filename");
     86    const dataTransfer = new DataTransfer();
     87    dataTransfer.items.add(file);
     88    form.querySelector('input[name=file]').files = dataTransfer.files;
     89
     90    form.addEventListener('formdata', t.step_func(e => {
     91      assert_true(e.formData.has('file'));
     92      assert_equals(e.formData.get('file'), file);
     93      assert_true(e.formData.has('empty'));
     94      assert_true(e.formData.get('empty') instanceof File);
     95    }));
     96    form.submit();
     97  }, `Files in a ${enctype} form show up as File objects in the "formData" IDL attribute`);
     98}
     99
    80100test(() => {
    81101  let listener1ok = false;
  • trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/text-plain.window-expected.txt

    r286221 r286427  
    33PASS text/plain: Basic test (formdata event)
    44PASS text/plain: Basic File test (normal form)
    5 FAIL text/plain: Basic File test (formdata event) assert_equals: expected "basic=file-test.txt\r\n" but got ""
     5PASS text/plain: Basic File test (formdata event)
    66PASS text/plain: 0x00 in name (normal form)
    77PASS text/plain: 0x00 in name (formdata event)
     
    99PASS text/plain: 0x00 in value (formdata event)
    1010PASS text/plain: 0x00 in filename (normal form)
    11 FAIL text/plain: 0x00 in filename (formdata event) assert_equals: expected "a=b\0c\r\n" but got ""
     11PASS text/plain: 0x00 in filename (formdata event)
    1212PASS text/plain: \n in name (normal form)
    1313PASS text/plain: \n in name (formdata event)
     
    2727PASS text/plain: \n\r in value (formdata event)
    2828PASS text/plain: \n in filename (normal form)
    29 FAIL text/plain: \n in filename (formdata event) assert_equals: expected "a=b\r\nc\r\n" but got ""
     29PASS text/plain: \n in filename (formdata event)
    3030PASS text/plain: \r in filename (normal form)
    31 FAIL text/plain: \r in filename (formdata event) assert_equals: expected "a=b\r\nc\r\n" but got ""
     31PASS text/plain: \r in filename (formdata event)
    3232PASS text/plain: \r\n in filename (normal form)
    33 FAIL text/plain: \r\n in filename (formdata event) assert_equals: expected "a=b\r\nc\r\n" but got ""
     33PASS text/plain: \r\n in filename (formdata event)
    3434PASS text/plain: \n\r in filename (normal form)
    35 FAIL text/plain: \n\r in filename (formdata event) assert_equals: expected "a=b\r\n\r\nc\r\n" but got ""
     35PASS text/plain: \n\r in filename (formdata event)
    3636PASS text/plain: double quote in name (normal form)
    3737PASS text/plain: double quote in name (formdata event)
     
    3939PASS text/plain: double quote in value (formdata event)
    4040PASS text/plain: double quote in filename (normal form)
    41 FAIL text/plain: double quote in filename (formdata event) assert_equals: expected "a=b\"c\r\n" but got ""
     41PASS text/plain: double quote in filename (formdata event)
    4242PASS text/plain: single quote in name (normal form)
    4343PASS text/plain: single quote in name (formdata event)
     
    4545PASS text/plain: single quote in value (formdata event)
    4646PASS text/plain: single quote in filename (normal form)
    47 FAIL text/plain: single quote in filename (formdata event) assert_equals: expected "a=b'c\r\n" but got ""
     47PASS text/plain: single quote in filename (formdata event)
    4848PASS text/plain: backslash in name (normal form)
    4949PASS text/plain: backslash in name (formdata event)
     
    5151PASS text/plain: backslash in value (formdata event)
    5252PASS text/plain: backslash in filename (normal form)
    53 FAIL text/plain: backslash in filename (formdata event) assert_equals: expected "a=b\\c\r\n" but got ""
     53PASS text/plain: backslash in filename (formdata event)
    5454PASS text/plain: non-ASCII in name and value (normal form)
    5555PASS text/plain: non-ASCII in name and value (formdata event)
    5656PASS text/plain: non-ASCII in filename (normal form)
    57 FAIL text/plain: non-ASCII in filename (formdata event) assert_equals: expected "a=ə.txt\r\n" but got ""
     57PASS text/plain: non-ASCII in filename (formdata event)
    5858PASS text/plain: characters not in encoding in name and value (normal form)
    5959PASS text/plain: characters not in encoding in name and value (formdata event)
    6060PASS text/plain: character not in encoding in filename (normal form)
    61 FAIL text/plain: character not in encoding in filename (formdata event) assert_equals: expected "á=&#128169;\r\n" but got ""
     61PASS text/plain: character not in encoding in filename (formdata event)
    6262
  • trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/urlencoded2.window-expected.txt

    r285810 r286427  
    33PASS application/x-www-form-urlencoded: Basic test (formdata event)
    44PASS application/x-www-form-urlencoded: Basic File test (normal form)
    5 FAIL application/x-www-form-urlencoded: Basic File test (formdata event) assert_equals: expected "basic=file-test.txt" but got ""
     5PASS application/x-www-form-urlencoded: Basic File test (formdata event)
    66PASS application/x-www-form-urlencoded: 0x00 in name (normal form)
    77PASS application/x-www-form-urlencoded: 0x00 in name (formdata event)
     
    99PASS application/x-www-form-urlencoded: 0x00 in value (formdata event)
    1010PASS application/x-www-form-urlencoded: 0x00 in filename (normal form)
    11 FAIL application/x-www-form-urlencoded: 0x00 in filename (formdata event) assert_equals: expected "a=b%00c" but got ""
     11PASS application/x-www-form-urlencoded: 0x00 in filename (formdata event)
    1212PASS application/x-www-form-urlencoded: \n in name (normal form)
    1313PASS application/x-www-form-urlencoded: \n in name (formdata event)
     
    2727PASS application/x-www-form-urlencoded: \n\r in value (formdata event)
    2828PASS application/x-www-form-urlencoded: \n in filename (normal form)
    29 FAIL application/x-www-form-urlencoded: \n in filename (formdata event) assert_equals: expected "a=b%0D%0Ac" but got ""
     29PASS application/x-www-form-urlencoded: \n in filename (formdata event)
    3030PASS application/x-www-form-urlencoded: \r in filename (normal form)
    31 FAIL application/x-www-form-urlencoded: \r in filename (formdata event) assert_equals: expected "a=b%0D%0Ac" but got ""
     31PASS application/x-www-form-urlencoded: \r in filename (formdata event)
    3232PASS application/x-www-form-urlencoded: \r\n in filename (normal form)
    33 FAIL application/x-www-form-urlencoded: \r\n in filename (formdata event) assert_equals: expected "a=b%0D%0Ac" but got ""
     33PASS application/x-www-form-urlencoded: \r\n in filename (formdata event)
    3434PASS application/x-www-form-urlencoded: \n\r in filename (normal form)
    35 FAIL application/x-www-form-urlencoded: \n\r in filename (formdata event) assert_equals: expected "a=b%0D%0A%0D%0Ac" but got ""
     35PASS application/x-www-form-urlencoded: \n\r in filename (formdata event)
    3636PASS application/x-www-form-urlencoded: double quote in name (normal form)
    3737PASS application/x-www-form-urlencoded: double quote in name (formdata event)
     
    3939PASS application/x-www-form-urlencoded: double quote in value (formdata event)
    4040PASS application/x-www-form-urlencoded: double quote in filename (normal form)
    41 FAIL application/x-www-form-urlencoded: double quote in filename (formdata event) assert_equals: expected "a=b%22c" but got ""
     41PASS application/x-www-form-urlencoded: double quote in filename (formdata event)
    4242PASS application/x-www-form-urlencoded: single quote in name (normal form)
    4343PASS application/x-www-form-urlencoded: single quote in name (formdata event)
     
    4545PASS application/x-www-form-urlencoded: single quote in value (formdata event)
    4646PASS application/x-www-form-urlencoded: single quote in filename (normal form)
    47 FAIL application/x-www-form-urlencoded: single quote in filename (formdata event) assert_equals: expected "a=b%27c" but got ""
     47PASS application/x-www-form-urlencoded: single quote in filename (formdata event)
    4848PASS application/x-www-form-urlencoded: backslash in name (normal form)
    4949PASS application/x-www-form-urlencoded: backslash in name (formdata event)
     
    5151PASS application/x-www-form-urlencoded: backslash in value (formdata event)
    5252PASS application/x-www-form-urlencoded: backslash in filename (normal form)
    53 FAIL application/x-www-form-urlencoded: backslash in filename (formdata event) assert_equals: expected "a=b%5Cc" but got ""
     53PASS application/x-www-form-urlencoded: backslash in filename (formdata event)
    5454PASS application/x-www-form-urlencoded: non-ASCII in name and value (normal form)
    5555PASS application/x-www-form-urlencoded: non-ASCII in name and value (formdata event)
    5656PASS application/x-www-form-urlencoded: non-ASCII in filename (normal form)
    57 FAIL application/x-www-form-urlencoded: non-ASCII in filename (formdata event) assert_equals: expected "a=%C9%99.txt" but got ""
     57PASS application/x-www-form-urlencoded: non-ASCII in filename (formdata event)
    5858PASS application/x-www-form-urlencoded: characters not in encoding in name and value (normal form)
    5959PASS application/x-www-form-urlencoded: characters not in encoding in name and value (formdata event)
    6060PASS application/x-www-form-urlencoded: character not in encoding in filename (normal form)
    61 FAIL application/x-www-form-urlencoded: character not in encoding in filename (formdata event) assert_equals: expected "%E1=%26%23128169%3B" but got ""
     61PASS application/x-www-form-urlencoded: character not in encoding in filename (formdata event)
    6262
  • trunk/Source/WebCore/ChangeLog

    r286426 r286427  
     12021-12-02  Andreu Botella  <andreu@andreubotella.com>
     2
     3        File inputs in non-multipart form submissions show up as string values in the formdata event
     4        https://bugs.webkit.org/show_bug.cgi?id=233725
     5
     6        Reviewed by Chris Dumez.
     7
     8        When a form's entry list was constructed form a non-multipart/form-data form submission,
     9        file inputs were added to the DOMFormData object as string values consisting of the file's
     10        filename. Before r280310, this optimization was unobservable, since the DOMFormData object
     11        was never exposed to the user halfway through a form submission.
     12
     13        r280310 changed this by adding the formdata event, which fires at the end of the "construct
     14        the entry list" algorithm and can be used to both inspect and modify the DOMFormData object.
     15        This means that it is now observable that file inputs in urlencoded and text/plain form
     16        submissions are encoded as their filenames, and that any new File entries added to the
     17        DOMFormData object the event listeners will be skipped when building the form payload.
     18
     19        This change fixes that by always adding file inputs to DOMFormData as File entries, and
     20        using a File's filename as the string value in FormData::appendNonMultipartKeyValuePairItems
     21
     22        Tests: imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/constructing-form-data-set.html
     23               imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/text-plain.window.html
     24               imported/w3c/web-platform-tests/html/semantics/forms/form-submission-0/urlencoded2.window.html
     25
     26        * html/FileInputType.cpp:
     27        (WebCore::FileInputType::appendFormData const): Changed to always add File entries to the
     28        DOMFormData object, rather than adding the filenames as string values when `multipart` is
     29        false.
     30        * platform/network/FormData.cpp:
     31        (WebCore::FormData::appendNonMultiPartKeyValuePairItems): Changed to encode File entry
     32        values as their filenames, rather than skipping them.
     33
    1342021-12-02  Tyler Wilcock  <tyler_w@apple.com>
    235
  • trunk/Source/WebCore/html/FileInputType.cpp

    r285932 r286427  
    159159}
    160160
    161 bool FileInputType::appendFormData(DOMFormData& formData, bool multipart) const
     161bool FileInputType::appendFormData(DOMFormData& formData, bool) const
    162162{
    163163    ASSERT(element());
     
    166166
    167167    auto name = element()->name();
    168 
    169     if (!multipart) {
    170         // Send only the basenames.
    171         // 4.10.16.4 and 4.10.16.6 sections in HTML5.
    172 
    173         if (fileList->isEmpty())
    174             formData.append(name, emptyString());
    175 
    176         for (auto& file : fileList->files())
    177             formData.append(name, file->name());
    178         return true;
    179     }
    180168
    181169    // If no filename at all is entered, return successful but empty.
  • trunk/Source/WebCore/platform/network/FormData.cpp

    r284095 r286427  
    274274    Vector<char> encodedData;
    275275    for (auto& item : formData.items()) {
    276         // 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.
    277         // FIXME: Remove the following if statement when fixed.
    278         if (!std::holds_alternative<String>(item.data))
    279             continue;
    280        
    281         ASSERT(std::holds_alternative<String>(item.data));
     276        String stringValue = WTF::switchOn(item.data,
     277            [](const String& string) {
     278                return string;
     279            }, [](const RefPtr<File>& file) {
     280                return file->name();
     281            }
     282        );
    282283
    283284        auto normalizedName = normalizeStringData(encoding, item.name);
    284         auto normalizedStringData = normalizeStringData(encoding, std::get<String>(item.data));
     285        auto normalizedStringData = normalizeStringData(encoding, stringValue);
    285286        FormDataBuilder::addKeyValuePairAsFormData(encodedData, normalizedName, normalizedStringData, encodingType);
    286287    }
Note: See TracChangeset for help on using the changeset viewer.