diff options
Diffstat (limited to 'data/extensions/spyblock@gnu.org/lib/matcher.js')
-rw-r--r-- | data/extensions/spyblock@gnu.org/lib/matcher.js | 173 |
1 files changed, 113 insertions, 60 deletions
diff --git a/data/extensions/spyblock@gnu.org/lib/matcher.js b/data/extensions/spyblock@gnu.org/lib/matcher.js index 59ef1e7..02573bd 100644 --- a/data/extensions/spyblock@gnu.org/lib/matcher.js +++ b/data/extensions/spyblock@gnu.org/lib/matcher.js @@ -1,6 +1,6 @@ /* * This file is part of Adblock Plus <https://adblockplus.org/>, - * Copyright (C) 2006-2015 Eyeo GmbH + * Copyright (C) 2006-2017 eyeo GmbH * * Adblock Plus is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -15,11 +15,14 @@ * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. */ +"use strict"; + /** - * @fileOverview Matcher class implementing matching addresses against a list of filters. + * @fileOverview Matcher class implementing matching addresses against + * a list of filters. */ -let {Filter, RegExpFilter, WhitelistFilter} = require("filterClasses"); +const {Filter, WhitelistFilter} = require("filterClasses"); /** * Blacklist/whitelist filter matching @@ -34,20 +37,20 @@ exports.Matcher = Matcher; Matcher.prototype = { /** * Lookup table for filters by their associated keyword - * @type Object + * @type {Object} */ filterByKeyword: null, /** * Lookup table for keywords by the filter text - * @type Object + * @type {Object} */ keywordByFilter: null, /** * Removes all known filters */ - clear: function() + clear() { this.filterByKeyword = Object.create(null); this.keywordByFilter = Object.create(null); @@ -57,7 +60,7 @@ Matcher.prototype = { * Adds a filter to the matcher * @param {RegExpFilter} filter */ - add: function(filter) + add(filter) { if (filter.text in this.keywordByFilter) return; @@ -78,7 +81,7 @@ Matcher.prototype = { * Removes a filter from the matcher * @param {RegExpFilter} filter */ - remove: function(filter) + remove(filter) { if (!(filter.text in this.keywordByFilter)) return; @@ -103,13 +106,13 @@ Matcher.prototype = { /** * Chooses a keyword to be associated with the filter - * @param {String} text text representation of the filter - * @return {String} keyword (might be empty string) + * @param {Filter} filter + * @return {string} keyword or an empty string if no keyword could be found */ - findKeyword: function(filter) + findKeyword(filter) { let result = ""; - let text = filter.text; + let {text} = filter; if (Filter.regexpRegExp.test(text)) return result; @@ -122,7 +125,9 @@ Matcher.prototype = { if (text.substr(0, 2) == "@@") text = text.substr(2); - let candidates = text.toLowerCase().match(/[^a-z0-9%*][a-z0-9%]{3,}(?=[^a-z0-9%*])/g); + let candidates = text.toLowerCase().match( + /[^a-z0-9%*][a-z0-9%]{3,}(?=[^a-z0-9%*])/g + ); if (!candidates) return result; @@ -133,7 +138,8 @@ Matcher.prototype = { { let candidate = candidates[i].substr(1); let count = (candidate in hash ? hash[candidate].length : 0); - if (count < resultCount || (count == resultCount && candidate.length > resultLength)) + if (count < resultCount || + (count == resultCount && candidate.length > resultLength)) { result = candidate; resultCount = count; @@ -145,33 +151,50 @@ Matcher.prototype = { /** * Checks whether a particular filter is being matched against. + * @param {RegExpFilter} filter + * @return {boolean} */ - hasFilter: function(/**RegExpFilter*/ filter) /**Boolean*/ + hasFilter(filter) { return (filter.text in this.keywordByFilter); }, /** * Returns the keyword used for a filter, null for unknown filters. + * @param {RegExpFilter} filter + * @return {string} */ - getKeywordForFilter: function(/**RegExpFilter*/ filter) /**String*/ + getKeywordForFilter(filter) { if (filter.text in this.keywordByFilter) return this.keywordByFilter[filter.text]; - else - return null; + return null; }, /** * Checks whether the entries for a particular keyword match a URL + * @param {string} keyword + * @param {string} location + * @param {number} typeMask + * @param {string} docDomain + * @param {boolean} thirdParty + * @param {string} sitekey + * @param {boolean} specificOnly + * @return {?Filter} */ - _checkEntryMatch: function(keyword, location, contentType, docDomain, thirdParty, sitekey, privatenode) + _checkEntryMatch(keyword, location, typeMask, docDomain, thirdParty, sitekey, + specificOnly, privatenode) { let list = this.filterByKeyword[keyword]; for (let i = 0; i < list.length; i++) { let filter = list[i]; - if (filter.matches(location, contentType, docDomain, thirdParty, sitekey, privatenode)) + + if (specificOnly && filter.isGeneric() && + !(filter instanceof WhitelistFilter)) + continue; + + if (filter.matches(location, typeMask, docDomain, thirdParty, sitekey, privatenode)) return filter; } return null; @@ -179,14 +202,22 @@ Matcher.prototype = { /** * Tests whether the URL matches any of the known filters - * @param {String} location URL to be tested - * @param {String} contentType content type identifier of the URL - * @param {String} docDomain domain name of the document that loads the URL - * @param {Boolean} thirdParty should be true if the URL is a third-party request - * @param {String} sitekey public key provided by the document - * @return {RegExpFilter} matching filter or null + * @param {string} location + * URL to be tested + * @param {number} typeMask + * bitmask of content / request types to match + * @param {string} docDomain + * domain name of the document that loads the URL + * @param {boolean} thirdParty + * should be true if the URL is a third-party request + * @param {string} sitekey + * public key provided by the document + * @param {boolean} specificOnly + * should be true if generic matches should be ignored + * @return {?RegExpFilter} + * matching filter or null */ - matchesAny: function(location, contentType, docDomain, thirdParty, sitekey) + matchesAny(location, typeMask, docDomain, thirdParty, sitekey, specificOnly) { let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); if (candidates === null) @@ -197,7 +228,9 @@ Matcher.prototype = { let substr = candidates[i]; if (substr in this.filterByKeyword) { - let result = this._checkEntryMatch(substr, location, contentType, docDomain, thirdParty, sitekey); + let result = this._checkEntryMatch(substr, location, typeMask, + docDomain, thirdParty, sitekey, + specificOnly); if (result) return result; } @@ -211,6 +244,7 @@ Matcher.prototype = { * Combines a matcher for blocking and exception rules, automatically sorts * rules into two Matcher instances. * @constructor + * @augments Matcher */ function CombinedMatcher() { @@ -222,7 +256,7 @@ exports.CombinedMatcher = CombinedMatcher; /** * Maximal number of matching cache entries to be kept - * @type Number + * @type {number} */ CombinedMatcher.maxCacheEntries = 1000; @@ -230,32 +264,32 @@ CombinedMatcher.prototype = { /** * Matcher for blocking rules. - * @type Matcher + * @type {Matcher} */ blacklist: null, /** * Matcher for exception rules. - * @type Matcher + * @type {Matcher} */ whitelist: null, /** * Lookup table of previous matchesAny results - * @type Object + * @type {Object} */ resultCache: null, /** * Number of entries in resultCache - * @type Number + * @type {number} */ cacheEntries: 0, /** * @see Matcher#clear */ - clear: function() + clear() { this.blacklist.clear(); this.whitelist.clear(); @@ -265,8 +299,9 @@ CombinedMatcher.prototype = /** * @see Matcher#add + * @param {Filter} filter */ - add: function(filter) + add(filter) { if (filter instanceof WhitelistFilter) this.whitelist.add(filter); @@ -282,8 +317,9 @@ CombinedMatcher.prototype = /** * @see Matcher#remove + * @param {Filter} filter */ - remove: function(filter) + remove(filter) { if (filter instanceof WhitelistFilter) this.whitelist.remove(filter); @@ -299,55 +335,63 @@ CombinedMatcher.prototype = /** * @see Matcher#findKeyword + * @param {Filter} filter + * @return {string} keyword */ - findKeyword: function(filter) + findKeyword(filter) { if (filter instanceof WhitelistFilter) return this.whitelist.findKeyword(filter); - else - return this.blacklist.findKeyword(filter); + return this.blacklist.findKeyword(filter); }, /** * @see Matcher#hasFilter + * @param {Filter} filter + * @return {boolean} */ - hasFilter: function(filter) + hasFilter(filter) { if (filter instanceof WhitelistFilter) return this.whitelist.hasFilter(filter); - else - return this.blacklist.hasFilter(filter); + return this.blacklist.hasFilter(filter); }, /** * @see Matcher#getKeywordForFilter + * @param {Filter} filter + * @return {string} keyword */ - getKeywordForFilter: function(filter) + getKeywordForFilter(filter) { if (filter instanceof WhitelistFilter) return this.whitelist.getKeywordForFilter(filter); - else - return this.blacklist.getKeywordForFilter(filter); + return this.blacklist.getKeywordForFilter(filter); }, /** * Checks whether a particular filter is slow + * @param {RegExpFilter} filter + * @return {boolean} */ - isSlowFilter: function(/**RegExpFilter*/ filter) /**Boolean*/ + isSlowFilter(filter) { - let matcher = (filter instanceof WhitelistFilter ? this.whitelist : this.blacklist); + let matcher = ( + filter instanceof WhitelistFilter ? this.whitelist : this.blacklist + ); if (matcher.hasFilter(filter)) return !matcher.getKeywordForFilter(filter); - else - return !matcher.findKeyword(filter); + return !matcher.findKeyword(filter); }, /** * Optimized filter matching testing both whitelist and blacklist matchers * simultaneously. For parameters see Matcher.matchesAny(). * @see Matcher#matchesAny + * @inheritdoc */ - matchesAnyInternal: function(location, contentType, docDomain, thirdParty, sitekey, privatenode) + matchesAnyInternal(location, typeMask, docDomain, thirdParty, sitekey, + specificOnly, privatenode) { let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); if (candidates === null) @@ -360,28 +404,37 @@ CombinedMatcher.prototype = let substr = candidates[i]; if (substr in this.whitelist.filterByKeyword) { - let result = this.whitelist._checkEntryMatch(substr, location, contentType, docDomain, thirdParty, sitekey, privatenode); + let result = this.whitelist._checkEntryMatch( + substr, location, typeMask, docDomain, thirdParty, sitekey, privatenode + ); if (result) return result; } if (substr in this.blacklist.filterByKeyword && blacklistHit === null) - blacklistHit = this.blacklist._checkEntryMatch(substr, location, contentType, docDomain, thirdParty, sitekey, privatenode); + { + blacklistHit = this.blacklist._checkEntryMatch( + substr, location, typeMask, docDomain, thirdParty, sitekey, + specificOnly, privatenode + ); + } } return blacklistHit; }, /** * @see Matcher#matchesAny + * @inheritdoc */ - matchesAny: function(location, contentType, docDomain, thirdParty, sitekey, privatenode) + matchesAny(location, typeMask, docDomain, thirdParty, sitekey, specificOnly, privatenode) { - let key = location + " " + contentType + " " + docDomain + " " + thirdParty + " " + sitekey; - if (!privatenode){ + let key = location + " " + typeMask + " " + docDomain + " " + thirdParty + + " " + sitekey + " " + specificOnly; + if (!privatenode) if (key in this.resultCache) return this.resultCache[key]; - } - let result = this.matchesAnyInternal(location, contentType, docDomain, thirdParty, sitekey, privatenode); + let result = this.matchesAnyInternal(location, typeMask, docDomain, + thirdParty, sitekey, specificOnly, privatenode); if (this.cacheEntries >= CombinedMatcher.maxCacheEntries) { @@ -396,10 +449,10 @@ CombinedMatcher.prototype = return result; } -} +}; /** * Shared CombinedMatcher instance that should usually be used. - * @type CombinedMatcher + * @type {CombinedMatcher} */ -let defaultMatcher = exports.defaultMatcher = new CombinedMatcher(); +exports.defaultMatcher = new CombinedMatcher(); |