OLD | NEW |
(Empty) | |
| 1 /*! |
| 2 * Parts of original code from ipv6.js <https://github.com/beaugunderson/javascr
ipt-ipv6> |
| 3 * Copyright 2011 Beau Gunderson |
| 4 * Available under MIT license <http://mths.be/mit> |
| 5 */ |
| 6 |
| 7 const RE_V4 = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|0x[0-9a-f][0-9a-f]?|0
[0-7]{3})\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|0x[0-9a-f][0-9a-f]?|0[0-7
]{3})$/i; |
| 8 const RE_V4_HEX = /^0x([0-9a-f]{8})$/i; |
| 9 const RE_V4_NUMERIC = /^[0-9]+$/; |
| 10 const RE_V4inV6 = /(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2
[0-4][0-9]|[01]?[0-9][0-9]?)$/; |
| 11 |
| 12 const RE_BAD_CHARACTERS = /([^0-9a-f:])/i; |
| 13 const RE_BAD_ADDRESS = /([0-9a-f]{5,}|:{3,}|[^:]:$|^:[^:]$)/i; |
| 14 |
| 15 function isIPv4(address) |
| 16 { |
| 17 if (RE_V4.test(address)) |
| 18 return true; |
| 19 if (RE_V4_HEX.test(address)) |
| 20 return true; |
| 21 if (RE_V4_NUMERIC.test(address)) |
| 22 return true; |
| 23 return false; |
| 24 } |
| 25 |
| 26 function isIPv6(address) |
| 27 { |
| 28 var a4addon = 0; |
| 29 var address4 = address.match(RE_V4inV6); |
| 30 if (address4) |
| 31 { |
| 32 var temp4 = address4[0].split('.'); |
| 33 for (var i = 0; i < 4; i++) |
| 34 { |
| 35 if (/^0[0-9]+/.test(temp4[i])) |
| 36 return false; |
| 37 } |
| 38 address = address.replace(RE_V4inV6, ''); |
| 39 if (/[0-9]$/.test(address)) |
| 40 return false; |
| 41 |
| 42 address = address + temp4.join(':'); |
| 43 a4addon = 2; |
| 44 } |
| 45 |
| 46 if (RE_BAD_CHARACTERS.test(address)) |
| 47 return false; |
| 48 |
| 49 if (RE_BAD_ADDRESS.test(address)) |
| 50 return false; |
| 51 |
| 52 function count(string, substring) |
| 53 { |
| 54 return (string.length - string.replace(new RegExp(substring,"g"), '').length
) / substring.length; |
| 55 } |
| 56 |
| 57 var halves = count(address, '::'); |
| 58 if (halves == 1 && count(address, ':') <= 6 + 2 + a4addon) |
| 59 return true; |
| 60 if (halves == 0 && count(address, ':') == 7 + a4addon) |
| 61 return true; |
| 62 return false; |
| 63 } |
| 64 |
| 65 /** |
| 66 * Returns base domain for specified host based on Public Suffix List. |
| 67 */ |
| 68 function getBaseDomain(/**String*/ hostname) /**String*/ |
| 69 { |
| 70 // remove trailing dot(s) |
| 71 hostname = hostname.replace(/\.+$/, ''); |
| 72 |
| 73 // return IP address untouched |
| 74 if (isIPv6(hostname) || isIPv4(hostname)) |
| 75 return hostname; |
| 76 |
| 77 // decode punycode if exists |
| 78 if (hostname.indexOf('xn--') >= 0) |
| 79 { |
| 80 hostname = punycode.toUnicode(hostname); |
| 81 } |
| 82 |
| 83 // search through PSL |
| 84 var prevDomains = []; |
| 85 var curDomain = hostname; |
| 86 var nextDot = curDomain.indexOf('.'); |
| 87 var tld = 0; |
| 88 |
| 89 while (true) |
| 90 { |
| 91 var suffix = publicSuffixes[curDomain]; |
| 92 if (typeof(suffix) != 'undefined') |
| 93 { |
| 94 tld = suffix; |
| 95 break; |
| 96 } |
| 97 |
| 98 if (nextDot < 0) |
| 99 { |
| 100 tld = 1; |
| 101 break; |
| 102 } |
| 103 |
| 104 prevDomains.push(curDomain.substring(0,nextDot)); |
| 105 curDomain = curDomain.substring(nextDot+1); |
| 106 nextDot = curDomain.indexOf('.'); |
| 107 } |
| 108 |
| 109 while (tld > 0 && prevDomains.length > 0) |
| 110 { |
| 111 curDomain = prevDomains.pop() + '.' + curDomain; |
| 112 tld--; |
| 113 } |
| 114 |
| 115 return curDomain; |
| 116 } |
| 117 |
| 118 /** |
| 119 * Checks whether a request is third party for the given document, uses |
| 120 * information from the public suffix list to determine the effective domain |
| 121 * name for the document. |
| 122 */ |
| 123 function isThirdParty(/**String*/ requestHost, /**String*/ documentHost) |
| 124 { |
| 125 // Remove trailing dots |
| 126 requestHost = requestHost.replace(/\.+$/, ""); |
| 127 documentHost = documentHost.replace(/\.+$/, ""); |
| 128 |
| 129 // Extract domain name - leave IP addresses unchanged, otherwise leave only ba
se domain |
| 130 var documentDomain = getBaseDomain(documentHost); |
| 131 if (requestHost.length > documentDomain.length) |
| 132 return (requestHost.substr(requestHost.length - documentDomain.length - 1) !
= "." + documentDomain); |
| 133 else |
| 134 return (requestHost != documentDomain); |
| 135 } |
| 136 |
| 137 /** |
| 138 * Extracts host name from a URL. |
| 139 */ |
| 140 function extractHostFromURL(/**String*/ url) |
| 141 { |
| 142 if (url && extractHostFromURL._lastURL == url) |
| 143 return extractHostFromURL._lastDomain; |
| 144 |
| 145 var host = ""; |
| 146 try |
| 147 { |
| 148 host = new URI(url).host; |
| 149 } |
| 150 catch (e) |
| 151 { |
| 152 // Keep the empty string for invalid URIs. |
| 153 } |
| 154 |
| 155 extractHostFromURL._lastURL = url; |
| 156 extractHostFromURL._lastDomain = host; |
| 157 return host; |
| 158 } |
| 159 |
| 160 /** |
| 161 * Parses URLs and provides an interface similar to nsIURI in Gecko, see |
| 162 * https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsIURI. |
| 163 * TODO: Make sure the parsing actually works the same as nsStandardURL. |
| 164 * @constructor |
| 165 */ |
| 166 function URI(/**String*/ spec) |
| 167 { |
| 168 this.spec = spec; |
| 169 this._schemeEnd = spec.indexOf(":"); |
| 170 if (this._schemeEnd < 0) |
| 171 throw new Error("Invalid URI scheme"); |
| 172 |
| 173 if (spec.substr(this._schemeEnd + 1, 2) != "//") |
| 174 throw new Error("Unexpected URI structure"); |
| 175 |
| 176 this._hostPortStart = this._schemeEnd + 3; |
| 177 this._hostPortEnd = spec.indexOf("/", this._hostPortStart); |
| 178 if (this._hostPortEnd < 0) |
| 179 throw new Error("Invalid URI host"); |
| 180 |
| 181 var authEnd = spec.indexOf("@", this._hostPortStart); |
| 182 if (authEnd >= 0 && authEnd < this._hostPortEnd) |
| 183 this._hostPortStart = authEnd + 1; |
| 184 |
| 185 this._portStart = -1; |
| 186 this._hostEnd = spec.indexOf("]", this._hostPortStart + 1); |
| 187 if (spec[this._hostPortStart] == "[" && this._hostEnd >= 0 && this._hostEnd <
this._hostPortEnd) |
| 188 { |
| 189 // The host is an IPv6 literal |
| 190 this._hostStart = this._hostPortStart + 1; |
| 191 if (spec[this._hostEnd + 1] == ":") |
| 192 this._portStart = this._hostEnd + 2; |
| 193 } |
| 194 else |
| 195 { |
| 196 this._hostStart = this._hostPortStart; |
| 197 this._hostEnd = spec.indexOf(":", this._hostStart); |
| 198 if (this._hostEnd >= 0 && this._hostEnd < this._hostPortEnd) |
| 199 this._portStart = this._hostEnd + 1; |
| 200 else |
| 201 this._hostEnd = this._hostPortEnd; |
| 202 } |
| 203 } |
| 204 URI.prototype = |
| 205 { |
| 206 spec: null, |
| 207 get scheme() |
| 208 { |
| 209 return this.spec.substring(0, this._schemeEnd).toLowerCase(); |
| 210 }, |
| 211 get host() |
| 212 { |
| 213 return this.spec.substring(this._hostStart, this._hostEnd); |
| 214 }, |
| 215 get asciiHost() |
| 216 { |
| 217 var host = this.host; |
| 218 if (/^[\x00-\x7F]+$/.test(host)) |
| 219 return host; |
| 220 else |
| 221 return punycode.toASCII(host); |
| 222 }, |
| 223 get hostPort() |
| 224 { |
| 225 return this.spec.substring(this._hostPortStart, this._hostPortEnd); |
| 226 }, |
| 227 get port() |
| 228 { |
| 229 if (this._portStart < 0) |
| 230 return -1; |
| 231 else |
| 232 return parseInt(this.spec.substring(this._portStart, this._hostPortEnd), 1
0); |
| 233 }, |
| 234 get path() |
| 235 { |
| 236 return this.spec.substring(this._hostPortEnd); |
| 237 }, |
| 238 get prePath() |
| 239 { |
| 240 return this.spec.substring(0, this._hostPortEnd); |
| 241 } |
| 242 }; |
OLD | NEW |