| Index: lib/basedomain.js | 
| =================================================================== | 
| --- a/lib/basedomain.js | 
| +++ b/lib/basedomain.js | 
| @@ -134,32 +134,109 @@ function isThirdParty(/**String*/ reques | 
| return (requestHost != documentDomain); | 
| } | 
| /** | 
| * Extracts host name from a URL. | 
| */ | 
| function extractHostFromURL(/**String*/ url) | 
| { | 
| - if (!url) | 
| - return ""; | 
| - | 
| - if (extractHostFromURL._lastURL == url) | 
| + if (url && extractHostFromURL._lastURL == url) | 
| return extractHostFromURL._lastDomain; | 
| - var x = url.substr(url.indexOf("://") + 3); | 
| - x = x.substr(0, x.indexOf("/")); | 
| - x = x.substr(x.indexOf("@") + 1); | 
| - if (x.indexOf("[") == 0 && x.indexOf("]") > 0) | 
| + var host = ""; | 
| + try | 
| { | 
| - x = x.substring(1,x.indexOf("]")); | 
| + host = new URI(url).host; | 
| + } | 
| + catch (e) | 
| + { | 
| + // Keep the empty string for invalid URIs. | 
| + } | 
| + | 
| + extractHostFromURL._lastURL = url; | 
| + extractHostFromURL._lastDomain = host; | 
| + return host; | 
| +} | 
| + | 
| +/** | 
| + * Parses URLs and provides an interface similar to nsIURI in Gecko, see | 
| + * https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsIURI. | 
| + * TODO: Make sure the parsing actually works the same as nsStandardURL. | 
| + * @constructor | 
| + */ | 
| +function URI(/**String*/ spec) | 
| +{ | 
| + this.spec = spec; | 
| + this._schemeEnd = spec.indexOf(":"); | 
| + if (this._schemeEnd < 0) | 
| + throw new Error("Invalid URI scheme"); | 
| + | 
| + if (spec.substr(this._schemeEnd + 1, 2) != "//") | 
| + throw new Error("Unexpected URI structure"); | 
| + | 
| + this._hostPortStart = this._schemeEnd + 3; | 
| + this._hostPortEnd = spec.indexOf("/", this._hostPortStart); | 
| + if (this._hostPortEnd < 0) | 
| + throw new Error("Invalid URI host"); | 
| + | 
| + var authEnd = spec.indexOf("@", this._hostPortStart); | 
| + if (authEnd >= 0 && authEnd < this._hostPortEnd) | 
| + this._hostPortStart = authEnd + 1; | 
| + | 
| + this._portStart = -1; | 
| + this._hostEnd = spec.indexOf("]", this._hostPortStart + 1); | 
| + if (spec[this._hostPortStart] == "[" && this._hostEnd >= 0 && this._hostEnd < this._hostPortEnd) | 
| + { | 
| + // The host is an IPv6 literal | 
| + this._hostStart = this._hostPortStart + 1; | 
| + if (spec[this._hostEnd + 1] == ":") | 
| + this._portStart = this._hostEnd + 2; | 
| } | 
| else | 
| { | 
| - colPos = x.indexOf(":"); | 
| - if (colPos >= 0) | 
| - x = x.substr(0, colPos); | 
| + this._hostStart = this._hostPortStart; | 
| + this._hostEnd = spec.indexOf(":", this._hostStart); | 
| + if (this._hostEnd >= 0 && this._hostEnd < this._hostPortEnd) | 
| + this._portStart = this._hostEnd + 1; | 
| + else | 
| + this._hostEnd = this._hostPortEnd; | 
| } | 
| - | 
| - extractHostFromURL._lastURL = url; | 
| - extractHostFromURL._lastDomain = x; | 
| - return x; | 
| } | 
| +URI.prototype = | 
| +{ | 
| + spec: null, | 
| + get scheme() | 
| + { | 
| + return this.spec.substring(0, this._schemeEnd).toLowerCase(); | 
| + }, | 
| + get host() | 
| + { | 
| + return this.spec.substring(this._hostStart, this._hostEnd); | 
| + }, | 
| + get asciiHost() | 
| + { | 
| + var host = this.host; | 
| + if (/^[\x00-\x7F]+$/.test(host)) | 
| + return host; | 
| + else | 
| + return punycode.toASCII(host); | 
| + }, | 
| + get hostPort() | 
| + { | 
| + return this.spec.substring(this._hostPortStart, this._hostPortEnd); | 
| + }, | 
| + get port() | 
| + { | 
| + if (this._portStart < 0) | 
| + return -1; | 
| + else | 
| + return parseInt(this.spec.substring(this._portStart, this._hostPortEnd), 10); | 
| + }, | 
| + get path() | 
| + { | 
| + return this.spec.substring(this._hostPortEnd); | 
| + }, | 
| + get prePath() | 
| + { | 
| + return this.spec.substring(0, this._hostPortEnd); | 
| + } | 
| +}; |