| 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-2015 Eyeo GmbH | 3  * Copyright (C) 2006-2015 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 /** @module filterValidation */ | 18 /** @module filterValidation */ | 
| 19 | 19 | 
| 20 let {Filter, InvalidFilter, ElemHideBase} = require("filterClasses"); | 20 let {Filter, InvalidFilter, ElemHideBase} = require("filterClasses"); | 
| 21 | 21 | 
|  | 22 function isValidCSSSelector(selector) | 
|  | 23 { | 
|  | 24   let style = document.createElement("style"); | 
|  | 25   document.documentElement.appendChild(style); | 
|  | 26   let sheet = style.sheet; | 
|  | 27   document.documentElement.removeChild(style); | 
|  | 28 | 
|  | 29   try | 
|  | 30   { | 
|  | 31     document.querySelector(selector); | 
|  | 32     sheet.insertRule(selector + "{}", 0); | 
|  | 33   } | 
|  | 34   catch (e) | 
|  | 35   { | 
|  | 36     return false; | 
|  | 37   } | 
|  | 38   return true; | 
|  | 39 } | 
|  | 40 | 
|  | 41 /** | 
|  | 42  * @typedef ParsedFilter | 
|  | 43  * @property {?Filter} [filter]  The parsed filter if it is valid. Or null if | 
|  | 44  *                               the given string is empty or a filter list head
     er. | 
|  | 45  * @property {string} [error]    An error message indicated that the filter cann
     ot | 
|  | 46  *                               be parsed or contains an invalid CSS selector. | 
|  | 47  */ | 
|  | 48 | 
|  | 49 let parseFilter = | 
| 22 /** | 50 /** | 
| 23  * Parses and validates a filter given by the user. | 51  * Parses and validates a filter given by the user. | 
| 24  * | 52  * | 
| 25  * @param {string}  text | 53  * @param {string}  text | 
| 26  * @param {Boolean} [ignoreHeaders=false]  If true, no exception is raised | 54  * @param {Boolean} [ignoreHeaders=false]  If true, {filter: null} is | 
| 27  *                                         for filter list headers, instead | 55                                            returned instead an error | 
| 28  *                                         the function will return null. | 56                                            for filter list headers. | 
| 29  * @return {Filter} | 57  * @return {ParsedFilter} | 
| 30  * @throws Will throw an exception if filter cannot be |  | 
| 31  *         parsed or contains an invalid CSS selector. |  | 
| 32  * @static |  | 
| 33  */ | 58  */ | 
| 34 function parseFilter(text, ignoreHeaders) | 59 exports.parseFilter = function(text, ignoreHeaders) | 
| 35 { | 60 { | 
|  | 61   let filter = null; | 
| 36   text = Filter.normalize(text); | 62   text = Filter.normalize(text); | 
| 37   if (!text) |  | 
| 38     return null; |  | 
| 39 | 63 | 
| 40   if (text[0] == "[") | 64   if (text) | 
| 41   { | 65   { | 
| 42     if (ignoreHeaders) | 66     if (text[0] != "[") | 
| 43       return null; | 67     { | 
|  | 68       filter = Filter.fromText(text); | 
| 44 | 69 | 
| 45     throw ext.i18n.getMessage("unexpected_filter_list_header"); | 70       if (filter instanceof InvalidFilter) | 
| 46   } | 71         return {error: filter.reason}; | 
| 47 | 72 | 
| 48   let filter = Filter.fromText(text); | 73       if (filter instanceof ElemHideBase && !isValidCSSSelector(filter.selector)
     ) | 
| 49 | 74         return {error: ext.i18n.getMessage("invalid_css_selector", "'" + filter.
     selector + "'")}; | 
| 50   if (filter instanceof InvalidFilter) | 75     } | 
| 51     throw filter.reason; | 76     else if (!ignoreHeaders) | 
| 52 |  | 
| 53   if (filter instanceof ElemHideBase) |  | 
| 54   { |  | 
| 55     let style = document.createElement("style"); |  | 
| 56     document.documentElement.appendChild(style); |  | 
| 57     let sheet = style.sheet; |  | 
| 58     document.documentElement.removeChild(style); |  | 
| 59 |  | 
| 60     try |  | 
| 61     { | 77     { | 
| 62       document.querySelector(filter.selector); | 78       return {error: ext.i18n.getMessage("unexpected_filter_list_header")}; | 
| 63       sheet.insertRule(filter.selector + "{}", 0); |  | 
| 64     } |  | 
| 65     catch (error) |  | 
| 66     { |  | 
| 67       throw ext.i18n.getMessage("invalid_css_selector", "'" + filter.selector + 
     "'"); |  | 
| 68     } | 79     } | 
| 69   } | 80   } | 
| 70 | 81 | 
| 71   return filter; | 82   return {filter: filter}; | 
| 72 } | 83 }; | 
| 73 exports.parseFilter = parseFilter; | 84 | 
|  | 85 /** | 
|  | 86  * @typedef ParsedFilters | 
|  | 87  * @property {Filter[]} [filters]  The parsed filters if all of them are valid. | 
|  | 88  * @property {string} [error]      An error message indicated that any filter ca
     nnot | 
|  | 89  *                                 be parsed or contains an invalid CSS selector
     . | 
|  | 90  */ | 
| 74 | 91 | 
| 75 /** | 92 /** | 
| 76  * Parses and validates a newline-separated list of filters given by the user. | 93  * Parses and validates a newline-separated list of filters given by the user. | 
| 77  * | 94  * | 
| 78  * @param {string}  text | 95  * @param {string}  text | 
| 79  * @param {Boolean} [ignoreHeaders=false]  If true, filter list headers | 96  * @param {Boolean} [ignoreHeaders=false]  If true, filter list headers | 
| 80  *                                         will be stripped instead of | 97  *                                         will be stripped instead of | 
| 81  *                                         raising an exception. | 98  *                                         returning an error. | 
| 82  * @return {Filter[]} | 99  * @return {ParsedFilters} | 
| 83  * @throws Will throw an exception if one of the filters cannot |  | 
| 84            be parsed or contains an invalid CSS selector. |  | 
| 85  */ | 100  */ | 
| 86 exports.parseFilters = function(text, ignoreHeaders) | 101 exports.parseFilters = function(text, ignoreHeaders) | 
| 87 { | 102 { | 
| 88   let lines = text.split("\n"); | 103   let lines = text.split("\n"); | 
| 89   let filters = []; | 104   let filters = []; | 
| 90 | 105 | 
| 91   for (let i = 0; i < lines.length; i++) | 106   for (let i = 0; i < lines.length; i++) | 
| 92   { | 107   { | 
| 93     let filter; | 108     let {filter, error} = parseFilter(lines[i], ignoreHeaders); | 
| 94     try | 109 | 
| 95     { | 110     if (error) | 
| 96       filter = parseFilter(lines[i], ignoreHeaders); | 111       return {error: ext.i18n.getMessage("line", (i + 1).toString()) + ": " + er
     ror}; | 
| 97     } |  | 
| 98     catch (error) |  | 
| 99     { |  | 
| 100       throw ext.i18n.getMessage("line", (i + 1).toString()) + ": " + error; |  | 
| 101     } |  | 
| 102 | 112 | 
| 103     if (filter) | 113     if (filter) | 
| 104       filters.push(filter); | 114       filters.push(filter); | 
| 105   } | 115   } | 
| 106 | 116 | 
| 107   return filters; | 117   return {filters: filters}; | 
| 108 }; | 118 }; | 
| OLD | NEW | 
|---|