"use strict"; const { utf8Encode, utf8DecodeWithoutBOM } = require("./encoding"); const { percentDecodeBytes, utf8PercentEncodeString, isURLEncodedPercentEncode } = require("./percent-encoding"); function p(char) { return char.codePointAt(0); } // https://url.spec.whatwg.org/#concept-urlencoded-parser function parseUrlencoded(input) { const sequences = strictlySplitByteSequence(input, p("&")); const output = []; for (const bytes of sequences) { if (bytes.length === 0) { continue; } let name, value; const indexOfEqual = bytes.indexOf(p("=")); 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) { // TODO: accept and use encoding argument let output = ""; for (const [i, tuple] of tuples.entries()) { const name = utf8PercentEncodeString(tuple[0], isURLEncodedPercentEncode, true); const value = utf8PercentEncodeString(tuple[1], 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 };