| 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-2016 Eyeo GmbH |     3  * Copyright (C) 2006-2016 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 /** |    18 /** | 
|    19  * @fileOverview Definition of Filter class and its subclasses. |    19  * @fileOverview Definition of Filter class and its subclasses. | 
|    20  */ |    20  */ | 
|    21  |    21  | 
|    22 let {FilterNotifier} = require("filterNotifier"); |    22 let {FilterNotifier} = require("filterNotifier"); | 
|    23 let {extend} = require("coreUtils"); |    23 let {extend} = require("coreUtils"); | 
 |    24 let {filterToRegExp} = require("common"); | 
|    24  |    25  | 
|    25 /** |    26 /** | 
|    26  * Abstract base class for filters |    27  * Abstract base class for filters | 
|    27  * |    28  * | 
|    28  * @param {String} text   string representation of the filter |    29  * @param {String} text   string representation of the filter | 
|    29  * @constructor |    30  * @constructor | 
|    30  */ |    31  */ | 
|    31 function Filter(text) |    32 function Filter(text) | 
|    32 { |    33 { | 
|    33   this.text = text; |    34   this.text = text; | 
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|    88 /** |    89 /** | 
|    89  * Regular expression that RegExp filters specified as RegExps should match |    90  * Regular expression that RegExp filters specified as RegExps should match | 
|    90  * @type RegExp |    91  * @type RegExp | 
|    91  */ |    92  */ | 
|    92 Filter.regexpRegExp = /^(@@)?\/.*\/(?:\$~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:=[
      ^,\s]+)?)*)?$/; |    93 Filter.regexpRegExp = /^(@@)?\/.*\/(?:\$~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:=[
      ^,\s]+)?)*)?$/; | 
|    93 /** |    94 /** | 
|    94  * Regular expression that options on a RegExp filter should match |    95  * Regular expression that options on a RegExp filter should match | 
|    95  * @type RegExp |    96  * @type RegExp | 
|    96  */ |    97  */ | 
|    97 Filter.optionsRegExp = /\$(~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:=[^,\s]+)?)*)$/
      ; |    98 Filter.optionsRegExp = /\$(~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:=[^,\s]+)?)*)$/
      ; | 
