1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-25 15:29:32 -05:00

fix(fetch): implement newline normalization and escapes in the multipart/form-data serializer (#10832)

This commit is contained in:
Andreu Botella 2021-06-03 20:48:09 +02:00 committed by GitHub
parent 55e962b688
commit 03184aeabb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 13 deletions

View file

@ -323,11 +323,13 @@
filename,
type,
) {
const escapedField = this.#headerEscape(field);
const escapedFilename = this.#headerEscape(filename, true);
/** @type {[string, string][]} */
const headers = [
[
"Content-Disposition",
`form-data; name="${field}"; filename="${filename}"`,
`form-data; name="${escapedField}"; filename="${escapedFilename}"`,
],
["Content-Type", type || "application/octet-stream"],
];
@ -340,7 +342,10 @@
*/
#writeFieldHeaders(field) {
/** @type {[string, string][]} */
const headers = [["Content-Disposition", `form-data; name="${field}"`]];
const headers = [[
"Content-Disposition",
`form-data; name="${this.#headerEscape(field)}"`,
]];
return this.#writeHeaders(headers);
}
@ -351,7 +356,7 @@
*/
#writeField(field, value) {
this.#writeFieldHeaders(field);
this.chunks.push(encoder.encode(value));
this.chunks.push(encoder.encode(this.#normalizeNewlines(value)));
}
/**
@ -363,6 +368,32 @@
this.#writeFileHeaders(field, value.name, value.type);
this.chunks.push(value[_byteSequence]);
}
/**
* @param {string} string
* @returns {string}
*/
#normalizeNewlines(string) {
return string.replace(/\r(?!\n)|(?<!\r)\n/g, "\r\n");
}
/**
* Performs the percent-escaping and the normalization required for field
* names and filenames in Content-Disposition headers.
* @param {string} name
* @param {boolean} isFilename Whether we are encoding a filename. This
* skips the newline normalization that takes place for field names.
* @returns {string}
*/
#headerEscape(name, isFilename = false) {
if (!isFilename) {
name = this.#normalizeNewlines(name);
}
return name
.replaceAll("\n", "%0A")
.replaceAll("\r", "%0D")
.replaceAll('"', "%22");
}
}
/**

View file

@ -990,16 +990,8 @@
},
"file": {
"File-constructor.any.html": true,
"send-file-formdata-controls.any.html": [
"Upload file-for-upload-in-form-LF-[\n].txt (ASCII) in fetch with FormData",
"Upload file-for-upload-in-form-LF-CR-[\n\r].txt (ASCII) in fetch with FormData",
"Upload file-for-upload-in-form-CR-[\r].txt (ASCII) in fetch with FormData",
"Upload file-for-upload-in-form-CR-LF-[\r\n].txt (ASCII) in fetch with FormData"
],
"send-file-formdata-punctuation.any.html": [
"Upload file-for-upload-in-form-QUOTATION-MARK-[\"].txt (ASCII) in fetch with FormData",
"Upload \"file-for-upload-in-form-double-quoted.txt\" (ASCII) in fetch with FormData"
],
"send-file-formdata-controls.any.html": true,
"send-file-formdata-punctuation.any.html": true,
"send-file-formdata-utf-8.any.html": true,
"send-file-formdata.any.html": true
},