Bug 1677832 [wpt PR 26556] - Test multipart/form-data form submission with controls and punctuation., a=testonly
Automatic update from web-platform-tests Test multipart/form-data form submission with controls and punctuation This PR adds tests for forms containing controls and punctuation, both on multipart/form-data request bodies and on FormData objects. This is in part a modification of #8618, which got closed downstream due to inactivity. Co-Authored-By: Benjamin C. Wiley Sittler <bsittler@chromium.org> -- wpt-commits: ebb2824cabb11ff1ef3bfce1b7530980efbc916d wpt-pr: 26556
This commit is contained in:
committed by
moz-wptsync-bot
parent
d00f4b60c2
commit
ae83fb121d
@@ -0,0 +1,24 @@
|
||||
from wptserve.utils import isomorphic_encode
|
||||
|
||||
# Outputs the request body, with controls and non-ASCII bytes escaped
|
||||
# (b"\n" becomes b"\\x0a"), and with backslashes doubled.
|
||||
# As a convenience, CRLF newlines are left as is.
|
||||
|
||||
def escape_byte(byte):
|
||||
if b"\0" <= byte <= b"\x1F" or byte >= b"\x7F":
|
||||
return b"\\x%02x" % ord(byte)
|
||||
if byte == b"\\":
|
||||
return b"\\\\"
|
||||
return byte
|
||||
|
||||
def main(request, response):
|
||||
|
||||
headers = [(b"X-Request-Method", isomorphic_encode(request.method)),
|
||||
(b"X-Request-Content-Length", request.headers.get(b"Content-Length", b"NO")),
|
||||
(b"X-Request-Content-Type", request.headers.get(b"Content-Type", b"NO")),
|
||||
# Avoid any kind of content sniffing on the response.
|
||||
(b"Content-Type", b"text/plain; charset=UTF-8")]
|
||||
|
||||
content = b"".join(map(escape_byte, request.body)).replace(b"\\x0d\\x0a", b"\r\n")
|
||||
|
||||
return headers, content
|
||||
@@ -0,0 +1,117 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8" />
|
||||
<title>Upload files named using controls (tentative)</title>
|
||||
<!--
|
||||
NOTE: This test is tentative because encoding for filename
|
||||
control characters is not yet standardized.
|
||||
-->
|
||||
<link
|
||||
rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data"
|
||||
/>
|
||||
<link
|
||||
rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist"
|
||||
/>
|
||||
<link rel="help" href="https://w3c.github.io/FileAPI/#file-constructor" />
|
||||
<link
|
||||
rel="author"
|
||||
title="Benjamin C. Wiley Sittler"
|
||||
href="mailto:bsittler@chromium.org"
|
||||
/>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../support/send-file-form-helper.js"></script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-NUL-[\0].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-NUL-[\0].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-BS-[\b].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-BS-[\b].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-VT-[\v].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-VT-[\v].txt",
|
||||
});
|
||||
|
||||
// These have characters that undergo processing in name=,
|
||||
// filename=, and/or value; formPostFileUploadTest postprocesses
|
||||
// expectedEncodedBaseName for these internally.
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-LF-[\n].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-LF-[\n].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-LF-CR-[\n\r].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-LF-CR-[\n\r].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-CR-[\r].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-CR-[\r].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-CR-LF-[\r\n].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-CR-LF-[\r\n].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-HT-[\t].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-HT-[\t].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-FF-[\f].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-FF-[\f].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-DEL-[\x7F].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-DEL-[\x7F].txt",
|
||||
});
|
||||
|
||||
// The rest should be passed through unmodified:
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-ESC-[\x1B].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-ESC-[\x1B].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-SPACE-[ ].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-SPACE-[ ].txt",
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,230 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8" />
|
||||
<title>Upload files named using punctuation (tentative)</title>
|
||||
<!--
|
||||
NOTE: This test is tentative because encoding for filename
|
||||
punctuation characters is not yet standardized.
|
||||
-->
|
||||
<link
|
||||
rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data"
|
||||
/>
|
||||
<link
|
||||
rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist"
|
||||
/>
|
||||
<link rel="help" href="https://w3c.github.io/FileAPI/#file-constructor" />
|
||||
<link
|
||||
rel="author"
|
||||
title="Benjamin C. Wiley Sittler"
|
||||
href="mailto:bsittler@chromium.org"
|
||||
/>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../support/send-file-form-helper.js"></script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
// These have characters that undergo processing in name=,
|
||||
// filename=, and/or value; formPostFileUploadTest postprocesses
|
||||
// expectedEncodedBaseName for these internally.
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-QUOTATION-MARK-[\x22].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName:
|
||||
"file-for-upload-in-form-QUOTATION-MARK-[\x22].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: '"file-for-upload-in-form-double-quoted.txt"',
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: '"file-for-upload-in-form-double-quoted.txt"',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-REVERSE-SOLIDUS-[\\].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName:
|
||||
"file-for-upload-in-form-REVERSE-SOLIDUS-[\\].txt",
|
||||
});
|
||||
|
||||
// The rest should be passed through unmodified:
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-EXCLAMATION-MARK-[!].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-EXCLAMATION-MARK-[!].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-DOLLAR-SIGN-[$].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-DOLLAR-SIGN-[$].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-PERCENT-SIGN-[%].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-PERCENT-SIGN-[%].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-AMPERSAND-[&].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-AMPERSAND-[&].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-APOSTROPHE-['].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-APOSTROPHE-['].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-LEFT-PARENTHESIS-[(].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-LEFT-PARENTHESIS-[(].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-RIGHT-PARENTHESIS-[)].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName:
|
||||
"file-for-upload-in-form-RIGHT-PARENTHESIS-[)].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-ASTERISK-[*].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-ASTERISK-[*].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-PLUS-SIGN-[+].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-PLUS-SIGN-[+].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-COMMA-[,].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-COMMA-[,].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-FULL-STOP-[.].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-FULL-STOP-[.].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-SOLIDUS-[/].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-SOLIDUS-[/].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-COLON-[:].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-COLON-[:].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-SEMICOLON-[;].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-SEMICOLON-[;].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-EQUALS-SIGN-[=].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-EQUALS-SIGN-[=].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-QUESTION-MARK-[?].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-QUESTION-MARK-[?].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-CIRCUMFLEX-ACCENT-[^].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName:
|
||||
"file-for-upload-in-form-CIRCUMFLEX-ACCENT-[^].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-LEFT-SQUARE-BRACKET-[[].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName:
|
||||
"file-for-upload-in-form-LEFT-SQUARE-BRACKET-[[].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-RIGHT-SQUARE-BRACKET-[]].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName:
|
||||
"file-for-upload-in-form-RIGHT-SQUARE-BRACKET-[]].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-LEFT-CURLY-BRACKET-[{].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName:
|
||||
"file-for-upload-in-form-LEFT-CURLY-BRACKET-[{].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-VERTICAL-LINE-[|].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-VERTICAL-LINE-[|].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-RIGHT-CURLY-BRACKET-[}].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName:
|
||||
"file-for-upload-in-form-RIGHT-CURLY-BRACKET-[}].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-TILDE-[~].txt",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "file-for-upload-in-form-TILDE-[~].txt",
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "'file-for-upload-in-form-single-quoted.txt'",
|
||||
formEncoding: "UTF-8",
|
||||
expectedEncodedBaseName: "'file-for-upload-in-form-single-quoted.txt'",
|
||||
});
|
||||
</script>
|
||||
@@ -27,35 +27,36 @@ formPostFileUploadTest({
|
||||
fileBaseName: 'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt',
|
||||
formEncoding: 'UTF-8',
|
||||
expectedEncodedBaseName: (
|
||||
'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt'),
|
||||
'file-for-upload-in-form-\xEF\x9F\xB0\xEF\x9E\x93\xEF\x9E\x83\xEF\x9E\xA0.txt'),
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'windows-1252',
|
||||
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
formEncoding: 'UTF-8',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
expectedEncodedBaseName: (
|
||||
'file-for-upload-in-form-\xC3\xA2\xCB\x9C\xC2\xBA\xC3\xB0\xC5\xB8\xCB\x9C\xE2\x80\x9A.txt'),
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'JIS X 0201 and JIS X 0208',
|
||||
fileBaseName: 'file-for-upload-in-form-★星★.txt',
|
||||
formEncoding: 'UTF-8',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-★星★.txt',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-\xE2\x98\x85\xE6\x98\x9F\xE2\x98\x85.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'Unicode',
|
||||
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
formEncoding: 'UTF-8',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-\xE2\x98\xBA\xF0\x9F\x98\x82.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'Unicode',
|
||||
fileBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
|
||||
formEncoding: 'UTF-8',
|
||||
expectedEncodedBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
|
||||
expectedEncodedBaseName: `file-for-upload-in-form-${kTestFallbackUtf8}.txt`,
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
@@ -33,15 +33,14 @@ formPostFileUploadTest({
|
||||
fileNameSource: 'x-user-defined',
|
||||
fileBaseName: 'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt',
|
||||
formEncoding: 'windows-1252',
|
||||
expectedEncodedBaseName: (
|
||||
'file-for-upload-in-form-.txt'),
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
fileNameSource: 'windows-1252',
|
||||
fileBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
formEncoding: 'windows-1252',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-☺😂.txt',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-\xE2\x98\xBA\xF0\x9F\x98\x82.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
|
||||
@@ -33,7 +33,7 @@ formPostFileUploadTest({
|
||||
fileNameSource: 'x-user-defined',
|
||||
fileBaseName: 'file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt',
|
||||
formEncoding: 'x-user-defined',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-𓃠.txt',
|
||||
expectedEncodedBaseName: 'file-for-upload-in-form-\xF0\x93\x83\xA0.txt',
|
||||
});
|
||||
|
||||
formPostFileUploadTest({
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8" />
|
||||
<title>FormData: Upload files named using controls (tentative)</title>
|
||||
<!--
|
||||
NOTE: This test is tentative because encoding for filename
|
||||
control characters is not yet standardized.
|
||||
-->
|
||||
<link
|
||||
rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data"
|
||||
/>
|
||||
<link
|
||||
rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist"
|
||||
/>
|
||||
<link rel="help" href="https://w3c.github.io/FileAPI/#file-constructor" />
|
||||
<link
|
||||
rel="author"
|
||||
title="Benjamin C. Wiley Sittler"
|
||||
href="mailto:bsittler@chromium.org"
|
||||
/>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../support/send-file-formdata-helper.js"></script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-NUL-[\0].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-BS-[\b].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-VT-[\v].txt",
|
||||
});
|
||||
|
||||
// These have characters that undergo processing in name=,
|
||||
// filename=, and/or value; formDataPostFileUploadTest postprocesses
|
||||
// expectedEncodedBaseName for these internally.
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-LF-[\n].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-LF-CR-[\n\r].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-CR-[\r].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-CR-LF-[\r\n].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-HT-[\t].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-FF-[\f].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-DEL-[\x7F].txt",
|
||||
});
|
||||
|
||||
// The rest should be passed through unmodified:
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-ESC-[\x1B].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-SPACE-[ ].txt",
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,168 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8" />
|
||||
<title>FormData: Upload files named using punctuation (tentative)</title>
|
||||
<!--
|
||||
NOTE: This test is tentative because encoding for filename
|
||||
punctuation characters is not yet standardized.
|
||||
-->
|
||||
<link
|
||||
rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data"
|
||||
/>
|
||||
<link
|
||||
rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist"
|
||||
/>
|
||||
<link rel="help" href="https://w3c.github.io/FileAPI/#file-constructor" />
|
||||
<link
|
||||
rel="author"
|
||||
title="Benjamin C. Wiley Sittler"
|
||||
href="mailto:bsittler@chromium.org"
|
||||
/>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../support/send-file-formdata-helper.js"></script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
// These have characters that undergo processing in name=,
|
||||
// filename=, and/or value; formDataPostFileUploadTest postprocesses
|
||||
// expectedEncodedBaseName for these internally.
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-QUOTATION-MARK-[\x22].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: '"file-for-upload-in-form-double-quoted.txt"',
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-REVERSE-SOLIDUS-[\\].txt",
|
||||
});
|
||||
|
||||
// The rest should be passed through unmodified:
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-EXCLAMATION-MARK-[!].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-DOLLAR-SIGN-[$].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-PERCENT-SIGN-[%].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-AMPERSAND-[&].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-APOSTROPHE-['].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-LEFT-PARENTHESIS-[(].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-RIGHT-PARENTHESIS-[)].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-ASTERISK-[*].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-PLUS-SIGN-[+].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-COMMA-[,].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-FULL-STOP-[.].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-SOLIDUS-[/].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-COLON-[:].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-SEMICOLON-[;].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-EQUALS-SIGN-[=].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-QUESTION-MARK-[?].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-CIRCUMFLEX-ACCENT-[^].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-LEFT-SQUARE-BRACKET-[[].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-RIGHT-SQUARE-BRACKET-[]].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-LEFT-CURLY-BRACKET-[{].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-VERTICAL-LINE-[|].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-RIGHT-CURLY-BRACKET-[}].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form-TILDE-[~].txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "'file-for-upload-in-form-single-quoted.txt'",
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,53 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8" />
|
||||
<title>FormData: Upload files in UTF-8 fetch()</title>
|
||||
<link
|
||||
rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data"
|
||||
/>
|
||||
<link
|
||||
rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist"
|
||||
/>
|
||||
<link rel="help" href="https://w3c.github.io/FileAPI/#file-constructor" />
|
||||
<link
|
||||
rel="author"
|
||||
title="Benjamin C. Wiley Sittler"
|
||||
href="mailto:bsittler@chromium.org"
|
||||
/>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../support/send-file-formdata-helper.js"></script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form.txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "x-user-defined",
|
||||
fileBaseName: "file-for-upload-in-form-\uF7F0\uF793\uF783\uF7A0.txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "windows-1252",
|
||||
fileBaseName: "file-for-upload-in-form-☺😂.txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "JIS X 0201 and JIS X 0208",
|
||||
fileBaseName: "file-for-upload-in-form-★星★.txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "Unicode",
|
||||
fileBaseName: "file-for-upload-in-form-☺😂.txt",
|
||||
});
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "Unicode",
|
||||
fileBaseName: `file-for-upload-in-form-${kTestChars}.txt`,
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8" />
|
||||
<title>FormData: Upload ASCII-named file in UTF-8 form</title>
|
||||
<link
|
||||
rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data"
|
||||
/>
|
||||
<link
|
||||
rel="help"
|
||||
href="https://html.spec.whatwg.org/multipage/dnd.html#datatransferitemlist"
|
||||
/>
|
||||
<link rel="help" href="https://w3c.github.io/FileAPI/#file-constructor" />
|
||||
<link
|
||||
rel="author"
|
||||
title="Benjamin C. Wiley Sittler"
|
||||
href="mailto:bsittler@chromium.org"
|
||||
/>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="../support/send-file-formdata-helper.js"></script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
formDataPostFileUploadTest({
|
||||
fileNameSource: "ASCII",
|
||||
fileBaseName: "file-for-upload-in-form.txt",
|
||||
});
|
||||
</script>
|
||||
@@ -1,5 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
// See /FileAPI/file/resources/echo-content-escaped.py
|
||||
function escapeString(string) {
|
||||
return string.replace(/\\/g, "\\\\").replace(
|
||||
/[^\x20-\x7E]/g,
|
||||
(x) => {
|
||||
let hex = x.charCodeAt(0).toString(16);
|
||||
if (hex.length < 2) hex = "0" + hex;
|
||||
return `\\x${hex}`;
|
||||
},
|
||||
).replace(/\\x0d\\x0a/g, "\r\n");
|
||||
}
|
||||
|
||||
// Rationale for this particular test character sequence, which is
|
||||
// used in filenames and also in file contents:
|
||||
//
|
||||
@@ -72,36 +84,46 @@
|
||||
// are also allowed in Windows Unicode filenames.
|
||||
const kTestChars = 'ABC~‾¥≈¤・・•∙·☼★星🌟星★☼·∙•・・¤≈¥‾~XYZ';
|
||||
|
||||
// NOTE: The expected interpretation of ISO-2022-JP according to
|
||||
// https://encoding.spec.whatwg.org/#iso-2022-jp-encoder unifies
|
||||
// single-byte and double-byte katakana.
|
||||
const kTestFallbackIso2022jp =
|
||||
('ABC~\x1B(J~\\≈¤\x1B$B!&!&\x1B(B•∙·☼\x1B$B!z@1\x1B(B🌟' +
|
||||
'\x1B$B@1!z\x1B(B☼·∙•\x1B$B!&!&\x1B(B¤≈\x1B(J\\~\x1B(B~XYZ').replace(
|
||||
/[^\0-\x7F]/gu,
|
||||
x => `&#${x.codePointAt(0)};`);
|
||||
// The kTestFallback* strings represent the expected byte sequence from
|
||||
// encoding kTestChars with the given encoding with "html" replacement
|
||||
// mode, isomorphic-decoded. That means, characters that can't be
|
||||
// encoded in that encoding get HTML-escaped, but no further
|
||||
// `escapeString`-like escapes are needed.
|
||||
const kTestFallbackUtf8 = (
|
||||
"ABC~\xE2\x80\xBE\xC2\xA5\xE2\x89\x88\xC2\xA4\xEF\xBD\xA5\xE3\x83\xBB\xE2" +
|
||||
"\x80\xA2\xE2\x88\x99\xC2\xB7\xE2\x98\xBC\xE2\x98\x85\xE6\x98\x9F\xF0\x9F" +
|
||||
"\x8C\x9F\xE6\x98\x9F\xE2\x98\x85\xE2\x98\xBC\xC2\xB7\xE2\x88\x99\xE2\x80" +
|
||||
"\xA2\xE3\x83\xBB\xEF\xBD\xA5\xC2\xA4\xE2\x89\x88\xC2\xA5\xE2\x80\xBE~XYZ"
|
||||
);
|
||||
|
||||
// NOTE: \uFFFD is used here to replace Windows-1252 bytes to match
|
||||
// how we will see them in the reflected POST bytes in a frame using
|
||||
// UTF-8 byte interpretation. The bytes will actually be intact, but
|
||||
// this code cannot tell and does not really care.
|
||||
const kTestFallbackWindows1252 =
|
||||
'ABC~‾\xA5≈\xA4・・\x95∙\xB7☼★星🌟星★☼\xB7∙\x95・・\xA4≈\xA5‾~XYZ'.replace(
|
||||
/[^\0-\xFF]/gu,
|
||||
x => `&#${x.codePointAt(0)};`).replace(/[\x80-\xFF]/g, '\uFFFD');
|
||||
const kTestFallbackIso2022jp = (
|
||||
("ABC~\x1B(J~\\≈¤\x1B$B!&!&\x1B(B•∙·☼\x1B$B!z@1\x1B(B🌟" +
|
||||
"\x1B$B@1!z\x1B(B☼·∙•\x1B$B!&!&\x1B(B¤≈\x1B(J\\~\x1B(B~XYZ")
|
||||
.replace(/[^\0-\x7F]/gu, (x) => `&#${x.codePointAt(0)};`)
|
||||
);
|
||||
|
||||
const kTestFallbackXUserDefined =
|
||||
kTestChars.replace(/[^\0-\x7F]/gu, x => `&#${x.codePointAt(0)};`);
|
||||
const kTestFallbackWindows1252 = (
|
||||
"ABC~‾\xA5≈\xA4・・\x95∙\xB7☼★星🌟星★☼\xB7∙\x95・・\xA4≈\xA5‾~XYZ".replace(
|
||||
/[^\0-\xFF]/gu,
|
||||
(x) => `&#${x.codePointAt(0)};`,
|
||||
)
|
||||
);
|
||||
|
||||
const kTestFallbackXUserDefined = kTestChars.replace(
|
||||
/[^\0-\x7F]/gu,
|
||||
(x) => `&#${x.codePointAt(0)};`,
|
||||
);
|
||||
|
||||
// formPostFileUploadTest - verifies multipart upload structure and
|
||||
// numeric character reference replacement for filenames, field names,
|
||||
// and field values.
|
||||
// and field values using form submission.
|
||||
//
|
||||
// Uses /fetch/api/resources/echo-content.py to echo the upload
|
||||
// POST with UTF-8 byte interpretation, leading to the "UTF-8 goggles"
|
||||
// behavior documented below for expectedEncodedBaseName when non-
|
||||
// UTF-8-compatible byte sequences appear in the formEncoding-encoded
|
||||
// uploaded data.
|
||||
// Uses /FileAPI/file/resources/echo-content-escaped.py to echo the
|
||||
// upload POST with controls and non-ASCII bytes escaped. This is done
|
||||
// because navigations whose response body contains [\0\b\v] may get
|
||||
// treated as a download, which is not what we want. Use the
|
||||
// `escapeString` function to replicate that kind of escape (note that
|
||||
// it takes an isomorphic-decoded string, not a byte sequence).
|
||||
//
|
||||
// Fields in the parameter object:
|
||||
//
|
||||
@@ -114,10 +136,9 @@ const kTestFallbackXUserDefined =
|
||||
// - formEncoding: the acceptCharset of the form used to submit the
|
||||
// test file. Used in the test name.
|
||||
// - expectedEncodedBaseName: the expected formEncoding-encoded
|
||||
// version of fileBaseName with unencodable characters replaced by
|
||||
// numeric character references and non-7-bit-ASCII bytes seen
|
||||
// through UTF-8 goggles; subsequences not interpretable as UTF-8
|
||||
// have each byte represented here by \uFFFD REPLACEMENT CHARACTER.
|
||||
// version of fileBaseName, isomorphic-decoded. That means, characters
|
||||
// that can't be encoded in that encoding get HTML-escaped, but no
|
||||
// further `escapeString`-like escapes are needed.
|
||||
const formPostFileUploadTest = ({
|
||||
fileNameSource,
|
||||
fileBaseName,
|
||||
@@ -140,7 +161,7 @@ const formPostFileUploadTest = ({
|
||||
|
||||
const form = Object.assign(document.createElement('form'), {
|
||||
acceptCharset: formEncoding,
|
||||
action: '/fetch/api/resources/echo-content.py',
|
||||
action: '/FileAPI/file/resources/echo-content-escaped.py',
|
||||
method: 'POST',
|
||||
enctype: 'multipart/form-data',
|
||||
target: formTargetFrame.name,
|
||||
@@ -194,7 +215,7 @@ const formPostFileUploadTest = ({
|
||||
// exposed through the newer .files[0].name API. This check
|
||||
// verifies that assumption.
|
||||
assert_equals(
|
||||
fileInput.files[0].name,
|
||||
baseNameOfFilePath(fileInput.files[0].name),
|
||||
baseNameOfFilePath(fileInput.value),
|
||||
`The basename of the field's value should match its files[0].name`);
|
||||
form.submit();
|
||||
@@ -219,6 +240,15 @@ const formPostFileUploadTest = ({
|
||||
`${fileBaseName}: multipart form data must end with ${boundary}--: ${
|
||||
JSON.stringify(formDataText)
|
||||
}`);
|
||||
|
||||
const asValue = expectedEncodedBaseName.replace(/\r\n?|\n/g, "\r\n");
|
||||
const asName = asValue.replace(/[\r\n"]/g, encodeURIComponent);
|
||||
const asFilename = expectedEncodedBaseName.replace(/[\r\n"]/g, encodeURIComponent);
|
||||
|
||||
// The response body from echo-content-escaped.py has controls and non-ASCII
|
||||
// bytes escaped, so any caller-provided field that might contain such bytes
|
||||
// must be passed to `escapeString`, after any other expected
|
||||
// transformations.
|
||||
const expectedText = [
|
||||
boundary,
|
||||
'Content-Disposition: form-data; name="_charset_"',
|
||||
@@ -227,19 +257,22 @@ const formPostFileUploadTest = ({
|
||||
boundary,
|
||||
'Content-Disposition: form-data; name="filename"',
|
||||
'',
|
||||
expectedEncodedBaseName,
|
||||
// Unlike for names and filenames, multipart/form-data values don't escape
|
||||
// \r\n linebreaks, and when they're read from an iframe they become \n.
|
||||
escapeString(asValue).replace(/\r\n/g, "\n"),
|
||||
boundary,
|
||||
`Content-Disposition: form-data; name="${expectedEncodedBaseName}"`,
|
||||
`Content-Disposition: form-data; name="${escapeString(asName)}"`,
|
||||
'',
|
||||
'filename',
|
||||
boundary,
|
||||
`Content-Disposition: form-data; name="file"; ` +
|
||||
`filename="${expectedEncodedBaseName}"`,
|
||||
`filename="${escapeString(asFilename)}"`,
|
||||
'Content-Type: text/plain',
|
||||
'',
|
||||
kTestChars,
|
||||
escapeString(kTestFallbackUtf8),
|
||||
boundary + '--',
|
||||
].join('\n');
|
||||
|
||||
assert_true(
|
||||
formDataText.startsWith(expectedText),
|
||||
`Unexpected multipart-shaped form data received:\n${
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
"use strict";
|
||||
|
||||
const kTestChars = "ABC~‾¥≈¤・・•∙·☼★星🌟星★☼·∙•・・¤≈¥‾~XYZ";
|
||||
|
||||
// formDataPostFileUploadTest - verifies multipart upload structure and
|
||||
// numeric character reference replacement for filenames, field names,
|
||||
// and field values using FormData and fetch().
|
||||
//
|
||||
// Uses /fetch/api/resources/echo-content.py to echo the upload
|
||||
// POST (unlike in send-file-form-helper.js, here we expect all
|
||||
// multipart/form-data request bodies to be UTF-8, so we don't need to
|
||||
// escape controls and non-ASCII bytes).
|
||||
//
|
||||
// Fields in the parameter object:
|
||||
//
|
||||
// - fileNameSource: purely explanatory and gives a clue about which
|
||||
// character encoding is the source for the non-7-bit-ASCII parts of
|
||||
// the fileBaseName, or Unicode if no smaller-than-Unicode source
|
||||
// contains all the characters. Used in the test name.
|
||||
// - fileBaseName: the not-necessarily-just-7-bit-ASCII file basename
|
||||
// used for the constructed test file. Used in the test name.
|
||||
const formDataPostFileUploadTest = ({
|
||||
fileNameSource,
|
||||
fileBaseName,
|
||||
}) => {
|
||||
promise_test(async (testCase) => {
|
||||
const formData = new FormData();
|
||||
let file = new Blob([kTestChars], { type: "text/plain" });
|
||||
try {
|
||||
// Switch to File in browsers that allow this
|
||||
file = new File([file], fileBaseName, { type: file.type });
|
||||
} catch (ignoredException) {
|
||||
}
|
||||
|
||||
// Used to verify that the browser agrees with the test about
|
||||
// field value replacement and encoding independently of file system
|
||||
// idiosyncracies.
|
||||
formData.append("filename", fileBaseName);
|
||||
|
||||
// Same, but with name and value reversed to ensure field names
|
||||
// get the same treatment.
|
||||
formData.append(fileBaseName, "filename");
|
||||
|
||||
formData.append("file", file, fileBaseName);
|
||||
|
||||
const formDataText = await (await fetch(
|
||||
`/fetch/api/resources/echo-content.py`,
|
||||
{
|
||||
method: "POST",
|
||||
body: formData,
|
||||
},
|
||||
)).text();
|
||||
const formDataLines = formDataText.split("\r\n");
|
||||
if (formDataLines.length && !formDataLines[formDataLines.length - 1]) {
|
||||
--formDataLines.length;
|
||||
}
|
||||
assert_greater_than(
|
||||
formDataLines.length,
|
||||
2,
|
||||
`${fileBaseName}: multipart form data must have at least 3 lines: ${
|
||||
JSON.stringify(formDataText)
|
||||
}`,
|
||||
);
|
||||
const boundary = formDataLines[0];
|
||||
assert_equals(
|
||||
formDataLines[formDataLines.length - 1],
|
||||
boundary + "--",
|
||||
`${fileBaseName}: multipart form data must end with ${boundary}--: ${
|
||||
JSON.stringify(formDataText)
|
||||
}`,
|
||||
);
|
||||
|
||||
const asName = fileBaseName.replace(/[\r\n"]/g, encodeURIComponent);
|
||||
const expectedText = [
|
||||
boundary,
|
||||
'Content-Disposition: form-data; name="filename"',
|
||||
"",
|
||||
fileBaseName,
|
||||
boundary,
|
||||
`Content-Disposition: form-data; name="${asName}"`,
|
||||
"",
|
||||
"filename",
|
||||
boundary,
|
||||
`Content-Disposition: form-data; name="file"; ` +
|
||||
`filename="${asName}"`,
|
||||
"Content-Type: text/plain",
|
||||
"",
|
||||
kTestChars,
|
||||
boundary + "--",
|
||||
].join("\r\n");
|
||||
|
||||
assert_true(
|
||||
formDataText.startsWith(expectedText),
|
||||
`Unexpected multipart-shaped form data received:\n${formDataText}\nExpected:\n${expectedText}`,
|
||||
);
|
||||
}, `Upload ${fileBaseName} (${fileNameSource}) in fetch with FormData`);
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Form newline normalization</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
function createForm(testCase, name, value) {
|
||||
const form = document.createElement("form");
|
||||
const input = document.createElement("input");
|
||||
input.type = "hidden";
|
||||
input.name = name;
|
||||
input.value = value;
|
||||
form.appendChild(input);
|
||||
document.body.appendChild(form);
|
||||
testCase.add_cleanup(() => {
|
||||
document.body.removeChild(form);
|
||||
});
|
||||
return form;
|
||||
}
|
||||
|
||||
test((testCase) => {
|
||||
const formData = new FormData(createForm(testCase, "a", "b\nc"));
|
||||
assert_equals(formData.get("a"), "b\r\nc");
|
||||
}, document.title + ": \\n in the value becomes \\r\\n");
|
||||
|
||||
test((testCase) => {
|
||||
const formData = new FormData(createForm(testCase, "a", "b\rc"));
|
||||
assert_equals(formData.get("a"), "b\r\nc");
|
||||
}, document.title + ": \\r in the value becomes \\r\\n");
|
||||
|
||||
test((testCase) => {
|
||||
const formData = new FormData(createForm(testCase, "a", "b\r\nc"));
|
||||
assert_equals(formData.get("a"), "b\r\nc");
|
||||
}, document.title + ": \\r\\n in the value stays unchanged");
|
||||
|
||||
test((testCase) => {
|
||||
const formData = new FormData(createForm(testCase, "a", "b\n\rc"));
|
||||
assert_equals(formData.get("a"), "b\r\n\r\nc");
|
||||
}, document.title + ": \\n\\r in the value becomes \\r\\n\\r\\n");
|
||||
|
||||
test((testCase) => {
|
||||
const formData = new FormData(createForm(testCase, "a\nb", "c"));
|
||||
assert_equals([...formData][0][0], "a\r\nb");
|
||||
}, document.title + ": \\n in the name becomes \\r\\n");
|
||||
|
||||
test((testCase) => {
|
||||
const formData = new FormData(createForm(testCase, "a\rb", "c"));
|
||||
assert_equals([...formData][0][0], "a\r\nb");
|
||||
}, document.title + ": \\r in the name becomes \\r\\n");
|
||||
|
||||
test((testCase) => {
|
||||
const formData = new FormData(createForm(testCase, "a\r\nb", "c"));
|
||||
assert_equals([...formData][0][0], "a\r\nb");
|
||||
}, document.title + ": \\r\\n in the name stays unchanged");
|
||||
|
||||
test((testCase) => {
|
||||
const formData = new FormData(createForm(testCase, "a\n\rb", "c"));
|
||||
assert_equals([...formData][0][0], "a\r\n\r\nb");
|
||||
}, document.title + ": \\n\\r in the name becomes \\r\\n\\r\\n");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user