whatwg-url
Advanced tools
Comparing version 0.6.2 to 0.6.4
505
lib/url.js
@@ -6,12 +6,10 @@ "use strict"; | ||
/*jshint unused: false */ | ||
const specialSchemas = { | ||
"ftp": "21", | ||
"ftp": 21, | ||
"file": null, | ||
"gopher": "70", | ||
"http": "80", | ||
"https": "443", | ||
"ws": "80", | ||
"wss": "443" | ||
"gopher": 70, | ||
"http": 80, | ||
"https": 443, | ||
"ws": 80, | ||
"wss": 443 | ||
}; | ||
@@ -33,2 +31,4 @@ | ||
const failure = Symbol("failure"); | ||
const STATES = { | ||
@@ -53,3 +53,5 @@ SCHEME_START: 1, | ||
PORT: 18, | ||
PATH_OR_AUTHORITY: 19 | ||
FILE: 19, | ||
FILE_SLASH: 20, | ||
PATH_OR_AUTHORITY: 21 | ||
}; | ||
@@ -78,2 +80,11 @@ | ||
function isSingleDot(buffer) { | ||
return buffer === "." || buffer.toLowerCase() === "%2e"; | ||
} | ||
function isDoubleDot(buffer) { | ||
buffer = buffer.toLowerCase(); | ||
return buffer === ".." || buffer === "%2e." || buffer === ".%2e" || buffer === "%2e%2e"; | ||
} | ||
function percentEncode(c) { | ||
@@ -104,45 +115,40 @@ let hex = c.toString(16).toUpperCase(); | ||
function simpleEncode(c) { | ||
const c_str = String.fromCodePoint(c); | ||
if (c < 0x20 || c > 0x7E) { | ||
return utf8PercentEncode(c_str); | ||
} else { | ||
return c_str; | ||
function utf8PercentDecode(str) { | ||
const input = new Buffer(str); | ||
const output = []; | ||
for (let i = 0; i < input.length; ++i) { | ||
if (input[i] !== 37) { | ||
output.push(input[i]); | ||
} else if (input[i] === 37 && isASCIIHex(input[i + 1]) && isASCIIHex(input[i + 2])) { | ||
output.push(parseInt(input.slice(i + 1, i + 3).toString(), 16)); | ||
i += 2; | ||
} else { | ||
output.push(input[i]); | ||
} | ||
} | ||
return new Buffer(output).toString(); | ||
} | ||
function defaultEncode(c) { | ||
const c_str = String.fromCodePoint(c); | ||
if (c <= 0x20 || c >= 0x7E || c_str === "\"" || c_str === "#" || | ||
c_str === "<" || c_str === ">" || c_str === "?" || c_str === "`" || | ||
c_str === "{" || c_str === "}") { | ||
return utf8PercentEncode(c_str); | ||
} else { | ||
return c_str; | ||
} | ||
function isSimpleEncode(c) { | ||
return c < 0x20 || c > 0x7E; | ||
} | ||
function passwordEncode(c) { | ||
const c_str = String.fromCodePoint(c); | ||
if (c <= 0x20 || c >= 0x7E || c_str === "\"" || c_str === "#" || | ||
c_str === "<" || c_str === ">" || c_str === "?" || c_str === "`" || | ||
c_str === "{" || c_str === "}" || | ||
c_str === "/" || c_str === "@" || c_str === "\\") { | ||
return utf8PercentEncode(c_str); | ||
} else { | ||
return c_str; | ||
} | ||
const defaultEncodeSet = [34, 35, 60, 62, 63, 96, 123, 125]; | ||
function isDefaultEncode(c) { | ||
return isSimpleEncode(c) || defaultEncodeSet.indexOf(c) !== -1; | ||
} | ||
function usernameEncode(c) { | ||
const userInfoEncodeSet = [47, 58, 59, 61, 64, 91, 92, 93, 94, 124]; | ||
function isUserInfoEncode(c) { | ||
return isDefaultEncode(c) || userInfoEncodeSet.indexOf(c) !== -1; | ||
} | ||
function encodeChar(c, checkCb) { | ||
const c_str = String.fromCodePoint(c); | ||
if (c <= 0x20 || c >= 0x7E || c_str === "\"" || c_str === "#" || | ||
c_str === "<" || c_str === ">" || c_str === "?" || c_str === "`" || | ||
c_str === "{" || c_str === "}" || | ||
c_str === "/" || c_str === "@" || c_str === "\\" || c_str === ":") { | ||
if (checkCb(c)) { | ||
return utf8PercentEncode(c_str); | ||
} else { | ||
return c_str; | ||
} | ||
return c_str; | ||
} | ||
@@ -167,3 +173,3 @@ | ||
if (regex.test(input)) { | ||
return null; | ||
return failure; | ||
} | ||
@@ -187,3 +193,3 @@ | ||
const n = parseIPv4Number(part); | ||
if (n === null) { | ||
if (n === failure) { | ||
return input; | ||
@@ -197,7 +203,7 @@ } | ||
if (numbers[i] > 255) { | ||
throw new TypeError("Invalid Host"); | ||
return failure; | ||
} | ||
} | ||
if (numbers[numbers.length - 1] >= Math.pow(256, 5 - numbers.length)) { | ||
throw new TypeError("Invalid Host"); | ||
return failure; | ||
} | ||
@@ -239,5 +245,5 @@ | ||
if (at(input, pointer) === ":") { | ||
if (at(input, pointer + 1) !== ":") { | ||
throw new TypeError("Invalid Host"); | ||
if (input[pointer] === 58) { | ||
if (input[pointer + 1] !== 58) { | ||
return failure; | ||
} | ||
@@ -254,8 +260,8 @@ | ||
if (piecePtr === 8) { | ||
throw new TypeError("Invalid Host"); | ||
return failure; | ||
} | ||
if (at(input, pointer) === ":") { | ||
if (input[pointer] === 58) { | ||
if (compressPtr !== null) { | ||
throw new TypeError("Invalid Host"); | ||
return failure; | ||
} | ||
@@ -280,3 +286,3 @@ ++pointer; | ||
if (length === 0) { | ||
throw new TypeError("Invalid Host"); | ||
return failure; | ||
} | ||
@@ -289,3 +295,3 @@ pointer -= length; | ||
if (input[pointer] === undefined) { | ||
throw new TypeError("Invalid Host"); | ||
return failure; | ||
} | ||
@@ -296,3 +302,3 @@ break; | ||
default: | ||
throw new TypeError("Invalid Host"); | ||
return failure; | ||
} | ||
@@ -305,3 +311,3 @@ | ||
if (ipv4 && piecePtr > 6) { | ||
throw new TypeError("Invalid Host"); | ||
return failure; | ||
} else if (input[pointer] !== undefined) { | ||
@@ -313,3 +319,3 @@ let dotsSeen = 0; | ||
if (!isASCIIDigit(input[pointer])) { | ||
throw new TypeError("Invalid Host"); | ||
return failure; | ||
} | ||
@@ -322,3 +328,3 @@ | ||
} else if (value === 0) { | ||
throw new TypeError("Invalid Host"); | ||
return failure; | ||
} else { | ||
@@ -329,8 +335,8 @@ value = value * 10 + number; | ||
if (value > 255) { | ||
throw new TypeError("Invalid Host"); | ||
return failure; | ||
} | ||
} | ||
if (dotsSeen < 3 && at(input, pointer) !== ".") { | ||
throw new TypeError("Invalid Host"); | ||
if (dotsSeen < 3 && input[pointer] !== 46) { | ||
return failure; | ||
} | ||
@@ -347,3 +353,3 @@ ip[piecePtr] = ip[piecePtr] * 0x100 + value; | ||
if (dotsSeen === 3 && input[pointer] !== undefined) { | ||
throw new TypeError("Invalid Host"); | ||
return failure; | ||
} | ||
@@ -365,3 +371,3 @@ ++dotsSeen; | ||
} else if (piecePtr !== 8) { | ||
throw new TypeError("Invalid Host"); | ||
return failure; | ||
} | ||
@@ -401,3 +407,3 @@ | ||
if (input[input.length - 1] !== "]") { | ||
throw new TypeError("Invalid Host"); | ||
return failure; | ||
} | ||
@@ -408,20 +414,14 @@ | ||
let domain; | ||
try { | ||
domain = decodeURIComponent(input); | ||
} catch (e) { | ||
throw new TypeError("Error while decoding host"); | ||
} | ||
const domain = utf8PercentDecode(input); | ||
const asciiDomain = tr46.toASCII(domain, false, tr46.PROCESSING_OPTIONS.TRANSITIONAL, false); | ||
if (asciiDomain === null) { | ||
throw new TypeError("Invalid Host"); | ||
return failure; | ||
} | ||
if (asciiDomain.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|%|\/|:|\?|@|\[|\\|\]/) !== -1) { | ||
throw new TypeError("Invalid Host"); | ||
return failure; | ||
} | ||
let ipv4Host = parseIPv4(asciiDomain); | ||
if (typeof ipv4Host === "number") { | ||
if (typeof ipv4Host === "number" || ipv4Host === failure) { | ||
return ipv4Host; | ||
@@ -486,2 +486,3 @@ } | ||
this.url = url; | ||
this.failure = false; | ||
@@ -494,3 +495,3 @@ if (!this.url) { | ||
host: null, | ||
port: "", | ||
port: null, | ||
path: [], | ||
@@ -520,4 +521,8 @@ query: null, | ||
// exec state machine | ||
if (this["parse" + this.state](c, c_str) === false) { | ||
const ret = this["parse" + this.state](c, c_str); | ||
if (ret === false) { | ||
break; // terminate algorithm | ||
} else if (ret === failure) { | ||
this.failure = true; | ||
break; | ||
} | ||
@@ -543,5 +548,5 @@ } | ||
function parseScheme(c, c_str) { | ||
if (isASCIIAlpha(c) || c_str === "+" || c_str === "-" || c_str === ".") { | ||
if (isASCIIAlpha(c) || c === 43 || c === 45 || c === 46) { | ||
this.buffer += c_str.toLowerCase(); | ||
} else if (c_str === ":") { | ||
} else if (c === 58) { | ||
if (this.state_override) { | ||
@@ -561,3 +566,3 @@ // TODO: XOR | ||
if (this.url.scheme === "file") { | ||
this.state = STATES.RELATIVE; | ||
this.state = STATES.FILE; | ||
} else if (specialSchemas[this.url.scheme] !== undefined && this.base !== null && | ||
@@ -568,3 +573,3 @@ this.base.scheme === this.url.scheme) { | ||
this.state = STATES.SPECIAL_AUTHORITY_SLASHES; | ||
} else if (at(this.input, this.pointer + 1) === "/") { | ||
} else if (this.input[this.pointer + 1] === 47) { | ||
this.state = STATES.PATH_OR_AUTHORITY; | ||
@@ -590,5 +595,5 @@ ++this.pointer; | ||
//jshint unused:false | ||
if (this.base === null || (this.base.nonRelative && c_str !== "#")) { | ||
throw new TypeError("Invalid URL"); | ||
} else if (this.base.nonRelative && c_str === "#") { | ||
if (this.base === null || (this.base.nonRelative && c !== 35)) { | ||
return failure; | ||
} else if (this.base.nonRelative && c === 35) { | ||
this.url.scheme = this.base.scheme; | ||
@@ -600,2 +605,5 @@ this.url.path = this.base.path.slice(); | ||
this.state = STATES.FRAGMENT; | ||
} else if (this.base.scheme === "file") { | ||
this.state = STATES.FILE; | ||
--this.pointer; | ||
} else { | ||
@@ -609,3 +617,3 @@ this.state = STATES.RELATIVE; | ||
function parseSpecialRelativeOrAuthority(c, c_str) { | ||
if (c_str === "/" && at(this.input, this.pointer + 1) === "/") { | ||
if (c === 47 && this.input[this.pointer + 1] === 47) { | ||
this.state = STATES.SPECIAL_AUTHORITY_IGNORE_SLASHES; | ||
@@ -622,3 +630,3 @@ ++this.pointer; | ||
function parsePathOrAuthority(c, c_str) { | ||
if (c_str === "/") { | ||
if (c === 47) { | ||
this.state = STATES.AUTHORITY; | ||
@@ -633,5 +641,3 @@ } else { | ||
function parseRelative(c, c_str) { | ||
if (this.url.scheme !== "file") { | ||
this.url.scheme = this.base.scheme; | ||
} | ||
this.url.scheme = this.base.scheme; | ||
if (isNaN(c)) { | ||
@@ -644,5 +650,5 @@ this.url.username = this.base.username; | ||
this.url.query = this.base.query; | ||
} else if (c_str === "/") { | ||
} else if (c === 47) { | ||
this.state = STATES.RELATIVE_SLASH; | ||
} else if (c_str === "?") { | ||
} else if (c === 63) { | ||
this.url.username = this.base.username; | ||
@@ -655,3 +661,3 @@ this.url.password = this.base.password; | ||
this.state = STATES.QUERY; | ||
} else if (c_str === "#") { | ||
} else if (c === 35) { | ||
this.url.username = this.base.username; | ||
@@ -665,17 +671,11 @@ this.url.password = this.base.password; | ||
this.state = STATES.FRAGMENT; | ||
} else if (specialSchemas[this.url.scheme] !== undefined && c_str === "\\") { | ||
} else if (specialSchemas[this.url.scheme] !== undefined && c === 92) { | ||
this.parse_error = true; | ||
this.state = STATES.RELATIVE_SLASH; | ||
} else { | ||
let nextChar = at(this.input, this.pointer + 1); | ||
let nextNextChar = at(this.input, this.pointer + 2); | ||
if (this.url.scheme !== "file" || !isASCIIAlpha(c) || !(nextChar === ":" || nextChar === "|") || | ||
this.input.length - this.pointer === 1 || !(nextNextChar === "/" || nextNextChar === "\\" || | ||
nextNextChar === "?" || nextNextChar === "#")) { | ||
this.url.username = this.base.username; | ||
this.url.password = this.base.password; | ||
this.url.host = this.base.host; | ||
this.url.port = this.base.port; | ||
this.url.path = this.base.path.slice(0, this.base.path.length - 1); | ||
} | ||
this.url.username = this.base.username; | ||
this.url.password = this.base.password; | ||
this.url.host = this.base.host; | ||
this.url.port = this.base.port; | ||
this.url.path = this.base.path.slice(0, this.base.path.length - 1); | ||
@@ -689,18 +689,12 @@ this.state = STATES.PATH; | ||
function parseRelativeSlash(c, c_str) { | ||
if (c_str === "/" || (specialSchemas[this.url.scheme] !== undefined && c_str === "\\")) { | ||
if (c_str === "\\") { | ||
if (c === 47 || (specialSchemas[this.url.scheme] !== undefined && c === 92)) { | ||
if (c === 92) { | ||
this.parse_error = true; | ||
} | ||
if (this.url.scheme === "file") { | ||
this.state = STATES.FILE_HOST; | ||
} else { | ||
this.state = STATES.SPECIAL_AUTHORITY_IGNORE_SLASHES; | ||
} | ||
this.state = STATES.SPECIAL_AUTHORITY_IGNORE_SLASHES; | ||
} else { | ||
if (this.url.scheme !== "file") { | ||
this.url.username = this.base.username; | ||
this.url.password = this.base.password; | ||
this.url.host = this.base.host; | ||
this.url.port = this.base.port; | ||
} | ||
this.url.username = this.base.username; | ||
this.url.password = this.base.password; | ||
this.url.host = this.base.host; | ||
this.url.port = this.base.port; | ||
this.state = STATES.PATH; | ||
@@ -713,3 +707,3 @@ --this.pointer; | ||
function parseSpecialAuthoritySlashes(c, c_str) { | ||
if (c_str === "/" && at(this.input, this.pointer + 1) === "/") { | ||
if (c === 47 && this.input[this.pointer + 1] === 47) { | ||
this.state = STATES.SPECIAL_AUTHORITY_IGNORE_SLASHES; | ||
@@ -726,3 +720,3 @@ ++this.pointer; | ||
function parseSpecialAuthorityIgnoreSlashes(c, c_str) { | ||
if (c_str !== "/" && c_str !== "\\") { | ||
if (c !== 47 && c !== 92) { | ||
this.state = STATES.AUTHORITY; | ||
@@ -737,3 +731,3 @@ --this.pointer; | ||
function parseAuthority(c, c_str) { | ||
if (c_str === "@") { | ||
if (c === 64) { | ||
this.parse_error = true; | ||
@@ -750,3 +744,2 @@ if (this.at_flag) { | ||
const c = this.buffer.codePointAt(pointer); | ||
const c_str = String.fromCodePoint(c); | ||
/* jshint +W004 */ | ||
@@ -758,15 +751,16 @@ | ||
if (c_str === ":" && this.url.password === null) { | ||
if (c === 58 && this.url.password === null) { | ||
this.url.password = ""; | ||
continue; | ||
} | ||
const encodedCodePoints = encodeChar(c, isUserInfoEncode); | ||
if (this.url.password !== null) { | ||
this.url.password += passwordEncode(c); | ||
this.url.password += encodedCodePoints; | ||
} else { | ||
this.url.username += usernameEncode(c); | ||
this.url.username += encodedCodePoints; | ||
} | ||
} | ||
this.buffer = ""; | ||
} else if (isNaN(c) || c_str === "/" || c_str === "?" || c_str === "#" || | ||
(specialSchemas[this.url.scheme] !== undefined && c_str === "\\")) { | ||
} else if (isNaN(c) || c === 47 || c === 63 || c === 35 || | ||
(specialSchemas[this.url.scheme] !== undefined && c === 92)) { | ||
this.pointer -= countSymbols(this.buffer) + 1; | ||
@@ -783,8 +777,12 @@ this.buffer = ""; | ||
function parseHostName(c, c_str) { | ||
if (c_str === ":" && !this.arr_flag) { | ||
if (c === 58 && !this.arr_flag) { | ||
if (specialSchemas[this.url.scheme] !== undefined && this.buffer === "") { | ||
throw new TypeError("Invalid URL"); | ||
return failure; | ||
} | ||
let host = parseHost(this.buffer); | ||
if (host === failure) { | ||
return failure; | ||
} | ||
this.url.host = host; | ||
@@ -796,10 +794,14 @@ this.buffer = ""; | ||
} | ||
} else if (isNaN(c) || c_str === "/" || c_str === "?" || c_str === "#" || | ||
(specialSchemas[this.url.scheme] !== undefined && c_str === "\\")) { | ||
} else if (isNaN(c) || c === 47 || c === 63 || c === 35 || | ||
(specialSchemas[this.url.scheme] !== undefined && c === 92)) { | ||
--this.pointer; | ||
if (specialSchemas[this.url.scheme] !== undefined && this.buffer === "") { | ||
throw new TypeError("Invalid URL"); | ||
return failure; | ||
} | ||
let host = parseHost(this.buffer); | ||
if (host === failure) { | ||
return failure; | ||
} | ||
this.url.host = host; | ||
@@ -814,5 +816,5 @@ this.buffer = ""; | ||
} else { | ||
if (c_str === "[") { | ||
if (c === 91) { | ||
this.arr_flag = true; | ||
} else if (c_str === "]") { | ||
} else if (c === 93) { | ||
this.arr_flag = false; | ||
@@ -824,6 +826,90 @@ } | ||
URLStateMachine.prototype["parse" + STATES.PORT] = | ||
function parsePort(c, c_str) { | ||
if (isASCIIDigit(c)) { | ||
this.buffer += c_str; | ||
} else if (isNaN(c) || c === 47 || c === 63 || c === 35 || | ||
(specialSchemas[this.url.scheme] !== undefined && c === 92) || | ||
this.state_override) { | ||
const port = parseInt(this.buffer, 10); | ||
if (port > Math.pow(2, 16) - 1) { | ||
this.parse_error = true; | ||
return failure; | ||
} | ||
this.url.port = isNaN(port) || port === specialSchemas[this.url.scheme] ? null : port; | ||
if (this.state_override) { | ||
return false; | ||
} | ||
this.buffer = ""; | ||
this.state = STATES.PATH_START; | ||
--this.pointer; | ||
} else if (c === 0x9 || c === 0xA || c === 0xD) { | ||
this.parse_error = true; | ||
} else { | ||
this.parse_error = true; | ||
return failure; | ||
} | ||
}; | ||
URLStateMachine.prototype["parse" + STATES.FILE] = | ||
function parseFile(c, c_str) { | ||
this.url.scheme = "file"; | ||
if (isNaN(c)) { | ||
if (this.base !== null && this.base.scheme === "file") { | ||
this.url.host = this.base.host; | ||
this.url.path = this.base.path.slice(); | ||
this.url.query = this.base.query; | ||
} | ||
} else if (c === 47 || c === 92) { | ||
if (c === 92) { | ||
this.parse_error = true; | ||
} | ||
this.state = STATES.FILE_SLASH; | ||
} else if (c === 63) { | ||
if (this.base !== null && this.base.scheme === "file") { | ||
this.url.host = this.base.host; | ||
this.url.path = this.base.path.slice(); | ||
this.url.query = ""; | ||
} | ||
this.state = STATES.QUERY; | ||
} else if (c === 35) { | ||
if (this.base !== null && this.base.scheme === "file") { | ||
this.url.host = this.base.host; | ||
this.url.path = this.base.path.slice(); | ||
this.url.query = this.base.query; | ||
this.url.fragment = ""; | ||
} | ||
this.state = STATES.FRAGMENT; | ||
} else { | ||
if (this.base !== null && this.base.scheme === "file") { | ||
this.url.host = this.base.host; | ||
this.url.path = this.base.path.slice(); | ||
this.url.path.pop(); | ||
} | ||
this.state = STATES.PATH; | ||
--this.pointer; | ||
} | ||
}; | ||
URLStateMachine.prototype["parse" + STATES.FILE_SLASH] = | ||
function parseFileSlash(c, c_str) { | ||
if (c === 47 || c === 92) { | ||
if (c === 92) { | ||
this.parse_error = true; | ||
} | ||
this.state = STATES.FILE_HOST; | ||
} else { | ||
if (this.base !== null && this.base.scheme === "file") { | ||
if (this.base.path.length && isASCIIAlpha(this.base.path[0][0].charCodeAt(0)) && this.base.path[0][1] === ":") { | ||
this.url.path.push(this.base.path[0]); | ||
} | ||
} | ||
this.state = STATES.PATH; | ||
--this.pointer; | ||
} | ||
}; | ||
URLStateMachine.prototype["parse" + STATES.FILE_HOST] = | ||
function parseFileHost(c, c_str) { | ||
if (isNaN(c) || c_str === "/" || c_str === "\\" || c_str === "?" || c_str === "#") { | ||
--this.pointer; | ||
if (isNaN(c) || c === 47 || c === 92 || c === 63 || c === 35) { | ||
// don't need to count symbols here since we check ASCII values | ||
@@ -837,3 +923,9 @@ if (this.buffer.length === 2 && | ||
let host = parseHost(this.buffer); | ||
this.url.host = host; | ||
if (host === failure) { | ||
return failure; | ||
} | ||
if (host !== "localhost") { | ||
this.url.host = host; | ||
} | ||
this.buffer = ""; | ||
@@ -849,36 +941,9 @@ this.state = STATES.PATH_START; | ||
URLStateMachine.prototype["parse" + STATES.PORT] = | ||
function parsePort(c, c_str) { | ||
if (isASCIIDigit(c)) { | ||
this.buffer += c_str; | ||
} else if (isNaN(c) || c_str === "/" || c_str === "?" || c_str === "#" || | ||
(specialSchemas[this.url.scheme] !== undefined && c_str === "\\")) { | ||
while (this.buffer[0] === "0" && this.buffer.length > 1) { | ||
this.buffer = this.buffer.substr(1); | ||
} | ||
if (this.buffer === specialSchemas[this.url.scheme]) { | ||
this.buffer = ""; | ||
} | ||
this.url.port = this.buffer; | ||
if (this.state_override) { | ||
return false; | ||
} | ||
this.buffer = ""; | ||
this.state = STATES.PATH_START; | ||
--this.pointer; | ||
} else if (c === 0x9 || c === 0xA || c === 0xD) { | ||
this.parse_error = true; | ||
} else { | ||
this.parse_error = true; | ||
throw new TypeError("Invalid URL"); | ||
} | ||
}; | ||
URLStateMachine.prototype["parse" + STATES.PATH_START] = | ||
function parsePathStart(c, c_str) { | ||
if (specialSchemas[this.url.scheme] !== undefined && c_str === "\\") { | ||
if (specialSchemas[this.url.scheme] !== undefined && c === 92) { | ||
this.parse_error = true; | ||
} | ||
this.state = STATES.PATH; | ||
if (c_str !== "/" && !(specialSchemas[this.url.scheme] !== undefined && c_str === "\\")) { | ||
if (c !== 47 && !(specialSchemas[this.url.scheme] !== undefined && c === 92)) { | ||
--this.pointer; | ||
@@ -890,20 +955,20 @@ } | ||
function parsePath(c, c_str) { | ||
if (isNaN(c) || c_str === "/" || (specialSchemas[this.url.scheme] !== undefined && c_str === "\\") || | ||
(!this.state_override && (c_str === "?" || c_str === "#"))) { | ||
if (specialSchemas[this.url.scheme] !== undefined && c_str === "\\") { | ||
if (isNaN(c) || c === 47 || (specialSchemas[this.url.scheme] !== undefined && c === 92) || | ||
(!this.state_override && (c === 63 || c === 35))) { | ||
if (specialSchemas[this.url.scheme] !== undefined && c === 92) { | ||
this.parse_error = true; | ||
} | ||
this.buffer = bufferReplacement[this.buffer.toLowerCase()] || this.buffer; | ||
if (this.buffer === "..") { | ||
if (isDoubleDot(this.buffer)) { | ||
this.url.path.pop(); | ||
if (c_str !== "/" && !(specialSchemas[this.url.scheme] !== undefined && c_str === "\\")) { | ||
if (c !== 47 && !(specialSchemas[this.url.scheme] !== undefined && c === 92)) { | ||
this.url.path.push(""); | ||
} | ||
} else if (this.buffer === "." && c_str !== "/" && | ||
!(specialSchemas[this.url.scheme] !== undefined && c_str === "\\")) { | ||
} else if (isSingleDot(this.buffer) && c !== 47 && | ||
!(specialSchemas[this.url.scheme] !== undefined && c === 92)) { | ||
this.url.path.push(""); | ||
} else if (this.buffer !== ".") { | ||
} else if (!isSingleDot(this.buffer)) { | ||
if (this.url.scheme === "file" && this.url.path.length === 0 && | ||
this.buffer.length === 2 && isASCIIAlpha(this.buffer.codePointAt(0)) && this.buffer[1] === "|") { | ||
this.url.host = null; | ||
this.buffer = this.buffer[0] + ":"; | ||
@@ -914,7 +979,7 @@ } | ||
this.buffer = ""; | ||
if (c_str === "?") { | ||
if (c === 63) { | ||
this.url.query = ""; | ||
this.state = STATES.QUERY; | ||
} | ||
if (c_str === "#") { | ||
if (c === 35) { | ||
this.url.fragment = ""; | ||
@@ -927,9 +992,9 @@ this.state = STATES.FRAGMENT; | ||
//TODO:If c is not a URL code point and not "%", parse error. | ||
if (c_str === "%" && | ||
(!isASCIIHex(at(this.input, this.pointer + 1)) || | ||
!isASCIIHex(at(this.input, this.pointer + 2)))) { | ||
if (c === 37 && | ||
(!isASCIIHex(this.input[this.pointer + 1]) || | ||
!isASCIIHex(this.input[this.pointer + 2]))) { | ||
this.parse_error = true; | ||
} | ||
this.buffer += defaultEncode(c); | ||
this.buffer += encodeChar(c, isDefaultEncode); | ||
} | ||
@@ -940,6 +1005,6 @@ }; | ||
function parseNonRelativePath(c, c_str) { | ||
if (c_str === "?") { | ||
if (c === 63) { | ||
this.url.query = ""; | ||
this.state = STATES.QUERY; | ||
} else if (c_str === "#") { | ||
} else if (c === 35) { | ||
this.url.fragment = ""; | ||
@@ -949,9 +1014,9 @@ this.state = STATES.FRAGMENT; | ||
// TODO: Add: not a URL code point | ||
if (!isNaN(c) && c_str !== "%") { | ||
if (!isNaN(c) && c !== 37) { | ||
this.parse_error = true; | ||
} | ||
if (c_str === "%" && | ||
(!isASCIIHex(at(this.input, this.pointer + 1)) || | ||
!isASCIIHex(at(this.input, this.pointer + 2)))) { | ||
if (c === 37 && | ||
(!isASCIIHex(this.input[this.pointer + 1]) || | ||
!isASCIIHex(this.input[this.pointer + 2]))) { | ||
this.parse_error = true; | ||
@@ -961,3 +1026,3 @@ } | ||
if (!isNaN(c) && c !== 0x9 && c !== 0xA && c !== 0xD) { | ||
this.url.path[0] = this.url.path[0] + simpleEncode(c); | ||
this.url.path[0] = this.url.path[0] + encodeChar(c, isSimpleEncode); | ||
} | ||
@@ -969,3 +1034,3 @@ } | ||
function parseQuery(c, c_str) { | ||
if (isNaN(c) || (!this.state_override && c_str === "#")) { | ||
if (isNaN(c) || (!this.state_override && c === 35)) { | ||
if (specialSchemas[this.url.scheme] === undefined || this.url.scheme === "ws" || this.url.scheme === "wss") { | ||
@@ -986,3 +1051,3 @@ this.encoding_override = "utf-8"; | ||
this.buffer = ""; | ||
if (c_str === "#") { | ||
if (c === 35) { | ||
this.url.fragment = ""; | ||
@@ -995,5 +1060,5 @@ this.state = STATES.FRAGMENT; | ||
//TODO: If c is not a URL code point and not "%", parse error. | ||
if (c_str === "%" && | ||
(!isASCIIHex(at(this.input, this.pointer + 1)) || | ||
!isASCIIHex(at(this.input, this.pointer + 2)))) { | ||
if (c === 37 && | ||
(!isASCIIHex(this.input[this.pointer + 1]) || | ||
!isASCIIHex(this.input[this.pointer + 2]))) { | ||
this.parse_error = true; | ||
@@ -1013,5 +1078,5 @@ } | ||
//TODO: If c is not a URL code point and not "%", parse error. | ||
if (c_str === "%" && | ||
(!isASCIIHex(at(this.input, this.pointer + 1)) || | ||
!isASCIIHex(at(this.input, this.pointer + 2)))) { | ||
if (c === 37 && | ||
(!isASCIIHex(this.input[this.pointer + 1]) || | ||
!isASCIIHex(this.input[this.pointer + 2]))) { | ||
this.parse_error = true; | ||
@@ -1035,5 +1100,7 @@ } | ||
output += serializeHost(url.host); | ||
if (url.port !== "") { | ||
if (url.port !== null) { | ||
output += ":" + url.port; | ||
} | ||
} else if (url.host === null && url.scheme === "file") { | ||
output += "//"; | ||
} | ||
@@ -1075,10 +1142,8 @@ | ||
const props = Object.getOwnPropertyNames(src); | ||
const descriptors = {}; | ||
for (let i = 0; i < props.length; ++i) { | ||
descriptors[props[i]] = Object.getOwnPropertyDescriptor(src, props[i]); | ||
const descriptor = Object.getOwnPropertyDescriptor(src, props[i]); | ||
Object.defineProperty(target, props[i], descriptor); | ||
} | ||
Object.defineProperties(target, descriptors); | ||
const symbols = Object.getOwnPropertySymbols(src); | ||
@@ -1100,20 +1165,15 @@ for (var i = 0; i < symbols.length; ++i) { | ||
function setTheInput(obj, input, url) { | ||
if (url) { | ||
obj[urlSymbol] = url; | ||
obj[inputSymbol] = input; | ||
} else { | ||
obj[urlSymbol] = null; | ||
if (input === null) { | ||
obj[inputSymbol] = ""; | ||
obj[inputSymbol] = input; | ||
obj[urlSymbol] = url ? url : null; | ||
if (input === null) { | ||
let parsed; | ||
if (typeof obj[baseSymbol] === "function") { | ||
parsed = new URLStateMachine(input, new URLStateMachine(obj[baseSymbol]()).url); | ||
} else { | ||
obj[inputSymbol] = input; | ||
try { | ||
if (typeof obj[baseSymbol] === "function") { | ||
obj[urlSymbol] = new URLStateMachine(input, new URLStateMachine(obj[baseSymbol]()).url); | ||
} else { | ||
obj[urlSymbol] = new URLStateMachine(input, obj[baseSymbol]); | ||
} | ||
} catch (e) {} | ||
parsed = new URLStateMachine(input, obj[baseSymbol]); | ||
} | ||
if (!parsed.failure) { | ||
obj[urlSymbol] = parsed; | ||
} | ||
} | ||
@@ -1174,3 +1234,3 @@ | ||
host: serializeHost(url.host), | ||
port: url.port === "" ? specialSchemas[url.scheme] : url.port | ||
port: url.port === null ? specialSchemas[url.scheme] : url.port | ||
}); | ||
@@ -1211,3 +1271,3 @@ case "file": | ||
for (let i = 0; i < decoded.length; ++i) { | ||
this[urlSymbol].url.username += usernameEncode(decoded[i]); | ||
this[urlSymbol].url.username += encodeChar(decoded[i], isUserInfoEncode); | ||
} | ||
@@ -1228,3 +1288,3 @@ preUpdateSteps(this); | ||
for (let i = 0; i < decoded.length; ++i) { | ||
this[urlSymbol].url.password += passwordEncode(decoded[i]); | ||
this[urlSymbol].url.password += encodeChar(decoded[i], isUserInfoEncode); | ||
} | ||
@@ -1267,3 +1327,3 @@ preUpdateSteps(this); | ||
} | ||
return this[urlSymbol].url.port; | ||
return this[urlSymbol].url.port ? this[urlSymbol].url.port : ""; | ||
}, | ||
@@ -1385,2 +1445,5 @@ set port(val) { | ||
parsedBase = new URLStateMachine(base); | ||
if (parsedBase.failure) { | ||
throw new TypeError("Invalid base URL"); | ||
} | ||
this[baseSymbol] = parsedBase.url; | ||
@@ -1390,2 +1453,5 @@ } | ||
const parsedURL = new URLStateMachine(url, parsedBase ? parsedBase.url : undefined); | ||
if (parsedURL.failure) { | ||
throw new TypeError("Invalid URL"); | ||
} | ||
setTheInput(this, "", parsedURL); | ||
@@ -1405,2 +1471,3 @@ } | ||
this[isURLSymbol] = true; | ||
this[updateStepsSymbol] = function () {}; | ||
init.apply(this, arguments); | ||
@@ -1407,0 +1474,0 @@ } |
{ | ||
"name": "whatwg-url", | ||
"version": "0.6.2", | ||
"version": "0.6.4", | ||
"description": "An implementation of the WHATWG URL algorithm", | ||
@@ -17,10 +17,13 @@ "main": "lib/url.js", | ||
"mocha": "^2.2.4", | ||
"request": "^2.55.0" | ||
"request": "^2.55.0", | ||
"recast": "~0.10.29" | ||
}, | ||
"scripts": { | ||
"build": "iojs bin/transform.js", | ||
"coverage": "istanbul cover node_modules/mocha/bin/_mocha", | ||
"lint": "jscs lib/ test/ scripts/ && jshint lib/ test/ scripts/", | ||
"pretest": "iojs scripts/get-latest-platform-tests.js", | ||
"lint": "jscs src/ test/ scripts/ && jshint src/ test/ scripts/", | ||
"prepublish": "npm run build", | ||
"pretest": "iojs scripts/get-latest-platform-tests.js && npm run build", | ||
"test": "npm run lint && mocha" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
40282
7
1282
6
1