| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * This file is part of Adblock Plus <http://adblockplus.org/>, | 2  * This file is part of Adblock Plus <http://adblockplus.org/>, | 
| 3  * Copyright (C) 2006-2014 Eyeo GmbH | 3  * Copyright (C) 2006-2014 Eyeo GmbH | 
| 4  * | 4  * | 
| 5  * Adblock Plus is free software: you can redistribute it and/or modify | 5  * Adblock Plus is free software: you can redistribute it and/or modify | 
| 6  * it under the terms of the GNU General Public License version 3 as | 6  * it under the terms of the GNU General Public License version 3 as | 
| 7  * published by the Free Software Foundation. | 7  * published by the Free Software Foundation. | 
| 8  * | 8  * | 
| 9  * Adblock Plus is distributed in the hope that it will be useful, | 9  * Adblock Plus is distributed in the hope that it will be useful, | 
| 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 158   { | 158   { | 
| 159     if (filter.text in this.keywordByFilter) | 159     if (filter.text in this.keywordByFilter) | 
| 160       return this.keywordByFilter[filter.text]; | 160       return this.keywordByFilter[filter.text]; | 
| 161     else | 161     else | 
| 162       return null; | 162       return null; | 
| 163   }, | 163   }, | 
| 164 | 164 | 
| 165   /** | 165   /** | 
| 166    * Checks whether the entries for a particular keyword match a URL | 166    * Checks whether the entries for a particular keyword match a URL | 
| 167    */ | 167    */ | 
| 168   _checkEntryMatch: function(keyword, location, contentType, docDomain, thirdPar
     ty) | 168   _checkEntryMatch: function(keyword, location, contentType, docDomain, thirdPar
     ty, sitekey) | 
