Socket
Socket
Sign inDemoInstall

whatwg-url

Package Overview
Dependencies
Maintainers
1
Versions
63
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

whatwg-url - npm Package Compare versions

Comparing version 0.1.0 to 0.2.0

coverage/coverage.json

611

lib/url.js

@@ -5,2 +5,5 @@ "use strict";

const Guid = require("Guid");
const tr46 = require("tr46");
/*jshint unused: false */

@@ -71,3 +74,3 @@

function isASCIIHex(c) {
return (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66);
return isASCIIDigit(c) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66);
}

@@ -138,9 +141,126 @@

//TODO: Finish up
function parseIPv6(input) {
if (!net.isIPv6(input)) {
const ip = [0, 0, 0, 0, 0, 0, 0, 0];
let piecePtr = 0;
let compressPtr = null;
let pointer = 0;
input = punycode.ucs2.decode(input);
if (at(input, pointer) === ":") {
if (at(input, pointer + 1) !== ":") {
throw new TypeError("Invalid Host");
}
pointer += 2;
++piecePtr;
compressPtr = piecePtr;
}
let ipv4 = false;
Main:
while (pointer < input.length) {
if (piecePtr === 8) {
throw new TypeError("Invalid Host");
}
if (at(input, pointer) === ":") {
if (compressPtr !== null) {
throw new TypeError("Invalid Host");
}
++pointer;
++piecePtr;
compressPtr = piecePtr;
continue;
}
let value = 0;
let length = 0;
while (length < 4 && isASCIIHex(input[pointer])) {
value = value * 0x10 + parseInt(at(input, pointer), 16);
++pointer;
++length;
}
switch (at(input, pointer)) {
case ".":
if (length === 0) {
throw new TypeError("Invalid Host");
}
pointer -= length;
ipv4 = true;
break Main;
case ":":
++pointer;
if (input[pointer] === undefined) {
throw new TypeError("Invalid Host");
}
break;
case undefined:
break;
default:
throw new TypeError("Invalid Host");
}
ip[piecePtr] = value;
++piecePtr;
}
if (ipv4 && piecePtr > 6) {
throw new TypeError("Invalid Host");
} else if (input[pointer] !== undefined) {
let dotsSeen = 0;
while (input[pointer] !== undefined) {
let value = null;
if (!isASCIIDigit(input[pointer])) {
throw new TypeError("Invalid Host");
}
while (isASCIIDigit(input[pointer])) {
const number = parseInt(at(input, pointer), 10);
if (value === null) {
value = number;
} else if (value === 0) {
throw new TypeError("Invalid Host");
} else {
value = value * 10 + number;
}
++pointer;
if (value > 255) {
throw new TypeError("Invalid Host");
}
}
if (dotsSeen < 3 && at(input, pointer) !== ".") {
throw new TypeError("Invalid Host");
}
ip[piecePtr] = ip[piecePtr] * 0x100 + value;
if (dotsSeen === 1 || dotsSeen === 3) {
++piecePtr;
}
++pointer;
if (dotsSeen === 3 && input[pointer] !== undefined) {
throw new TypeError("Invalid Host");
}
++dotsSeen;
}
}
return "[" + input + "]";
if (compressPtr !== null) {
let swaps = piecePtr - compressPtr;
piecePtr = 7;
while (piecePtr !== 0 && swaps > 0) {
const temp = ip[compressPtr + swaps - 1]; // piece
ip[compressPtr + swaps - 1] = ip[piecePtr];
ip[piecePtr] = temp;
--piecePtr;
--swaps;
}
} else if (piecePtr !== 8) {
throw new TypeError("Invalid Host");
}
return ip;
}

@@ -158,3 +278,3 @@

return parseIPv6(input.substr(1, input.length - 2));
return serializeHost(parseIPv6(input.substr(1, input.length - 2)));
}

@@ -169,3 +289,7 @@