|    98 /** |  | 
|    99  * Regular expression that CSS property filters should match |  | 
|   100  * Properties must not contain " or ' |  | 
|   101  * @type RegExp |  | 
|   102  */ |  | 
|   103 Filter.csspropertyRegExp = /\[\-abp\-properties=(["'])([^"']+)\1\]/; |  | 
|   104  |    99  | 
|   105 /** |   100 /** | 
|   106  * Creates a filter of correct type from its text representation - does the basi
      c parsing and |   101  * Creates a filter of correct type from its text representation - does the basi
      c parsing and | 
|   107  * calls the right constructor then. |   102  * calls the right constructor then. | 
|   108  * |   103  * | 
|   109  * @param {String} text   as in Filter() |   104  * @param {String} text   as in Filter() | 
|   110  * @return {Filter} |   105  * @return {Filter} | 
|   111  */ |   106  */ | 
|   112 Filter.fromText = function(text) |   107 Filter.fromText = function(text) | 
|   113 { |   108 { | 
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   169   { |   164   { | 
|   170     // Special treatment for element hiding filters, right side is allowed to co
      ntain spaces |   165     // Special treatment for element hiding filters, right side is allowed to co
      ntain spaces | 
|   171     let [, domain, separator, selector] = /^(.*?)(#\@?#?)(.*)$/.exec(text); |   166     let [, domain, separator, selector] = /^(.*?)(#\@?#?)(.*)$/.exec(text); | 
|   172     return domain.replace(/\s/g, "") + separator + selector.trim(); |   167     return domain.replace(/\s/g, "") + separator + selector.trim(); | 
|   173   } |   168   } | 
|   174   else |   169   else | 
|   175     return text.replace(/\s/g, ""); |   170     return text.replace(/\s/g, ""); | 
|   176 }; |   171 }; | 
|   177  |   172  | 
|   178 /** |   173 /** | 
|   179  * Converts filter text into regular expression string |   174  * @see filterToRegExp | 
|   180  * @param {String} text as in Filter() |  | 
|   181  * @return {String} regular expression representation of filter text |  | 
|   182  */ |   175  */ | 
|   183 Filter.toRegExp = function(text) |   176 Filter.toRegExp = filterToRegExp; | 
|   184 { |  | 
|   185   return text |  | 
|   186     .replace(/\*+/g, "*")        // remove multiple wildcards |  | 
|   187     .replace(/\^\|$/, "^")       // remove anchors following separator placehold
      er |  | 
|   188     .replace(/\W/g, "\\$&")      // escape special symbols |  | 
|   189     .replace(/\\\*/g, ".*")      // replace wildcards by .* |  | 
|   190     // process separator placeholders (all ANSI characters but alphanumeric char
      acters and _%.-) |  | 
|   191     .replace(/\\\^/g, "(?:[\\x00-\\x24\\x26-\\x2C\\x2F\\x3A-\\x40\\x5B-\\x5E\\x6
      0\\x7B-\\x7F]|$)") |  | 
|   192     .replace(/^\\\|\\\|/, "^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?") // process ex
      tended anchor at expression start |  | 
|   193     .replace(/^\\\|/, "^")       // process anchor at expression start |  | 
|   194     .replace(/\\\|$/, "$")       // process anchor at expression end |  | 
|   195     .replace(/^(\.\*)/, "")      // remove leading wildcards |  | 
|   196     .replace(/(\.\*)$/, "");     // remove trailing wildcards |  | 
|   197 } |  | 
|   198  |   177  | 
|   199 /** |   178 /** | 
|   200  * Class for invalid filters |   179  * Class for invalid filters | 
|   201  * @param {String} text see Filter() |   180  * @param {String} text see Filter() | 
|   202  * @param {String} reason Reason why this filter is invalid |   181  * @param {String} reason Reason why this filter is invalid | 
|   203  * @constructor |   182  * @constructor | 
|   204  * @augments Filter |   183  * @augments Filter | 
|   205  */ |   184  */ | 
|   206 function InvalidFilter(text, reason) |   185 function InvalidFilter(text, reason) | 
|   207 { |   186 { | 
| (...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   876  |   855  | 
|   877 /** |   856 /** | 
|   878  * Creates an element hiding filter from a pre-parsed text representation |   857  * Creates an element hiding filter from a pre-parsed text representation | 
|   879  * |   858  * | 
|   880  * @param {String} text         same as in Filter() |   859  * @param {String} text         same as in Filter() | 
|   881  * @param {String} domain       domain part of the text representation (can be e
      mpty) |   860  * @param {String} domain       domain part of the text representation (can be e
      mpty) | 
|   882  * @param {Boolean} isException exception rule indicator |   861  * @param {Boolean} isException exception rule indicator | 
|   883  * @param {String} tagName      tag name part (can be empty) |   862  * @param {String} tagName      tag name part (can be empty) | 
|   884  * @param {String} attrRules    attribute matching rules (can be empty) |   863  * @param {String} attrRules    attribute matching rules (can be empty) | 
|   885  * @param {String} selector     raw CSS selector (can be empty) |   864  * @param {String} selector     raw CSS selector (can be empty) | 
|   886  * @return {ElemHideFilter|ElemHideException|CSSPropertyFilter|InvalidFilter} |   865  * @return {ElemHideFilter|ElemHideException|ElemHideEmulationFilter|InvalidFilt
      er} | 
|   887  */ |   866  */ | 
|   888 ElemHideBase.fromText = function(text, domain, isException, tagName, attrRules, 
      selector) |   867 ElemHideBase.fromText = function(text, domain, isException, tagName, attrRules, 
      selector) | 
|   889 { |   868 { | 
|   890   if (!selector) |   869   if (!selector) | 
|   891   { |   870   { | 
|   892     if (tagName == "*") |   871     if (tagName == "*") | 
|   893       tagName = ""; |   872       tagName = ""; | 
|   894  |   873  | 
|   895     let id = null; |   874     let id = null; | 
|   896     let additional = ""; |   875     let additional = ""; | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
|   926  |   905  | 
|   927   // We don't allow ElemHide filters which have any empty domains. |   906   // We don't allow ElemHide filters which have any empty domains. | 
|   928   // Note: The ElemHide.prototype.domainSeparator is duplicated here, if that |   907   // Note: The ElemHide.prototype.domainSeparator is duplicated here, if that | 
|   929   // changes this must be changed too. |   908   // changes this must be changed too. | 
|   930   if (domain && /(^|,)~?(,|$)/.test(domain)) |   909   if (domain && /(^|,)~?(,|$)/.test(domain)) | 
|   931     return new InvalidFilter(text, "filter_invalid_domain"); |   910     return new InvalidFilter(text, "filter_invalid_domain"); | 
|   932  |   911  | 
|   933   if (isException) |   912   if (isException) | 
|   934     return new ElemHideException(text, domain, selector); |   913     return new ElemHideException(text, domain, selector); | 
|   935  |   914  | 
|   936   let match = Filter.csspropertyRegExp.exec(selector); |   915   if (selector.indexOf("[-abp-properties") != -1) | 
|   937   if (match) |  | 
|   938   { |   916   { | 
|   939     // CSS property filters are inefficient so we need to make sure that |   917     // Element hiding emulation filters are inefficient so we need to make sure | 
|   940     // they're only applied if they specify active domains |   918     // that they're only applied if they specify active domains | 
|   941     if (!/,[^~][^,.]*\.[^,]/.test("," + domain)) |   919     if (!/,[^~][^,.]*\.[^,]/.test("," + domain)) | 
|   942       return new InvalidFilter(text, "filter_cssproperty_nodomain"); |   920       return new InvalidFilter(text, "filter_elemhideemulation_nodomain"); | 
|   943  |   921  | 
|   944     return new CSSPropertyFilter(text, domain, selector, match[2], |   922     return new ElemHideEmulationFilter(text, domain, selector); | 
|   945       selector.substr(0, match.index), |  | 
|   946       selector.substr(match.index + match[0].length)); |  | 
|   947   } |   923   } | 
|   948  |   924  | 
|   949   return new ElemHideFilter(text, domain, selector); |   925   return new ElemHideFilter(text, domain, selector); | 
|   950 }; |   926 }; | 
|   951  |   927  | 
|   952 /** |   928 /** | 
|   953  * Class for element hiding filters |   929  * Class for element hiding filters | 
|   954  * @param {String} text see Filter() |   930  * @param {String} text see Filter() | 
|   955  * @param {String} domains  see ElemHideBase() |   931  * @param {String} domains  see ElemHideBase() | 
|   956  * @param {String} selector see ElemHideBase() |   932  * @param {String} selector see ElemHideBase() | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
|   979 { |   955 { | 
|   980   ElemHideBase.call(this, text, domains, selector); |   956   ElemHideBase.call(this, text, domains, selector); | 
|   981 } |   957 } | 
|   982 exports.ElemHideException = ElemHideException; |   958 exports.ElemHideException = ElemHideException; | 
|   983  |   959  | 
|   984 ElemHideException.prototype = extend(ElemHideBase, { |   960 ElemHideException.prototype = extend(ElemHideBase, { | 
|   985   type: "elemhideexception" |   961   type: "elemhideexception" | 
|   986 }); |   962 }); | 
|   987  |   963  | 
|   988 /** |   964 /** | 
|   989  * Class for CSS property filters |   965  * Class for element hiding emulation filters | 
|   990  * @param {String} text           see Filter() |   966  * @param {String} text           see Filter() | 
|   991  * @param {String} domains        see ElemHideBase() |   967  * @param {String} domains        see ElemHideBase() | 
|   992  * @param {String} selector       see ElemHideBase() |   968  * @param {String} selector       see ElemHideBase() | 
|   993  * @param {String} regexpSource   see CSSPropertyFilter.regexpSource |  | 
|   994  * @param {String} selectorPrefix see CSSPropertyFilter.selectorPrefix |  | 
|   995  * @param {String} selectorSuffix see CSSPropertyFilter.selectorSuffix |  | 
|   996  * @constructor |   969  * @constructor | 
|   997  * @augments ElemHideBase |   970  * @augments ElemHideBase | 
|   998  */ |   971  */ | 
|   999 function CSSPropertyFilter(text, domains, selector, regexpSource, |   972 function ElemHideEmulationFilter(text, domains, selector) | 
|  1000   selectorPrefix, selectorSuffix) |  | 
|  1001 { |   973 { | 
|  1002   ElemHideBase.call(this, text, domains, selector); |   974   ElemHideBase.call(this, text, domains, selector); | 
 |   975 } | 
 |   976 exports.ElemHideEmulationFilter = ElemHideEmulationFilter; | 
|  1003  |   977  | 
|  1004   this.regexpSource = regexpSource; |   978 ElemHideEmulationFilter.prototype = extend(ElemHideBase, { | 
|  1005   this.selectorPrefix = selectorPrefix; |   979   type: "elemhideemulation" | 
|  1006   this.selectorSuffix = selectorSuffix; |  | 
|  1007 } |  | 
|  1008 exports.CSSPropertyFilter = CSSPropertyFilter; |  | 
|  1009  |  | 
|  1010 CSSPropertyFilter.prototype = extend(ElemHideBase, { |  | 
|  1011   type: "cssproperty", |  | 
|  1012  |  | 
|  1013   /** |  | 
|  1014    * Expression from which a regular expression should be generated for matching |  | 
|  1015    * CSS properties - for delayed creation of the regexpString property |  | 
|  1016    * @type String |  | 
|  1017    */ |  | 
|  1018   regexpSource: null, |  | 
|  1019   /** |  | 
|  1020    * Substring of CSS selector before properties for the HTML elements that |  | 
|  1021    * should be hidden |  | 
|  1022    * @type String |  | 
|  1023    */ |  | 
|  1024   selectorPrefix: null, |  | 
|  1025   /** |  | 
|  1026    * Substring of CSS selector after properties for the HTML elements that |  | 
|  1027    * should be hidden |  | 
|  1028    * @type String |  | 
|  1029    */ |  | 
|  1030   selectorSuffix: null, |  | 
|  1031  |  | 
|  1032   /** |  | 
|  1033    * Raw regular expression string to be used when testing CSS properties |  | 
|  1034    * against this filter |  | 
|  1035    * @type String |  | 
|  1036    */ |  | 
|  1037   get regexpString() |  | 
|  1038   { |  | 
|  1039     // Despite this property being cached, the getter is called |  | 
|  1040     // several times on Safari, due to WebKit bug 132872 |  | 
|  1041     let prop = Object.getOwnPropertyDescriptor(this, "regexpString"); |  | 
|  1042     if (prop) |  | 
|  1043       return prop.value; |  | 
|  1044  |  | 
|  1045     let regexp; |  | 
|  1046     if (this.regexpSource.length >= 2 && this.regexpSource[0] == "/" && |  | 
|  1047         this.regexpSource[this.regexpSource.length - 1] == "/") |  | 
|  1048       regexp = this.regexpSource.slice(1, -1); |  | 
|  1049     else |  | 
|  1050       regexp = Filter.toRegExp(this.regexpSource); |  | 
|  1051     Object.defineProperty(this, "regexpString", {value: regexp}); |  | 
|  1052     return regexp; |  | 
|  1053   } |  | 
|  1054 }); |   980 }); | 
| OLD | NEW |