| 169   { | 169   { | 
| 170     let list = this.filterByKeyword[keyword]; | 170     let list = this.filterByKeyword[keyword]; | 
| 171     for (let i = 0; i < list.length; i++) | 171     for (let i = 0; i < list.length; i++) | 
| 172     { | 172     { | 
| 173       let filter = list[i]; | 173       let filter = list[i]; | 
| 174       if (filter.matches(location, contentType, docDomain, thirdParty)) | 174       if (filter.matches(location, contentType, docDomain, thirdParty, sitekey)) | 
| 175         return filter; | 175         return filter; | 
| 176     } | 176     } | 
| 177     return null; | 177     return null; | 
| 178   }, | 178   }, | 
| 179 | 179 | 
| 180   /** | 180   /** | 
| 181    * Tests whether the URL matches any of the known filters | 181    * Tests whether the URL matches any of the known filters | 
| 182    * @param {String} location URL to be tested | 182    * @param {String} location URL to be tested | 
| 183    * @param {String} contentType content type identifier of the URL | 183    * @param {String} contentType content type identifier of the URL | 
| 184    * @param {String} docDomain domain name of the document that loads the URL | 184    * @param {String} docDomain domain name of the document that loads the URL | 
| 185    * @param {Boolean} thirdParty should be true if the URL is a third-party requ
     est | 185    * @param {Boolean} thirdParty should be true if the URL is a third-party requ
     est | 
|  | 186    * @param {String} sitekey public key provided by the document | 
| 186    * @return {RegExpFilter} matching filter or null | 187    * @return {RegExpFilter} matching filter or null | 
| 187    */ | 188    */ | 
| 188   matchesAny: function(location, contentType, docDomain, thirdParty) | 189   matchesAny: function(location, contentType, docDomain, thirdParty, sitekey) | 
| 189   { | 190   { | 
| 190     let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); | 191     let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); | 
| 191     if (candidates === null) | 192     if (candidates === null) | 
| 192       candidates = []; | 193       candidates = []; | 
| 193     candidates.push(""); | 194     candidates.push(""); | 
| 194     for (let i = 0, l = candidates.length; i < l; i++) | 195     for (let i = 0, l = candidates.length; i < l; i++) | 
| 195     { | 196     { | 
| 196       let substr = candidates[i]; | 197       let substr = candidates[i]; | 
| 197       if (substr in this.filterByKeyword) | 198       if (substr in this.filterByKeyword) | 
| 198       { | 199       { | 
| 199         let result = this._checkEntryMatch(substr, location, contentType, docDom
     ain, thirdParty); | 200         let result = this._checkEntryMatch(substr, location, contentType, docDom
     ain, thirdParty, sitekey); | 
| 200         if (result) | 201         if (result) | 
| 201           return result; | 202           return result; | 
| 202       } | 203       } | 
| 203     } | 204     } | 
| 204 | 205 | 
| 205     return null; | 206     return null; | 
| 206   } | 207   } | 
| 207 }; | 208 }; | 
| 208 | 209 | 
| 209 /** | 210 /** | 
| 210  * Combines a matcher for blocking and exception rules, automatically sorts | 211  * Combines a matcher for blocking and exception rules, automatically sorts | 
| 211  * rules into two Matcher instances. | 212  * rules into two Matcher instances. | 
| 212  * @constructor | 213  * @constructor | 
| 213  */ | 214  */ | 
| 214 function CombinedMatcher() | 215 function CombinedMatcher() | 
| 215 { | 216 { | 
| 216   this.blacklist = new Matcher(); | 217   this.blacklist = new Matcher(); | 
| 217   this.whitelist = new Matcher(); | 218   this.whitelist = new Matcher(); | 
| 218   this.keys = Object.create(null); |  | 
| 219   this.resultCache = Object.create(null); | 219   this.resultCache = Object.create(null); | 
| 220 } | 220 } | 
| 221 exports.CombinedMatcher = CombinedMatcher; | 221 exports.CombinedMatcher = CombinedMatcher; | 
| 222 | 222 | 
| 223 /** | 223 /** | 
| 224  * Maximal number of matching cache entries to be kept | 224  * Maximal number of matching cache entries to be kept | 
| 225  * @type Number | 225  * @type Number | 
| 226  */ | 226  */ | 
| 227 CombinedMatcher.maxCacheEntries = 1000; | 227 CombinedMatcher.maxCacheEntries = 1000; | 
| 228 | 228 | 
| 229 CombinedMatcher.prototype = | 229 CombinedMatcher.prototype = | 
| 230 { | 230 { | 
| 231   /** | 231   /** | 
| 232    * Matcher for blocking rules. | 232    * Matcher for blocking rules. | 
| 233    * @type Matcher | 233    * @type Matcher | 
| 234    */ | 234    */ | 
| 235   blacklist: null, | 235   blacklist: null, | 
| 236 | 236 | 
| 237   /** | 237   /** | 
| 238    * Matcher for exception rules. | 238    * Matcher for exception rules. | 
| 239    * @type Matcher | 239    * @type Matcher | 
| 240    */ | 240    */ | 
| 241   whitelist: null, | 241   whitelist: null, | 
| 242 | 242 | 
| 243   /** | 243   /** | 
| 244    * Exception rules that are limited by public keys, mapped by the correspondin
     g keys. |  | 
| 245    * @type Object |  | 
| 246    */ |  | 
| 247   keys: null, |  | 
| 248 |  | 
| 249   /** |  | 
| 250    * Lookup table of previous matchesAny results | 244    * Lookup table of previous matchesAny results | 
| 251    * @type Object | 245    * @type Object | 
| 252    */ | 246    */ | 
| 253   resultCache: null, | 247   resultCache: null, | 
| 254 | 248 | 
| 255   /** | 249   /** | 
| 256    * Number of entries in resultCache | 250    * Number of entries in resultCache | 
| 257    * @type Number | 251    * @type Number | 
| 258    */ | 252    */ | 
| 259   cacheEntries: 0, | 253   cacheEntries: 0, | 
| 260 | 254 | 
| 261   /** | 255   /** | 
| 262    * @see Matcher#clear | 256    * @see Matcher#clear | 
| 263    */ | 257    */ | 
| 264   clear: function() | 258   clear: function() | 
| 265   { | 259   { | 
| 266     this.blacklist.clear(); | 260     this.blacklist.clear(); | 
| 267     this.whitelist.clear(); | 261     this.whitelist.clear(); | 
| 268     this.keys = Object.create(null); |  | 
| 269     this.resultCache = Object.create(null); | 262     this.resultCache = Object.create(null); | 
| 270     this.cacheEntries = 0; | 263     this.cacheEntries = 0; | 
| 271   }, | 264   }, | 
| 272 | 265 | 
| 273   /** | 266   /** | 
| 274    * @see Matcher#add | 267    * @see Matcher#add | 
| 275    */ | 268    */ | 
| 276   add: function(filter) | 269   add: function(filter) | 
| 277   { | 270   { | 
| 278     if (filter instanceof WhitelistFilter) | 271     if (filter instanceof WhitelistFilter) | 
| 279     { | 272       this.whitelist.add(filter); | 
| 280       if (filter.siteKeys) |  | 
| 281       { |  | 
| 282         for (let i = 0; i < filter.siteKeys.length; i++) |  | 
| 283           this.keys[filter.siteKeys[i]] = filter.text; |  | 
| 284       } |  | 
| 285       else |  | 
| 286         this.whitelist.add(filter); |  | 
| 287     } |  | 
| 288     else | 273     else | 
| 289       this.blacklist.add(filter); | 274       this.blacklist.add(filter); | 
| 290 | 275 | 
| 291     if (this.cacheEntries > 0) | 276     if (this.cacheEntries > 0) | 
| 292     { | 277     { | 
| 293       this.resultCache = Object.create(null); | 278       this.resultCache = Object.create(null); | 
| 294       this.cacheEntries = 0; | 279       this.cacheEntries = 0; | 
| 295     } | 280     } | 
| 296   }, | 281   }, | 
| 297 | 282 | 
| 298   /** | 283   /** | 
| 299    * @see Matcher#remove | 284    * @see Matcher#remove | 
| 300    */ | 285    */ | 
| 301   remove: function(filter) | 286   remove: function(filter) | 
| 302   { | 287   { | 
| 303     if (filter instanceof WhitelistFilter) | 288     if (filter instanceof WhitelistFilter) | 
| 304     { | 289       this.whitelist.remove(filter); | 
| 305       if (filter.siteKeys) |  | 
| 306       { |  | 
| 307         for (let i = 0; i < filter.siteKeys.length; i++) |  | 
| 308           delete this.keys[filter.siteKeys[i]]; |  | 
| 309       } |  | 
| 310       else |  | 
| 311         this.whitelist.remove(filter); |  | 
| 312     } |  | 
| 313     else | 290     else | 
| 314       this.blacklist.remove(filter); | 291       this.blacklist.remove(filter); | 
| 315 | 292 | 
| 316     if (this.cacheEntries > 0) | 293     if (this.cacheEntries > 0) | 
| 317     { | 294     { | 
| 318       this.resultCache = Object.create(null); | 295       this.resultCache = Object.create(null); | 
| 319       this.cacheEntries = 0; | 296       this.cacheEntries = 0; | 
| 320     } | 297     } | 
| 321   }, | 298   }, | 
| 322 | 299 | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 363       return !matcher.getKeywordForFilter(filter); | 340       return !matcher.getKeywordForFilter(filter); | 
| 364     else | 341     else | 
| 365       return !matcher.findKeyword(filter); | 342       return !matcher.findKeyword(filter); | 
| 366   }, | 343   }, | 
| 367 | 344 | 
| 368   /** | 345   /** | 
| 369    * Optimized filter matching testing both whitelist and blacklist matchers | 346    * Optimized filter matching testing both whitelist and blacklist matchers | 
| 370    * simultaneously. For parameters see Matcher.matchesAny(). | 347    * simultaneously. For parameters see Matcher.matchesAny(). | 
| 371    * @see Matcher#matchesAny | 348    * @see Matcher#matchesAny | 
| 372    */ | 349    */ | 
| 373   matchesAnyInternal: function(location, contentType, docDomain, thirdParty) | 350   matchesAnyInternal: function(location, contentType, docDomain, thirdParty, sit
     ekey) | 
| 374   { | 351   { | 
| 375     let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); | 352     let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g); | 
| 376     if (candidates === null) | 353     if (candidates === null) | 
| 377       candidates = []; | 354       candidates = []; | 
| 378     candidates.push(""); | 355     candidates.push(""); | 
| 379 | 356 | 
| 380     let blacklistHit = null; | 357     let blacklistHit = null; | 
| 381     for (let i = 0, l = candidates.length; i < l; i++) | 358     for (let i = 0, l = candidates.length; i < l; i++) | 
| 382     { | 359     { | 
| 383       let substr = candidates[i]; | 360       let substr = candidates[i]; | 
| 384       if (substr in this.whitelist.filterByKeyword) | 361       if (substr in this.whitelist.filterByKeyword) | 
| 385       { | 362       { | 
| 386         let result = this.whitelist._checkEntryMatch(substr, location, contentTy
     pe, docDomain, thirdParty); | 363         let result = this.whitelist._checkEntryMatch(substr, location, contentTy
     pe, docDomain, thirdParty, sitekey); | 
| 387         if (result) | 364         if (result) | 
| 388           return result; | 365           return result; | 
| 389       } | 366       } | 
| 390       if (substr in this.blacklist.filterByKeyword && blacklistHit === null) | 367       if (substr in this.blacklist.filterByKeyword && blacklistHit === null) | 
| 391         blacklistHit = this.blacklist._checkEntryMatch(substr, location, content
     Type, docDomain, thirdParty); | 368         blacklistHit = this.blacklist._checkEntryMatch(substr, location, content
     Type, docDomain, thirdParty, sitekey); | 
| 392     } | 369     } | 
| 393     return blacklistHit; | 370     return blacklistHit; | 
| 394   }, | 371   }, | 
| 395 | 372 | 
| 396   /** | 373   /** | 
| 397    * @see Matcher#matchesAny | 374    * @see Matcher#matchesAny | 
| 398    */ | 375    */ | 
| 399   matchesAny: function(location, contentType, docDomain, thirdParty) | 376   matchesAny: function(location, contentType, docDomain, thirdParty, sitekey) | 
| 400   { | 377   { | 
| 401     let key = location + " " + contentType + " " + docDomain + " " + thirdParty; | 378     let key = location + " " + contentType + " " + docDomain + " " + thirdParty 
     + " " + sitekey; | 
| 402     if (key in this.resultCache) | 379     if (key in this.resultCache) | 
| 403       return this.resultCache[key]; | 380       return this.resultCache[key]; | 
| 404 | 381 | 
| 405     let result = this.matchesAnyInternal(location, contentType, docDomain, third
     Party); | 382     let result = this.matchesAnyInternal(location, contentType, docDomain, third
     Party, sitekey); | 
| 406 | 383 | 
| 407     if (this.cacheEntries >= CombinedMatcher.maxCacheEntries) | 384     if (this.cacheEntries >= CombinedMatcher.maxCacheEntries) | 
| 408     { | 385     { | 
| 409       this.resultCache = Object.create(null); | 386       this.resultCache = Object.create(null); | 
| 410       this.cacheEntries = 0; | 387       this.cacheEntries = 0; | 
| 411     } | 388     } | 
| 412 | 389 | 
| 413     this.resultCache[key] = result; | 390     this.resultCache[key] = result; | 
| 414     this.cacheEntries++; | 391     this.cacheEntries++; | 
| 415 | 392 | 
| 416     return result; | 393     return result; | 
| 417   }, |  | 
| 418 |  | 
| 419   /** |  | 
| 420    * Looks up whether any filters match the given website key. |  | 
| 421    */ |  | 
| 422   matchesByKey: function(/**String*/ location, /**String*/ key, /**String*/ docD
     omain) |  | 
| 423   { |  | 
| 424     key = key.toUpperCase(); |  | 
| 425     if (key in this.keys) |  | 
| 426     { |  | 
| 427       let filter = Filter.knownFilters[this.keys[key]]; |  | 
| 428       if (filter && filter.matches(location, "DOCUMENT", docDomain, false)) |  | 
| 429         return filter; |  | 
| 430       else |  | 
| 431         return null; |  | 
| 432     } |  | 
| 433     else |  | 
| 434       return null; |  | 
| 435   } | 394   } | 
| 436 } | 395 } | 
| 437 | 396 | 
| 438 /** | 397 /** | 
| 439  * Shared CombinedMatcher instance that should usually be used. | 398  * Shared CombinedMatcher instance that should usually be used. | 
| 440  * @type CombinedMatcher | 399  * @type CombinedMatcher | 
| 441  */ | 400  */ | 
| 442 let defaultMatcher = exports.defaultMatcher = new CombinedMatcher(); | 401 let defaultMatcher = exports.defaultMatcher = new CombinedMatcher(); | 
| OLD | NEW | 
|---|