Left: | ||
Right: |
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 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
45 else | 45 else |
46 text[pos - delta] = text[pos]; | 46 text[pos - delta] = text[pos]; |
47 } | 47 } |
48 selectorStart -= delta; | 48 selectorStart -= delta; |
49 | 49 |
50 text.reset(text, 0, len - delta); | 50 text.reset(text, 0, len - delta); |
51 } | 51 } |
52 } | 52 } |
53 | 53 |
54 ElemHideBase::ElemHideBase(Type type, const String& text, const ElemHideData& da ta) | 54 ElemHideBase::ElemHideBase(Type type, const String& text, const ElemHideData& da ta) |
55 : ActiveFilter(type, text, false), mData(data) | 55 : ActiveFilter(type, text, false), |
56 mData(data) | |
56 { | 57 { |
57 if (mData.HasDomains()) | 58 if (mData.HasDomains()) |
58 ParseDomains(mData.GetDomainsSource(mText), u','); | 59 ParseDomains(mData.GetDomainsSource(mText), u','); |
59 } | 60 } |
60 | 61 |
61 Filter::Type ElemHideBase::Parse(DependentString& text, ElemHideData& data) | 62 Filter::Type ElemHideBase::Parse(DependentString& text, ElemHideData& data) |
62 { | 63 { |
63 StringScanner scanner(text); | 64 StringScanner scanner(text); |
64 | 65 |
65 // Domains part | 66 // Domains part |
(...skipping 16 matching lines...) Expand all Loading... | |
82 case u'"': | 83 case u'"': |
83 case u'!': | 84 case u'!': |
84 return Type::UNKNOWN; | 85 return Type::UNKNOWN; |
85 case u' ': | 86 case u' ': |
86 seenSpaces = true; | 87 seenSpaces = true; |
87 break; | 88 break; |
88 } | 89 } |
89 } | 90 } |
90 | 91 |
91 seenSpaces |= scanner.skip(u' '); | 92 seenSpaces |= scanner.skip(u' '); |
93 bool emulation = false; | |
92 bool exception = scanner.skipOne(u'@'); | 94 bool exception = scanner.skipOne(u'@'); |
93 if (exception) | 95 if (exception) |
94 seenSpaces |= scanner.skip(u' '); | 96 seenSpaces |= scanner.skip(u' '); |
97 else | |
98 emulation = scanner.skipOne(u'?'); | |
95 | 99 |
96 String::value_type next = scanner.next(); | 100 String::value_type next = scanner.next(); |
97 if (next != u'#') | 101 if (next != u'#') |
98 return Type::UNKNOWN; | 102 return Type::UNKNOWN; |
99 | 103 |
100 // Selector part | 104 // Selector part |
101 | 105 |
102 // Selector shouldn't be empty | 106 // Selector shouldn't be empty |
103 seenSpaces |= scanner.skip(u' '); | 107 seenSpaces |= scanner.skip(u' '); |
104 if (scanner.done()) | 108 if (scanner.done()) |
105 return Type::UNKNOWN; | 109 return Type::UNKNOWN; |
106 | 110 |
107 data.mSelectorStart = scanner.position() + 1; | 111 data.mSelectorStart = scanner.position() + 1; |
112 data.mNeedConversion = false; | |
108 | 113 |
109 // We are done validating, now we can normalize whitespace and the domain part | 114 // We are done validating, now we can normalize whitespace and the domain part |
110 if (seenSpaces) | 115 if (seenSpaces) |
111 NormalizeWhitespace(text, data.mDomainsEnd, data.mSelectorStart); | 116 NormalizeWhitespace(text, data.mDomainsEnd, data.mSelectorStart); |
112 DependentString(text, 0, data.mDomainsEnd).toLower(); | 117 DependentString(text, 0, data.mDomainsEnd).toLower(); |
113 | 118 |
119 // We still need to check the old syntax. It will be converted when | |
120 // we instantiate the filter. | |
121 if (!emulation && | |
122 text.find(u"[-abp-properties="_str, data.mSelectorStart) != text.npos) | |
123 { | |
124 data.mNeedConversion = true; | |
125 emulation = !exception; | |
sergei
2018/02/05 14:51:04
Should it be an invalid filter if it's exception w
hub
2018/02/07 04:13:35
no. This is actually how exceptions for element hi
| |
126 } | |
127 | |
114 if (exception) | 128 if (exception) |
115 return Type::ELEMHIDEEXCEPTION; | 129 return Type::ELEMHIDEEXCEPTION; |
116 | 130 |
117 if (text.find(u"[-abp-properties="_str, data.mSelectorStart) != text.npos) | 131 if (emulation) |
118 return Type::ELEMHIDEEMULATION; | 132 return Type::ELEMHIDEEMULATION; |
119 | 133 |
120 return Type::ELEMHIDE; | 134 return Type::ELEMHIDE; |
121 } | 135 } |
122 | 136 |
137 // Convert filter from the old syntax to the new. | |
138 OwnedString ElemHideBase::ConvertFilter(const String& text, String::size_type& a t) | |
139 { | |
140 static const auto propsSelector = u"[-abp-properties="_str; | |
141 static const auto newPropsSelector = u":-abp-properties("_str; | |
142 static const auto elemHideDelimiter = u"##"_str; | |
143 auto selectorPos = text.find(propsSelector, at); | |
144 if (selectorPos != text.npos) | |
145 { | |
146 auto length = text.length(); | |
147 auto properties = selectorPos + propsSelector.length(); | |
148 String::value_type quote = 0; | |
149 bool escape = false; | |
150 String::size_type removed = 0; // how many chars we remove | |
151 String::size_type end = properties; | |
152 String::size_type quote_start = 0; | |
153 String::size_type quote_end = 0; | |
154 for (auto index = properties; | |
155 index < length && end == properties; index++) | |
156 { | |
157 if (escape) | |
158 { | |
159 escape = false; | |
160 continue; | |
161 } | |
162 | |
163 auto c = text[index]; | |
164 switch (c) | |
165 { | |
166 case '\\': | |
167 escape = true; | |
168 break; | |
169 case '"': | |
170 case '\'': | |
171 if (quote == 0) | |
172 { | |
173 quote = c; | |
174 quote_start = index + 1; | |
175 } | |
176 else if (quote == c) | |
177 { | |
178 // end of quoted. | |
179 quote = 0; | |
180 removed += 2; | |
181 quote_end = index; | |
182 } | |
183 break; | |
184 case ']': | |
185 if (quote == 0) | |
186 end = index + 1; // end of properties (after ]) | |
187 break; | |
188 default: | |
189 break; | |
190 } | |
191 } | |
192 | |
193 if (quote != 0) | |
194 quote_end = end - 1; | |
195 else if (quote_end <= quote_start) | |
196 { | |
197 // we likely didn't find a quoted content so we just take it as is. | |
198 quote_start = properties; | |
199 quote_end = end - 1; | |
200 } | |
201 | |
202 // +1 for the replacement of "##" by "#?#" | |
203 String::size_type offset = 0; | |
204 | |
205 String::size_type delimiter = text.find(elemHideDelimiter); | |
206 OwnedString converted(length + ((delimiter != text.npos) ? 1 : 0) - removed) ; | |
207 if (delimiter != text.npos) | |
208 { | |
209 if (delimiter >= selectorPos) | |
210 return OwnedString(text); | |
211 | |
212 at++; | |
213 std::memcpy(converted.data(), text.data(), | |
214 delimiter * sizeof(String::value_type)); | |
215 offset += delimiter; | |
216 std::memcpy(converted.data() + offset, u"#?#", | |
217 3 * sizeof(String::value_type)); | |
218 offset += 3; | |
219 delimiter += 2; | |
220 // we have already parsed to past the delimiter. | |
221 selectorPos -= delimiter; | |
222 } | |
223 else | |
224 delimiter = 0; | |
225 | |
226 | |
227 std::memcpy(converted.data() + offset, text.data() + delimiter, | |
228 selectorPos * sizeof(String::value_type)); | |
229 offset += selectorPos; | |
230 | |
231 std::memcpy(converted.data() + offset, newPropsSelector.data(), | |
232 newPropsSelector.length() * sizeof(String::value_type)); | |
233 offset += newPropsSelector.length(); | |
234 | |
235 std::memcpy(converted.data() + offset, text.data() + quote_start, | |
236 (quote_end - quote_start) * sizeof(String::value_type)); | |
237 offset += quote_end - quote_start; | |
238 | |
239 std::memcpy(converted.data() + offset, u")", sizeof(String::value_type)); | |
240 offset++; | |
241 | |
242 std::memcpy(converted.data() + offset, text.data() + end, | |
243 (length - end) * sizeof(String::value_type)); | |
244 offset += (length - end) * sizeof(String::value_type); | |
245 | |
246 return converted; | |
247 } | |
248 | |
249 return OwnedString(text); | |
250 } | |
251 | |
123 namespace | 252 namespace |
124 { | 253 { |
125 static constexpr String::value_type OPENING_CURLY_REPLACEMENT[] = u"\\7B "; | 254 static constexpr String::value_type OPENING_CURLY_REPLACEMENT[] = u"\\7B "; |
126 static constexpr String::value_type CLOSING_CURLY_REPLACEMENT[] = u"\\7D "; | 255 static constexpr String::value_type CLOSING_CURLY_REPLACEMENT[] = u"\\7D "; |
127 static constexpr String::size_type CURLY_REPLACEMENT_SIZE = sizeof(OPENING_CUR LY_REPLACEMENT) / sizeof(OPENING_CURLY_REPLACEMENT[0]) - 1; | 256 static constexpr String::size_type CURLY_REPLACEMENT_SIZE = sizeof(OPENING_CUR LY_REPLACEMENT) / sizeof(OPENING_CURLY_REPLACEMENT[0]) - 1; |
128 | 257 |
129 OwnedString EscapeCurlies(String::size_type replacementCount, | 258 OwnedString EscapeCurlies(String::size_type replacementCount, |
130 const DependentString& str) | 259 const DependentString& str) |
131 { | 260 { |
132 OwnedString result(str.length() + replacementCount * (CURLY_REPLACEMENT_SIZE - 1)); | 261 OwnedString result(str.length() + replacementCount * (CURLY_REPLACEMENT_SIZE - 1)); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
181 if (item.second && !item.first.empty()) | 310 if (item.second && !item.first.empty()) |
182 { | 311 { |
183 if (!result.empty()) | 312 if (!result.empty()) |
184 result.append(u','); | 313 result.append(u','); |
185 result.append(item.first); | 314 result.append(item.first); |
186 } | 315 } |
187 } | 316 } |
188 } | 317 } |
189 return result; | 318 return result; |
190 } | 319 } |
OLD | NEW |