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 |