| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 
| 3  * Copyright (C) 2006-present eyeo GmbH | 3  * Copyright (C) 2006-present 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 | 
| 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| 12  * GNU General Public License for more details. | 12  * GNU General Public License for more details. | 
| 13  * | 13  * | 
| 14  * You should have received a copy of the GNU General Public License | 14  * You should have received a copy of the GNU General Public License | 
| 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
| 16  */ | 16  */ | 
| 17 | 17 | 
| 18 "use strict"; | 18 "use strict"; | 
| 19 | 19 | 
| 20 /** | 20 /** | 
| 21  * @fileOverview Definition of Filter class and its subclasses. | 21  * @fileOverview Definition of Filter class and its subclasses. | 
| 22  */ | 22  */ | 
| 23 | 23 | 
| 24 const {filterNotifier} = require("./filterNotifier"); | 24 const {filterNotifier} = require("./filterNotifier"); | 
| 25 const {extend} = require("./coreUtils"); | 25 const {extend} = require("./coreUtils"); | 
| 26 const {filterToRegExp} = require("./common"); | 26 const {filterToRegExp} = require("./common"); | 
| 27 | 27 | 
|  | 28 let tripleAnchorRegExp = new RegExp(filterToRegExp("|||")); | 
|  | 29 | 
| 28 /** | 30 /** | 
| 29  * All known unique domain sources mapped to their parsed values. | 31  * All known unique domain sources mapped to their parsed values. | 
| 30  * @type {Map.<string,Map.<string,boolean>>} | 32  * @type {Map.<string,Map.<string,boolean>>} | 
| 31  */ | 33  */ | 
| 32 let knownDomainMaps = new Map(); | 34 let knownDomainMaps = new Map(); | 
| 33 | 35 | 
| 34 /** | 36 /** | 
| 35  * Abstract base class for filters | 37  * Abstract base class for filters | 
| 36  * | 38  * | 
| 37  * @param {string} text   string representation of the filter | 39  * @param {string} text   string representation of the filter | 
| (...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 657  * @param {boolean} [matchCase] | 659  * @param {boolean} [matchCase] | 
| 658  *   Defines whether the filter should distinguish between lower and upper case | 660  *   Defines whether the filter should distinguish between lower and upper case | 
| 659  *   letters | 661  *   letters | 
| 660  * @param {string} [domains] | 662  * @param {string} [domains] | 
| 661  *   Domains that the filter is restricted to, e.g. "foo.com|bar.com|~baz.com" | 663  *   Domains that the filter is restricted to, e.g. "foo.com|bar.com|~baz.com" | 
| 662  * @param {boolean} [thirdParty] | 664  * @param {boolean} [thirdParty] | 
| 663  *   Defines whether the filter should apply to third-party or first-party | 665  *   Defines whether the filter should apply to third-party or first-party | 
| 664  *   content only | 666  *   content only | 
| 665  * @param {string} [sitekeys] | 667  * @param {string} [sitekeys] | 
| 666  *   Public keys of websites that this filter should apply to | 668  *   Public keys of websites that this filter should apply to | 
| 667  * @constructor | 669  * @param {?string} [rewrite] | 
|  | 670  *   The (optional) rule specifying how to rewrite the URL. | 
| 668  * @augments ActiveFilter | 671  * @augments ActiveFilter | 
| 669  */ | 672  */ | 
| 670 function RegExpFilter(text, regexpSource, contentType, matchCase, domains, | 673 function RegExpFilter(text, regexpSource, contentType, matchCase, domains, | 
| 671                       thirdParty, sitekeys) | 674                       thirdParty, sitekeys, rewrite) | 
| 672 { | 675 { | 
| 673   ActiveFilter.call(this, text, domains); | 676   ActiveFilter.call(this, text, domains); | 
| 674 | 677 | 
| 675   if (contentType != null) | 678   if (contentType != null) | 
| 676     this.contentType = contentType; | 679     this.contentType = contentType; | 
| 677   if (matchCase) | 680   if (matchCase) | 
| 678     this.matchCase = matchCase; | 681     this.matchCase = matchCase; | 
| 679   if (thirdParty != null) | 682   if (thirdParty != null) | 
| 680     this.thirdParty = thirdParty; | 683     this.thirdParty = thirdParty; | 
| 681   if (sitekeys != null) | 684   if (sitekeys != null) | 
| 682     this.sitekeySource = sitekeys; | 685     this.sitekeySource = sitekeys; | 
| 683 | 686 | 
| 684   if (regexpSource.length >= 2 && | 687   if (regexpSource.length >= 2 && | 
| 685       regexpSource[0] == "/" && | 688       regexpSource[0] == "/" && | 
| 686       regexpSource[regexpSource.length - 1] == "/") | 689       regexpSource[regexpSource.length - 1] == "/") | 
| 687   { | 690   { | 
| 688     // The filter is a regular expression - convert it immediately to | 691     // The filter is a regular expression - convert it immediately to | 
| 689     // catch syntax errors | 692     // catch syntax errors | 
| 690     let regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2), | 693     let regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2), | 
| 691                             this.matchCase ? "" : "i"); | 694                             this.matchCase ? "" : "i"); | 
| 692     Object.defineProperty(this, "regexp", {value: regexp}); | 695     Object.defineProperty(this, "regexp", {value: regexp}); | 
| 693   } | 696   } | 
| 694   else | 697   else | 
| 695   { | 698   { | 
| 696     // No need to convert this filter to regular expression yet, do it on demand | 699     // No need to convert this filter to regular expression yet, do it on demand | 
| 697     this.pattern = regexpSource; | 700     this.pattern = regexpSource; | 
|  | 701 | 
|  | 702     if (rewrite == null) | 
|  | 703     { | 
|  | 704       this.pattern = this.pattern.replace(/^\**/, "").replace(/\**$/, ""); | 
|  | 705 | 
|  | 706       if (!this.matchCase) | 
|  | 707         this.pattern = this.pattern.toLowerCase(); | 
|  | 708     } | 
| 698   } | 709   } | 
| 699 } | 710 } | 
| 700 exports.RegExpFilter = RegExpFilter; | 711 exports.RegExpFilter = RegExpFilter; | 
| 701 | 712 | 
| 702 RegExpFilter.prototype = extend(ActiveFilter, { | 713 RegExpFilter.prototype = extend(ActiveFilter, { | 
| 703   /** | 714   /** | 
| 704    * Number of filters contained, will always be 1 (required to | 715    * Number of filters contained, will always be 1 (required to | 
| 705    * optimize {@link Matcher}). | 716    * optimize {@link Matcher}). | 
| 706    * @type {number} | 717    * @type {number} | 
| 707    */ | 718    */ | 
| 708   size: 1, | 719   size: 1, | 
| 709 | 720 | 
| 710   /** | 721   /** | 
| 711    * @see ActiveFilter.domainSeparator | 722    * @see ActiveFilter.domainSeparator | 
| 712    */ | 723    */ | 
| 713   domainSeparator: "|", | 724   domainSeparator: "|", | 
| 714 | 725 | 
| 715   /** | 726   /** | 
| 716    * Expression from which a regular expression should be generated - | 727    * Expression from which a regular expression should be generated - | 
| 717    * for delayed creation of the regexp property | 728    * for delayed creation of the regexp property | 
| 718    * @type {?string} | 729    * @type {?string} | 
| 719    */ | 730    */ | 
| 720   pattern: null, | 731   pattern: null, | 
| 721   /** | 732   /** | 
| 722    * Regular expression to be used when testing against this filter | 733    * Regular expression to be used when testing against this filter | 
| 723    * @type {RegExp} | 734    * @type {RegExp} | 
| 724    */ | 735    */ | 
| 725   get regexp() | 736   get regexp() | 
| 726   { | 737   { | 
| 727     let source = filterToRegExp(this.pattern, this.rewrite != null); | 738     let value = null; | 
| 728     let regexp = new RegExp(source, this.matchCase ? "" : "i"); | 739 | 
| 729     Object.defineProperty(this, "regexp", {value: regexp}); | 740     let {pattern, rewrite} = this; | 
| 730     return regexp; | 741     if (rewrite != null || /[*^|]/.test(pattern.replace(/^\|{1,2}/, ""))) | 
|  | 742     { | 
|  | 743       value = new RegExp(filterToRegExp(pattern, rewrite != null), | 
|  | 744                          this.matchCase ? "" : "i"); | 
|  | 745     } | 
|  | 746 | 
|  | 747     Object.defineProperty(this, "regexp", {value}); | 
|  | 748     return value; | 
| 731   }, | 749   }, | 
| 732   /** | 750   /** | 
| 733    * Content types the filter applies to, combination of values from | 751    * Content types the filter applies to, combination of values from | 
| 734    * RegExpFilter.typeMap | 752    * RegExpFilter.typeMap | 
| 735    * @type {number} | 753    * @type {number} | 
| 736    */ | 754    */ | 
| 737   contentType: 0x7FFFFFFF, | 755   contentType: 0x7FFFFFFF, | 
| 738   /** | 756   /** | 
| 739    * Defines whether the filter should distinguish between lower and | 757    * Defines whether the filter should distinguish between lower and | 
| 740    * upper case letters | 758    * upper case letters | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 781    * @param {boolean} [thirdParty] should be true if the URL is a third-party | 799    * @param {boolean} [thirdParty] should be true if the URL is a third-party | 
| 782    *                               request | 800    *                               request | 
| 783    * @param {string} [sitekey] public key provided by the document | 801    * @param {string} [sitekey] public key provided by the document | 
| 784    * @return {boolean} true in case of a match | 802    * @return {boolean} true in case of a match | 
| 785    */ | 803    */ | 
| 786   matches(location, typeMask, docDomain, thirdParty, sitekey) | 804   matches(location, typeMask, docDomain, thirdParty, sitekey) | 
| 787   { | 805   { | 
| 788     return (this.contentType & typeMask) != 0 && | 806     return (this.contentType & typeMask) != 0 && | 
| 789            (this.thirdParty == null || this.thirdParty == thirdParty) && | 807            (this.thirdParty == null || this.thirdParty == thirdParty) && | 
| 790            this.isActiveOnDomain(docDomain, sitekey) && | 808            this.isActiveOnDomain(docDomain, sitekey) && | 
| 791            this.regexp.test(location); | 809            this.matchesLocation(location); | 
|  | 810   }, | 
|  | 811 | 
|  | 812   matchesLocation(location) | 
|  | 813   { | 
|  | 814     let {regexp} = this; | 
|  | 815 | 
|  | 816     if (regexp) | 
|  | 817       return regexp.test(location); | 
|  | 818 | 
|  | 819     if (!this.matchCase) | 
|  | 820       location = location.toLowerCase(); | 
|  | 821 | 
|  | 822     let {pattern} = this; | 
|  | 823 | 
|  | 824     if (pattern[0] == "|") | 
|  | 825     { | 
|  | 826       if (pattern[1] == "|") | 
|  | 827       { | 
|  | 828         let index = location.indexOf(pattern.substring(2)); | 
|  | 829         return index != -1 && location[index] != "/" && | 
|  | 830                tripleAnchorRegExp.test(location.substring(0, index)); | 
|  | 831       } | 
|  | 832 | 
|  | 833       return location.startsWith(pattern.substring(1)); | 
|  | 834     } | 
|  | 835 | 
|  | 836     return location.includes(pattern); | 
| 792   } | 837   } | 
| 793 }); | 838 }); | 
| 794 | 839 | 
| 795 /** | 840 /** | 
| 796  * Yields the filter itself (required to optimize {@link Matcher}). | 841  * Yields the filter itself (required to optimize {@link Matcher}). | 
| 797  * @yields {RegExpFilter} | 842  * @yields {RegExpFilter} | 
| 798  */ | 843  */ | 
| 799 RegExpFilter.prototype[Symbol.iterator] = function*() | 844 RegExpFilter.prototype[Symbol.iterator] = function*() | 
| 800 { | 845 { | 
| 801   yield this; | 846   yield this; | 
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 986  * @param {?string} [rewrite] | 1031  * @param {?string} [rewrite] | 
| 987  *   The (optional) rule specifying how to rewrite the URL. See | 1032  *   The (optional) rule specifying how to rewrite the URL. See | 
| 988  *   BlockingFilter.prototype.rewrite. | 1033  *   BlockingFilter.prototype.rewrite. | 
| 989  * @constructor | 1034  * @constructor | 
| 990  * @augments RegExpFilter | 1035  * @augments RegExpFilter | 
| 991  */ | 1036  */ | 
| 992 function BlockingFilter(text, regexpSource, contentType, matchCase, domains, | 1037 function BlockingFilter(text, regexpSource, contentType, matchCase, domains, | 
| 993                         thirdParty, sitekeys, collapse, csp, rewrite) | 1038                         thirdParty, sitekeys, collapse, csp, rewrite) | 
| 994 { | 1039 { | 
| 995   RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, | 1040   RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, | 
| 996                     thirdParty, sitekeys); | 1041                     thirdParty, sitekeys, rewrite); | 
| 997 | 1042 | 
| 998   if (collapse != null) | 1043   if (collapse != null) | 
| 999     this.collapse = collapse; | 1044     this.collapse = collapse; | 
| 1000 | 1045 | 
| 1001   if (csp != null) | 1046   if (csp != null) | 
| 1002     this.csp = csp; | 1047     this.csp = csp; | 
| 1003 | 1048 | 
| 1004   if (rewrite != null) | 1049   if (rewrite != null) | 
| 1005     this.rewrite = rewrite; | 1050     this.rewrite = rewrite; | 
| 1006 } | 1051 } | 
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1276 | 1321 | 
| 1277   /** | 1322   /** | 
| 1278    * Script that should be executed | 1323    * Script that should be executed | 
| 1279    * @type {string} | 1324    * @type {string} | 
| 1280    */ | 1325    */ | 
| 1281   get script() | 1326   get script() | 
| 1282   { | 1327   { | 
| 1283     return this.body; | 1328     return this.body; | 
| 1284   } | 1329   } | 
| 1285 }); | 1330 }); | 
| OLD | NEW | 
|---|