|
|
- "use strict";
- const { utf8Encode, utf8DecodeWithoutBOM } = require("./encoding");
- const { percentDecodeBytes, utf8PercentEncodeString, isURLEncodedPercentEncode } = require("./percent-encoding");
-
- // https://url.spec.whatwg.org/#concept-urlencoded-parser
- function parseUrlencoded(input) {
- const sequences = strictlySplitByteSequence(input, 38);
- const output = [];
- for (const bytes of sequences) {
- if (bytes.length === 0) {
- continue;
- }
-
- let name;
- let value;
- const indexOfEqual = bytes.indexOf(61);
-
- if (indexOfEqual >= 0) {
- name = bytes.slice(0, indexOfEqual);
- value = bytes.slice(indexOfEqual + 1);
- } else {
- name = bytes;
- value = new Uint8Array(0);
- }
-
- name = replaceByteInByteSequence(name, 0x2B, 0x20);
- value = replaceByteInByteSequence(value, 0x2B, 0x20);
-
- const nameString = utf8DecodeWithoutBOM(percentDecodeBytes(name));
- const valueString = utf8DecodeWithoutBOM(percentDecodeBytes(value));
-
- output.push([nameString, valueString]);
- }
- return output;
- }
-
- // https://url.spec.whatwg.org/#concept-urlencoded-string-parser
- function parseUrlencodedString(input) {
- return parseUrlencoded(utf8Encode(input));
- }
-
- // https://url.spec.whatwg.org/#concept-urlencoded-serializer
- function serializeUrlencoded(tuples, encodingOverride = undefined) {
- let encoding = "utf-8";
- if (encodingOverride !== undefined) {
- // TODO "get the output encoding", i.e. handle encoding labels vs. names.
- encoding = encodingOverride;
- }
-
- let output = "";
- for (const [i, tuple] of tuples.entries()) {
- // TODO: handle encoding override
-
- const name = utf8PercentEncodeString(tuple[0], isURLEncodedPercentEncode, true);
-
- let value = tuple[1];
- if (tuple.length > 2 && tuple[2] !== undefined) {
- if (tuple[2] === "hidden" && name === "_charset_") {
- value = encoding;
- } else if (tuple[2] === "file") {
- // value is a File object
- value = value.name;
- }
- }
-
- value = utf8PercentEncodeString(value, isURLEncodedPercentEncode, true);
-
- if (i !== 0) {
- output += "&";
- }
- output += `${name}=${value}`;
- }
- return output;
- }
-
- function strictlySplitByteSequence(buf, cp) {
- const list = [];
- let last = 0;
- let i = buf.indexOf(cp);
- while (i >= 0) {
- list.push(buf.slice(last, i));
- last = i + 1;
- i = buf.indexOf(cp, last);
- }
- if (last !== buf.length) {
- list.push(buf.slice(last));
- }
- return list;
- }
-
- function replaceByteInByteSequence(buf, from, to) {
- let i = buf.indexOf(from);
- while (i >= 0) {
- buf[i] = to;
- i = buf.indexOf(from, i + 1);
- }
- return buf;
- }
-
- module.exports = {
- parseUrlencodedString,
- serializeUrlencoded
- };
|