let asciiDomain = punycode.toASCII(domain.toLowerCase());
const asciiDomain = tr46.toASCII(domain, false, tr46.PROCESSING_OPTIONS.TRANSITIONAL, false);
if (asciiDomain === null) {
throw new TypeError("Invalid Host");
}
if (asciiDomain.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|%|\/|:|\?|@|\[|\\|\]/) !== -1) {

@@ -175,6 +299,34 @@ throw new TypeError("Invalid Host");

return isUnicode ? punycode.toUnicode(asciiDomain) : asciiDomain;
return isUnicode ? tr46.toUnicode(asciiDomain, false).domain : asciiDomain;
}
//TODO: Finish up
function findLongestZeroSequence(arr) {
let maxIdx = null;
let maxLen = 1; // only find elements > 1
let currStart = null;
let currLen = 0;
for (var i = 0; i < arr.length; ++i) {
if (arr[i] !== 0) {
if (currLen > maxLen) {
maxIdx = currStart;
maxLen = currLen;
}
currStart = null;
currLen = 0;
} else {
if (currStart === null) {
currStart = i;
}
++currLen;
}
}
return {
idx: maxIdx,
len: maxLen
};
}
function serializeHost(host) {

@@ -185,2 +337,29 @@ if (host === null) {

// IPv6 serializer
if (host instanceof Array) {
let output = "";
const seqResult = findLongestZeroSequence(host);
const compressPtr = seqResult.idx;
for (var i = 0; i < host.length; ++i) {
if (compressPtr === i) {
if (i === 0) {
output += "::";
} else {
output += ":";
}
i += seqResult.len - 1;
continue;
}
output += host[i].toString(16);
if (i !== host.length - 1) {
output += ":";
}
}
return "[" + output + "]";
}
return host;

@@ -655,2 +834,17 @@ }

function serializeOrigin(tuple) {
if (tuple.scheme === undefined || tuple.host === undefined || tuple.port === undefined) {
return "null";
}
let result = tuple.scheme + "://";
result += tr46.toUnicode(tuple.host, false).domain;
if (relativeSchemas[tuple.scheme] && tuple.port !== relativeSchemas[tuple.scheme]) {
result += ":" + tuple.port;
}
return result;
}
function mixin(src, target) {

@@ -672,219 +866,258 @@ const props = Object.getOwnPropertyNames(src);

const getBaseSymbol = Symbol("getTheBase");
const baseSymbol = Symbol("base");
const isURLSymbol = Symbol("isURL");
const guidSymbol = Symbol("guid");
const URLUtils = {};
function setTheInput(obj, input, url) {
if (url) {
obj[urlSymbol] = url;
obj[inputSymbol] = input;
} else {
obj[urlSymbol] = null;
if (input === null) {
obj[inputSymbol] = "";
} else {
obj[inputSymbol] = input;
Object.defineProperties(URLUtils, {
href: {
get: function () {
if (this[urlSymbol] === null) {
return this[inputSymbol];
}
try {
obj[urlSymbol] = new URLStateMachine(input, obj[baseSymbol]);
} catch (e) {}
}
}
return serializeURL(this[urlSymbol].url);
},
set: function (val) {
let input = String(this[inputSymbol]);
let url = null;
const query = obj[urlSymbol] !== null && obj[urlSymbol].url.query !== null ? obj[urlSymbol].url.query : "";
// TODO: Update URLSearchParams
}
if (this[isURLSymbol]) {
// SPEC: says to use "get the base" algorithm,
// but the base might've already been provided by the constructor.
// Clarify!
const parsedURL = new URLStateMachine(this[inputSymbol], this[getBaseSymbol]());
input = "";
url = parsedURL;
}
const URLUtils = {
get href() {
if (this[urlSymbol] === null) {
return this[inputSymbol];
}
// set the input algorithm
if (url !== null) {
this[urlSymbol] = url;
this[inputSymbol] = input;
} else {
if (input === null) {
this[inputSymbol] = "";
} else {
this[inputSymbol] = input;
return serializeURL(this[urlSymbol].url);
},
set href(val) {
let input = String(val);
// TODO: query encoding
this[urlSymbol] = new URLStateMachine(this[inputSymbol], this[getBaseSymbol]());
}
}
if (this[isURLSymbol]) {
// SPEC: says to use "get the base" algorithm,
// but the base might've already been provided by the constructor.
// Clarify!
const parsedURL = new URLStateMachine(input, this[baseSymbol]);
input = "";
setTheInput(this, "", parsedURL);
} else {
setTheInput(this, input);
// TODO: Run pre-update steps
}
},
const query = this[urlSymbol] !== null && this[urlSymbol].url.query !== null ? this[urlSymbol].url.query : "";
// TODO: Update URLSearchParams
get origin() {
if (this[urlSymbol] === null) {
return "";
}
const url = this[urlSymbol].url;
switch (url.scheme) {
case "blob":
try {
return module.exports.getURL()(url.scheme_data).origin;
} catch (e) {
if (this[guidSymbol] === undefined) {
this[guidSymbol] = Guid.raw();
}
return this[guidSymbol];
}
break;
case "ftp":
case "gopher":
case "http":
case "https":
case "ws":
case "wss":
return serializeOrigin({
scheme: url.scheme,
host: url.host,
port: url.port === "" ? relativeSchemas[url.scheme] : url.port
});
case "file":
// spec says "exercise to the reader", chrome says "file://"
return "file://";
default:
if (this[guidSymbol] === undefined) {
this[guidSymbol] = Guid.raw();
}
return this[guidSymbol];
}
},
// TODO: origin
protocol: {
get: function () {
if (this[urlSymbol] === null) {
return ":";
}
if (this === undefined) {console.log("this");}
if (this[urlSymbol] === undefined) {console.log("url");}
return this[urlSymbol].url.scheme + ":";
},
set: function (val) {
if (this[urlSymbol] === null) {
return;
}
this[urlSymbol] = new URLStateMachine(val + ":", null, null, this[urlSymbol].url, STATES.SCHEME_START);
get protocol() {
if (this[urlSymbol] === null) {
return ":";
}
return this[urlSymbol].url.scheme + ":";
},
set protocol(val) {
if (this[urlSymbol] === null) {
return;
}
this[urlSymbol] = new URLStateMachine(val + ":", null, null, this[urlSymbol].url, STATES.SCHEME_START);
},
username: {
get: function () {
return this[urlSymbol] === null ? "" : this[urlSymbol].url.username;
},
set: function (val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative) {
return;
}
get username() {
return this[urlSymbol] === null ? "" : this[urlSymbol].url.username;
},
set username(val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative) {
return;
}
this[urlSymbol].url.username = "";
const decoded = punycode.ucs2.decode(val);
for (let i = 0; i < decoded.length; ++i) {
this[urlSymbol].url.username += usernameEncode(decoded[i]);
}
this[urlSymbol].url.username = "";
const decoded = punycode.ucs2.decode(val);
for (let i = 0; i < decoded.length; ++i) {
this[urlSymbol].url.username += usernameEncode(decoded[i]);
}
},
password: {
get: function () {
return this[urlSymbol] === null || this[urlSymbol].url.password === null ? "" : this[urlSymbol].url.password;
},
set: function (val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative) {
return;
}
get password() {
return this[urlSymbol] === null || this[urlSymbol].url.password === null ? "" : this[urlSymbol].url.password;
},
set password(val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative) {
return;
}
this[urlSymbol].url.password = "";
const decoded = punycode.ucs2.decode(val);
for (let i = 0; i < decoded.length; ++i) {
this[urlSymbol].url.password += passwordEncode(decoded[i]);
}
this[urlSymbol].url.password = "";
const decoded = punycode.ucs2.decode(val);
for (let i = 0; i < decoded.length; ++i) {
this[urlSymbol].url.password += passwordEncode(decoded[i]);
}
},
host: {
get: function () {
if (this[urlSymbol] === null) {
return "";
}
return serializeHost(this[urlSymbol].url.host) +
(this[urlSymbol].url.port === "" ? "" : ":" + this[urlSymbol].url.port);
},
set: function (val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative) {
return;
}
this[urlSymbol] = new URLStateMachine(val, null, null, this[urlSymbol].url, STATES.HOST);
get host() {
if (this[urlSymbol] === null) {
return "";
}
return serializeHost(this[urlSymbol].url.host) +
(this[urlSymbol].url.port === "" ? "" : ":" + this[urlSymbol].url.port);
},
set host(val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative) {
return;
}
this[urlSymbol] = new URLStateMachine(val, null, null, this[urlSymbol].url, STATES.HOST);
},
hostname: {
get: function () {
if (this[urlSymbol] === null) {
return "";
}
return serializeHost(this[urlSymbol].url.host);
},
set: function (val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative) {
return;
}
this[urlSymbol] = new URLStateMachine(val, null, null, this[urlSymbol].url, STATES.HOST_NAME);
get hostname() {
if (this[urlSymbol] === null) {
return "";
}
return serializeHost(this[urlSymbol].url.host);
},
set hostname(val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative) {
return;
}
this[urlSymbol] = new URLStateMachine(val, null, null, this[urlSymbol].url, STATES.HOST_NAME);
},
port: {
get: function () {
if (this[urlSymbol] === null) {
return "";
}
return this[urlSymbol].url.port;
},
set: function (val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative || this[urlSymbol].url.scheme === "file") {
return;
}
this[urlSymbol] = new URLStateMachine(val, null, null, this[urlSymbol].url, STATES.PORT);
get port() {
if (this[urlSymbol] === null) {
return "";
}
return this[urlSymbol].url.port;
},
set port(val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative || this[urlSymbol].url.scheme === "file") {
return;
}
this[urlSymbol] = new URLStateMachine(val, null, null, this[urlSymbol].url, STATES.PORT);
},
pathname: {
get: function () {
if (this[urlSymbol] === null) {
return "";
}
if (!this[urlSymbol].url.isRelative) {
return this[urlSymbol].url.scheme_data;
}
get pathname() {
if (this[urlSymbol] === null) {
return "";
}
if (!this[urlSymbol].url.isRelative) {
return this[urlSymbol].url.scheme_data;
}
return "/" + this[urlSymbol].url.path.join("/");
},
set: function (val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative) {
return;
}
this[urlSymbol].url.path = [];
this[urlSymbol] = new URLStateMachine(val, null, null, this[urlSymbol].url, STATES.RELATIVE_PATH_START);
return "/" + this[urlSymbol].url.path.join("/");
},
set pathname(val) {
if (this[urlSymbol] === null || !this[urlSymbol].url.isRelative) {
return;
}
this[urlSymbol].url.path = [];
this[urlSymbol] = new URLStateMachine(val, null, null, this[urlSymbol].url, STATES.RELATIVE_PATH_START);
},
search: {
get: function () {
if (this[urlSymbol] === null || !this[urlSymbol].url.query) {
return "";
}
get search() {
if (this[urlSymbol] === null || !this[urlSymbol].url.query) {
return "";
}
return "?" + this[urlSymbol].url.query;
},
set: function (val) {
if (this[urlSymbol] === null) {
return;
}
if (val === "") {
this[urlSymbol].url.query = null;
// TODO: empty query object
return;
}
return "?" + this[urlSymbol].url.query;
},
set search(val) {
if (this[urlSymbol] === null) {
return;
}
if (val === "") {
this[urlSymbol].url.query = null;
// TODO: empty query object
return;
}
const input = val[0] === "?" ? val.substr(1) : val;
this[urlSymbol].url.query = "";
const input = val[0] === "?" ? val.substr(1) : val;
this[urlSymbol].url.query = "";
// TODO: Add query encoding
this[urlSymbol] = new URLStateMachine(input, null, null, this[urlSymbol].url, STATES.QUERY);
// TODO: Add query encoding
this[urlSymbol] = new URLStateMachine(input, null, null, this[urlSymbol].url, STATES.QUERY);
// TODO: Update query object
// TODO: Update query object
},
get hash() {
if (this[urlSymbol] === null || !this[urlSymbol].url.fragment) {
return "";
}
return "#" + this[urlSymbol].url.fragment;
},
set hash(val) {
if (this[urlSymbol] === null || this[urlSymbol].url.scheme === "javascript") {
return;
}
if (val === "") {
this[urlSymbol].url.fragment = null;
return;
}
hash: {
get: function () {
if (this[urlSymbol] === null || !this[urlSymbol].url.fragment) {
return "";
}
const input = val[0] === "#" ? val.substr(1) : val;
this[urlSymbol].url.fragment = "";
this[urlSymbol] = new URLStateMachine(input, null, null, this[urlSymbol].url, STATES.FRAGMENT);
}
};
return "#" + this[urlSymbol].url.fragment;
},
set: function (val) {
if (this[urlSymbol] === null || this[urlSymbol].url.scheme === "javascript") {
return;
}
if (val === "") {
this[urlSymbol].url.fragment = null;
return;
}
function urlToASCII(domain) {
try {
const asciiDomain = parseHost(domain);
return asciiDomain;
} catch (e) {
return "";
}
}
const input = val[0] === "#" ? val.substr(1) : val;
this[urlSymbol].url.fragment = "";
this[urlSymbol] = new URLStateMachine(input, null, null, this[urlSymbol].url, STATES.FRAGMENT);
}
function urlToUnicode(domain) {
try {
const unicodeDomain = parseHost(domain, true);
return unicodeDomain;
} catch (e) {
return "";
}
});
}

@@ -904,11 +1137,11 @@ function init(url, base) {

parsedBase = new URLStateMachine(base);
this[baseSymbol] = parsedBase.url;
}
this[urlSymbol] = new URLStateMachine(url, parsedBase.url);
this[inputSymbol] = "";
const parsedURL = new URLStateMachine(url, parsedBase ? parsedBase.url : undefined);
setTheInput(this, "", parsedURL);
}
module.exports.getURL = function (getBase) {
module.exports.getURL = function () {
function URL() {
this[getBaseSymbol] = getBase;
this[isURLSymbol] = true;

@@ -919,4 +1152,14 @@ init.apply(this, arguments);

mixin(URLUtils, URL.prototype);
URL.toASCII = urlToASCII;
URL.toUnicode = urlToUnicode;
return URL;
};
module.exports.addToObject = function (obj, base) {
obj[isURLSymbol] = false;
obj[baseSymbol] = new URLStateMachine(base).url;
setTheInput(obj, null, null);
mixin(URLUtils, obj);
};
{
"name": "whatwg-url",
"version": "0.1.0",
"version": "0.2.0",
"description": "An implementation of the WHATWG URL algorithm",

@@ -10,3 +10,8 @@ "main": "lib/url.js",

},
"dependencies": {
"guid": "0.0.12",
"tr46": "~0.0.1"
},
"devDependencies": {
"istanbul": "~0.3.14",
"jscs": "^1.13.0",

@@ -18,2 +23,3 @@ "jshint": "^2.7.0",

"scripts": {
"coverage": "istanbul cover node_modules/mocha/bin/_mocha",
"lint": "jscs lib/ test/ scripts/ && jshint lib/ test/ scripts/",

@@ -20,0 +26,0 @@ "pretest": "iojs scripts/get-latest-platform-tests.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc