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); |
+ } |
+}; |