aboutsummaryrefslogtreecommitdiffstats
path: root/lib/publicsuffixlist.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/publicsuffixlist.js')
-rw-r--r--lib/publicsuffixlist.js556
1 files changed, 278 insertions, 278 deletions
diff --git a/lib/publicsuffixlist.js b/lib/publicsuffixlist.js
index c0625ab..35b67cd 100644
--- a/lib/publicsuffixlist.js
+++ b/lib/publicsuffixlist.js
@@ -22,9 +22,9 @@
/*! Home: https://github.com/gorhill/publicsuffixlist.js */
/*
- This code is mostly dumb: I consider this to be lower-level code, thus
- in order to ensure efficiency, the caller is responsible for sanitizing
- the inputs.
+ This code is mostly dumb: I consider this to be lower-level code, thus
+ in order to ensure efficiency, the caller is responsible for sanitizing
+ the inputs.
*/
/******************************************************************************/
@@ -33,336 +33,336 @@
;(function(root) {
- 'use strict';
+'use strict';
- /******************************************************************************/
-
- var exceptions = {};
- var rules = {};
- var selfieMagic = 'iscjsfsaolnm';
+/******************************************************************************/
- // This value dictate how the search will be performed:
- // < this.cutoffLength = indexOf()
- // >= this.cutoffLength = binary search
- var cutoffLength = 256;
- var mustPunycode = /[^\w.*-]/;
+var exceptions = {};
+var rules = {};
+var selfieMagic = 'iscjsfsaolnm';
- var onChangedListeners = [];
+// This value dictate how the search will be performed:
+// < this.cutoffLength = indexOf()
+// >= this.cutoffLength = binary search
+var cutoffLength = 256;
+var mustPunycode = /[^\w.*-]/;
- /******************************************************************************/
+var onChangedListeners = [];
- // In the context of this code, a domain is defined as:
- // "{label}.{public suffix}".
- // A single standalone label is a public suffix as per
- // http://publicsuffix.org/list/:
- // "If no rules match, the prevailing rule is '*' "
- // This means 'localhost' is not deemed a domain by this
- // code, since according to the definition above, it would be
- // evaluated as a public suffix. The caller is therefore responsible to
- // decide how to further interpret such public suffix.
- //
- // `hostname` must be a valid ascii-based hostname.
+/******************************************************************************/
- function getDomain(hostname) {
- // A hostname starting with a dot is not a valid hostname.
- if ( !hostname || hostname.charAt(0) === '.' ) {
- return '';
- }
- hostname = hostname.toLowerCase();
- var suffix = getPublicSuffix(hostname);
- if ( suffix === hostname ) {
- return '';
- }
- var pos = hostname.lastIndexOf('.', hostname.lastIndexOf('.', hostname.length - suffix.length) - 1);
- if ( pos <= 0 ) {
- return hostname;
- }
- return hostname.slice(pos + 1);
+// In the context of this code, a domain is defined as:
+// "{label}.{public suffix}".
+// A single standalone label is a public suffix as per
+// http://publicsuffix.org/list/:
+// "If no rules match, the prevailing rule is '*' "
+// This means 'localhost' is not deemed a domain by this
+// code, since according to the definition above, it would be
+// evaluated as a public suffix. The caller is therefore responsible to
+// decide how to further interpret such public suffix.
+//
+// `hostname` must be a valid ascii-based hostname.
+
+function getDomain(hostname) {
+ // A hostname starting with a dot is not a valid hostname.
+ if ( !hostname || hostname.charAt(0) === '.' ) {
+ return '';
}
-
- /******************************************************************************/
-
- // Return longest public suffix.
- //
- // `hostname` must be a valid ascii-based string which respect hostname naming.
-
- function getPublicSuffix(hostname) {
- if ( !hostname ) {
- return '';
- }
- // Since we slice down the hostname with each pass, the first match
- // is the longest, so no need to find all the matching rules.
- var pos;
- while ( true ) {
- pos = hostname.indexOf('.');
- if ( pos < 0 ) {
- return hostname;
- }
- if ( search(exceptions, hostname) ) {
- return hostname.slice(pos + 1);
- }
- if ( search(rules, hostname) ) {
- return hostname;
- }
- if ( search(rules, '*' + hostname.slice(pos)) ) {
- return hostname;
- }
- hostname = hostname.slice(pos + 1);
- }
- // unreachable
+ hostname = hostname.toLowerCase();
+ var suffix = getPublicSuffix(hostname);
+ if ( suffix === hostname ) {
+ return '';
+ }
+ var pos = hostname.lastIndexOf('.', hostname.lastIndexOf('.', hostname.length - suffix.length) - 1);
+ if ( pos <= 0 ) {
+ return hostname;
}
+ return hostname.slice(pos + 1);
+}
- /******************************************************************************/
+/******************************************************************************/
- // Look up a specific hostname.
+// Return longest public suffix.
+//
+// `hostname` must be a valid ascii-based string which respect hostname naming.
- function search(store, hostname) {
- // Extract TLD
- var pos = hostname.lastIndexOf('.');
- var tld, remainder;
+function getPublicSuffix(hostname) {
+ if ( !hostname ) {
+ return '';
+ }
+ // Since we slice down the hostname with each pass, the first match
+ // is the longest, so no need to find all the matching rules.
+ var pos;
+ while ( true ) {
+ pos = hostname.indexOf('.');
if ( pos < 0 ) {
- tld = hostname;
- remainder = hostname;
- } else {
- tld = hostname.slice(pos + 1);
- remainder = hostname.slice(0, pos);
- }
- var substore = store[tld];
- if ( !substore ) {
- return false;
+ return hostname;
}
- // If substore is a string, use indexOf()
- if ( typeof substore === 'string' ) {
- return substore.indexOf(' ' + remainder + ' ') >= 0;
+ if ( search(exceptions, hostname) ) {
+ return hostname.slice(pos + 1);
}
- // It is an array: use binary search.
- var l = remainder.length;
- var haystack = substore[l];
- if ( !haystack ) {
- return false;
+ if ( search(rules, hostname) ) {
+ return hostname;
}
- var left = 0;
- var right = Math.floor(haystack.length / l + 0.5);
- var i, needle;
- while ( left < right ) {
- i = left + right >> 1;
- needle = haystack.substr( l * i, l );
- if ( remainder < needle ) {
- right = i;
- } else if ( remainder > needle ) {
- left = i + 1;
- } else {
- return true;
- }
+ if ( search(rules, '*' + hostname.slice(pos)) ) {
+ return hostname;
}
- return false;
+ hostname = hostname.slice(pos + 1);
}
+ // unreachable
+}
- /******************************************************************************/
-
- // Parse and set a UTF-8 text-based suffix list. Format is same as found at:
- // http://publicsuffix.org/list/
- //
- // `toAscii` is a converter from unicode to punycode. Required since the
- // Public Suffix List contains unicode characters.
- // Suggestion: use <https://github.com/bestiejs/punycode.js> it's quite good.
+/******************************************************************************/
- function parse(text, toAscii) {
- exceptions = {};
- rules = {};
+// Look up a specific hostname.
+
+function search(store, hostname) {
+ // Extract TLD
+ var pos = hostname.lastIndexOf('.');
+ var tld, remainder;
+ if ( pos < 0 ) {
+ tld = hostname;
+ remainder = hostname;
+ } else {
+ tld = hostname.slice(pos + 1);
+ remainder = hostname.slice(0, pos);
+ }
+ var substore = store[tld];
+ if ( !substore ) {
+ return false;
+ }
+ // If substore is a string, use indexOf()
+ if ( typeof substore === 'string' ) {
+ return substore.indexOf(' ' + remainder + ' ') >= 0;
+ }
+ // It is an array: use binary search.
+ var l = remainder.length;
+ var haystack = substore[l];
+ if ( !haystack ) {
+ return false;
+ }
+ var left = 0;
+ var right = Math.floor(haystack.length / l + 0.5);
+ var i, needle;
+ while ( left < right ) {
+ i = left + right >> 1;
+ needle = haystack.substr( l * i, l );
+ if ( remainder < needle ) {
+ right = i;
+ } else if ( remainder > needle ) {
+ left = i + 1;
+ } else {
+ return true;
+ }
+ }
+ return false;
+}
- var lineBeg = 0, lineEnd;
- var textEnd = text.length;
- var line, store, pos, tld;
+/******************************************************************************/
- while ( lineBeg < textEnd ) {
- lineEnd = text.indexOf('\n', lineBeg);
+// Parse and set a UTF-8 text-based suffix list. Format is same as found at:
+// http://publicsuffix.org/list/
+//
+// `toAscii` is a converter from unicode to punycode. Required since the
+// Public Suffix List contains unicode characters.
+// Suggestion: use <https://github.com/bestiejs/punycode.js> it's quite good.
+
+function parse(text, toAscii) {
+ exceptions = {};
+ rules = {};
+
+ var lineBeg = 0, lineEnd;
+ var textEnd = text.length;
+ var line, store, pos, tld;
+
+ while ( lineBeg < textEnd ) {
+ lineEnd = text.indexOf('\n', lineBeg);
+ if ( lineEnd < 0 ) {
+ lineEnd = text.indexOf('\r', lineBeg);
if ( lineEnd < 0 ) {
- lineEnd = text.indexOf('\r', lineBeg);
- if ( lineEnd < 0 ) {
- lineEnd = textEnd;
- }
+ lineEnd = textEnd;
}
- line = text.slice(lineBeg, lineEnd).trim();
- lineBeg = lineEnd + 1;
+ }
+ line = text.slice(lineBeg, lineEnd).trim();
+ lineBeg = lineEnd + 1;
- if ( line.length === 0 ) {
- continue;
- }
+ if ( line.length === 0 ) {
+ continue;
+ }
- // Ignore comments
- pos = line.indexOf('//');
- if ( pos >= 0 ) {
- line = line.slice(0, pos);
- }
+ // Ignore comments
+ pos = line.indexOf('//');
+ if ( pos >= 0 ) {
+ line = line.slice(0, pos);
+ }
- // Ignore surrounding whitespaces
- line = line.trim();
- if ( !line ) {
- continue;
- }
+ // Ignore surrounding whitespaces
+ line = line.trim();
+ if ( !line ) {
+ continue;
+ }
- // Is this an exception rule?
- if ( line.charAt(0) === '!' ) {
- store = exceptions;
- line = line.slice(1);
- } else {
- store = rules;
- }
+ // Is this an exception rule?
+ if ( line.charAt(0) === '!' ) {
+ store = exceptions;
+ line = line.slice(1);
+ } else {
+ store = rules;
+ }
- if ( mustPunycode.test(line) ) {
- line = toAscii(line);
- }
+ if ( mustPunycode.test(line) ) {
+ line = toAscii(line);
+ }
- // http://publicsuffix.org/list/:
- // "... all rules must be canonicalized in the normal way
- // for hostnames - lower-case, Punycode ..."
- line = line.toLowerCase();
-
- // Extract TLD
- pos = line.lastIndexOf('.');
- if ( pos < 0 ) {
- tld = line;
- } else {
- tld = line.slice(pos + 1);
- line = line.slice(0, pos);
- }
+ // http://publicsuffix.org/list/:
+ // "... all rules must be canonicalized in the normal way
+ // for hostnames - lower-case, Punycode ..."
+ line = line.toLowerCase();
- // Store suffix using tld as key
- if ( !store.hasOwnProperty(tld) ) {
- store[tld] = [];
- }
- if ( line ) {
- store[tld].push(line);
- }
+ // Extract TLD
+ pos = line.lastIndexOf('.');
+ if ( pos < 0 ) {
+ tld = line;
+ } else {
+ tld = line.slice(pos + 1);
+ line = line.slice(0, pos);
}
- crystallize(exceptions);
- crystallize(rules);
- callListeners(onChangedListeners);
+ // Store suffix using tld as key
+ if ( !store.hasOwnProperty(tld) ) {
+ store[tld] = [];
+ }
+ if ( line ) {
+ store[tld].push(line);
+ }
}
+ crystallize(exceptions);
+ crystallize(rules);
- /******************************************************************************/
+ callListeners(onChangedListeners);
+}
- // Cristallize the storage of suffixes using optimal internal representation
- // for future look up.
+/******************************************************************************/
- function crystallize(store) {
- var suffixes, suffix, i, l;
+// Cristallize the storage of suffixes using optimal internal representation
+// for future look up.
- for ( var tld in store ) {
- if ( !store.hasOwnProperty(tld) ) {
- continue;
- }
- suffixes = store[tld].join(' ');
- // No suffix
- if ( !suffixes ) {
- store[tld] = '';
- continue;
- }
- // Concatenated list of suffixes less than cutoff length:
- // Store as string, lookup using indexOf()
- if ( suffixes.length < cutoffLength ) {
- store[tld] = ' ' + suffixes + ' ';
- continue;
- }
- // Concatenated list of suffixes greater or equal to cutoff length
- // Store as array keyed on suffix length, lookup using binary search.
- // I borrowed the idea to key on string length here:
- // http://ejohn.org/blog/dictionary-lookups-in-javascript/#comment-392072
-
- i = store[tld].length;
- suffixes = [];
- while ( i-- ) {
- suffix = store[tld][i];
- l = suffix.length;
- if ( !suffixes[l] ) {
- suffixes[l] = [];
- }
- suffixes[l].push(suffix);
+function crystallize(store) {
+ var suffixes, suffix, i, l;
+
+ for ( var tld in store ) {
+ if ( !store.hasOwnProperty(tld) ) {
+ continue;
+ }
+ suffixes = store[tld].join(' ');
+ // No suffix
+ if ( !suffixes ) {
+ store[tld] = '';
+ continue;
+ }
+ // Concatenated list of suffixes less than cutoff length:
+ // Store as string, lookup using indexOf()
+ if ( suffixes.length < cutoffLength ) {
+ store[tld] = ' ' + suffixes + ' ';
+ continue;
+ }
+ // Concatenated list of suffixes greater or equal to cutoff length
+ // Store as array keyed on suffix length, lookup using binary search.
+ // I borrowed the idea to key on string length here:
+ // http://ejohn.org/blog/dictionary-lookups-in-javascript/#comment-392072
+
+ i = store[tld].length;
+ suffixes = [];
+ while ( i-- ) {
+ suffix = store[tld][i];
+ l = suffix.length;
+ if ( !suffixes[l] ) {
+ suffixes[l] = [];
}
- l = suffixes.length;
- while ( l-- ) {
- if ( suffixes[l] ) {
- suffixes[l] = suffixes[l].sort().join('');
- }
+ suffixes[l].push(suffix);
+ }
+ l = suffixes.length;
+ while ( l-- ) {
+ if ( suffixes[l] ) {
+ suffixes[l] = suffixes[l].sort().join('');
}
- store[tld] = suffixes;
}
- return store;
+ store[tld] = suffixes;
}
+ return store;
+}
- /******************************************************************************/
+/******************************************************************************/
- function toSelfie() {
- return {
- magic: selfieMagic,
- rules: rules,
- exceptions: exceptions
- };
- }
+function toSelfie() {
+ return {
+ magic: selfieMagic,
+ rules: rules,
+ exceptions: exceptions
+ };
+}
- function fromSelfie(selfie) {
- if ( typeof selfie !== 'object' || typeof selfie.magic !== 'string' || selfie.magic !== selfieMagic ) {
- return false;
- }
- rules = selfie.rules;
- exceptions = selfie.exceptions;
- callListeners(onChangedListeners);
- return true;
+function fromSelfie(selfie) {
+ if ( typeof selfie !== 'object' || typeof selfie.magic !== 'string' || selfie.magic !== selfieMagic ) {
+ return false;
}
+ rules = selfie.rules;
+ exceptions = selfie.exceptions;
+ callListeners(onChangedListeners);
+ return true;
+}
- /******************************************************************************/
+/******************************************************************************/
- var addListener = function(listeners, callback) {
- if ( typeof callback !== 'function' ) {
- return;
- }
- if ( listeners.indexOf(callback) === -1 ) {
- listeners.push(callback);
- }
- };
+var addListener = function(listeners, callback) {
+ if ( typeof callback !== 'function' ) {
+ return;
+ }
+ if ( listeners.indexOf(callback) === -1 ) {
+ listeners.push(callback);
+ }
+};
- var removeListener = function(listeners, callback) {
- var pos = listeners.indexOf(callback);
- if ( pos !== -1 ) {
- listeners.splice(pos, 1);
- }
- };
+var removeListener = function(listeners, callback) {
+ var pos = listeners.indexOf(callback);
+ if ( pos !== -1 ) {
+ listeners.splice(pos, 1);
+ }
+};
- var callListeners = function(listeners) {
- for ( var i = 0; i < listeners.length; i++ ) {
- listeners[i]();
- }
- };
+var callListeners = function(listeners) {
+ for ( var i = 0; i < listeners.length; i++ ) {
+ listeners[i]();
+ }
+};
- /******************************************************************************/
+/******************************************************************************/
- var onChanged = {
- addListener: function(callback) {
- addListener(onChangedListeners, callback);
- },
- removeListener: function(callback) {
- removeListener(onChangedListeners, callback);
- }
- };
+var onChanged = {
+ addListener: function(callback) {
+ addListener(onChangedListeners, callback);
+ },
+ removeListener: function(callback) {
+ removeListener(onChangedListeners, callback);
+ }
+};
- /******************************************************************************/
+/******************************************************************************/
- // Public API
+// Public API
- root = root || window;
+root = root || window;
- root.publicSuffixList = {
- 'version': '1.0',
- 'parse': parse,
- 'getDomain': getDomain,
- 'getPublicSuffix': getPublicSuffix,
- 'toSelfie': toSelfie,
- 'fromSelfie': fromSelfie,
- 'onChanged': onChanged
- };
+root.publicSuffixList = {
+ 'version': '1.0',
+ 'parse': parse,
+ 'getDomain': getDomain,
+ 'getPublicSuffix': getPublicSuffix,
+ 'toSelfie': toSelfie,
+ 'fromSelfie': fromSelfie,
+ 'onChanged': onChanged
+};
- /******************************************************************************/
+/******************************************************************************/
})(this);