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 #include "PluginStdAfx.h" | 18 #include "PluginStdAfx.h" |
19 #include "AdblockPlusClient.h" | 19 #include "AdblockPlusClient.h" |
20 #include "PluginFilter.h" | 20 #include "PluginFilter.h" |
21 #include "PluginSettings.h" | 21 #include "PluginSettings.h" |
22 #include "PluginMutex.h" | 22 #include "PluginMutex.h" |
23 #include "PluginSettings.h" | 23 #include "PluginSettings.h" |
24 #include "PluginSystem.h" | 24 #include "PluginSystem.h" |
25 #include "PluginClass.h" | 25 #include "PluginClass.h" |
| 26 #include "PluginUtil.h" |
26 #include "mlang.h" | 27 #include "mlang.h" |
| 28 #include "TokenSequence.h" |
27 #include "..\shared\CriticalSection.h" | 29 #include "..\shared\CriticalSection.h" |
28 #include "..\shared\Utils.h" | 30 #include "..\shared\Utils.h" |
29 #include "..\shared\MsHTMLUtils.h" | 31 #include "..\shared\MsHTMLUtils.h" |
30 | 32 |
31 // The filters are described at http://adblockplus.org/en/filters | 33 // The filters are described at http://adblockplus.org/en/filters |
32 | 34 |
33 static CriticalSection s_criticalSectionFilterMap; | 35 static CriticalSection s_criticalSectionFilterMap; |
34 | 36 |
35 // ============================================================================ | 37 // ============================================================================ |
36 // CFilterElementHideAttrSelector | |
37 // ============================================================================ | |
38 | |
39 CFilterElementHideAttrSelector::CFilterElementHideAttrSelector() : m_type(TYPE_N
ONE), m_pos(POS_NONE), m_bstrAttr(NULL) | |
40 { | |
41 } | |
42 | |
43 CFilterElementHideAttrSelector::CFilterElementHideAttrSelector(const CFilterElem
entHideAttrSelector& filter) | |
44 { | |
45 m_type = filter.m_type; | |
46 m_pos = filter.m_pos; | |
47 m_bstrAttr = filter.m_bstrAttr; | |
48 | |
49 m_value = filter.m_value; | |
50 } | |
51 | |
52 CFilterElementHideAttrSelector::~CFilterElementHideAttrSelector() | |
53 { | |
54 } | |
55 | |
56 | |
57 // ============================================================================ | |
58 // CFilterElementHide | 38 // CFilterElementHide |
59 // ============================================================================ | 39 // ============================================================================ |
| 40 namespace |
| 41 { |
| 42 class ElementHideParseException |
| 43 : public std::runtime_error |
| 44 { |
| 45 std::string message(const std::wstring& filterText, const std::string& reaso
n) |
| 46 { |
| 47 std::string s( |
| 48 "CFilterElementHide::CFilterElementHide, error parsing selector \"" |
| 49 + ToUtf8String(filterText) + "\" (" + reason + ")" |
| 50 ); |
| 51 DEBUG_FILTER(ToUtf16String(s)); |
| 52 return s; |
| 53 } |
| 54 public: |
| 55 ElementHideParseException(const std::wstring& filterText, const std::string&
reason) |
| 56 : std::runtime_error(message(filterText, reason)) |
| 57 {} |
| 58 }; |
| 59 } |
60 | 60 |
61 CFilterElementHide::CFilterElementHide(const CString& filterText) : m_filterText
(filterText), m_type(ETraverserComplexType::TRAVERSER_TYPE_ERROR) | 61 CFilterElementHide::CFilterElementHide(const std::wstring& filterText) |
| 62 : m_filterText(filterText), m_type(ETraverserComplexType::TRAVERSER_TYPE_ERROR
) |
62 { | 63 { |
| 64 std::wstring filterSuffix(filterText); // The unparsed remainder of the input
filter text |
| 65 |
63 // Find tag name, class or any (*) | 66 // Find tag name, class or any (*) |
64 CString filterString = filterText; | 67 wchar_t firstTag = filterText[0]; |
65 | |
66 wchar_t firstTag = filterString.GetAt(0); | |
67 // Any tag | |
68 if (firstTag == '*') | 68 if (firstTag == '*') |
69 { | 69 { |
70 filterString = filterString.Mid(1); | 70 // Any tag |
| 71 filterSuffix = filterSuffix.substr(1); |
71 } | 72 } |
72 // Any tag (implicitely) | |
73 else if (firstTag == '[' || firstTag == '.' || firstTag == '#') | 73 else if (firstTag == '[' || firstTag == '.' || firstTag == '#') |
74 { | 74 { |
| 75 // Any tag (implicitly) |
75 } | 76 } |
76 // Real tag | |
77 else if (isalnum(firstTag)) | 77 else if (isalnum(firstTag)) |
78 { | 78 { |
79 //TODO: Add support for descendant selectors | 79 // Real tag |
80 int pos = filterString.FindOneOf(L".#[("); | 80 //TODO: Add support for descendant selectors |
81 | 81 auto pos = filterSuffix.find_first_of(L".#[("); |
82 if (pos < 0) | 82 if (pos == std::wstring::npos) |
83 pos = filterString.GetLength(); | 83 { |
84 m_tag = filterString.Left(pos).MakeLower(); | 84 pos = filterSuffix.length(); |
85 | 85 } |
86 filterString = filterString.Mid(pos); | 86 m_tag = ToLowerString(filterSuffix.substr(0, pos)); |
| 87 filterSuffix = filterSuffix.substr(pos); |
87 } | 88 } |
88 // Error | |
89 else | 89 else |
90 { | 90 { |
91 DEBUG_FILTER("Filter::Error parsing selector:" + filterText + " (invalid tag
)"); | 91 // Error |
92 throw std::runtime_error(CStringA("Filter::Error parsing selector:" + filter
Text + " (invalid tag)").GetString()); | 92 throw ElementHideParseException(filterText, "invalid tag"); |
93 } | 93 } |
94 | 94 |
95 // Find Id and class name | 95 // Find Id and class name |
96 | 96 if (!filterSuffix.empty()) |
97 if (!filterString.IsEmpty()) | |
98 { | 97 { |
99 wchar_t firstId = filterString.GetAt(0); | 98 wchar_t firstId = filterSuffix[0]; |
100 | 99 |
101 // Id | 100 // Id |
102 if (firstId == '#') | 101 if (firstId == '#') |
103 { | 102 { |
104 int pos = filterString.Find('['); | 103 auto pos = filterSuffix.find('['); |
105 if (pos < 0) | 104 if (pos == std::wstring::npos) |
106 { | 105 { |
107 pos = filterString.GetLength(); | 106 pos = filterSuffix.length(); |
108 } | 107 } |
109 m_tagId = filterString.Mid(1, pos - 1); | 108 m_tagId = filterSuffix.substr(1, pos - 1); |
110 filterString = filterString.Mid(pos); | 109 filterSuffix = filterSuffix.substr(pos); |
111 pos = m_tagId.Find(L"."); | 110 pos = m_tagId.find(L"."); |
112 if (pos > 0) | 111 if (pos != std::wstring::npos) |
113 { | 112 { |
114 m_tagClassName = m_tagId.Mid(pos + 1); | 113 if (pos == 0) |
115 m_tagId = m_tagId.Left(pos); | 114 { |
| 115 throw ElementHideParseException(filterText, "empty tag id"); |
| 116 } |
| 117 m_tagClassName = m_tagId.substr(pos + 1); |
| 118 m_tagId = m_tagId.substr(0, pos); |
116 } | 119 } |
117 } | 120 } |
118 // Class name | 121 // Class name |
119 else if (firstId == '.') | 122 else if (firstId == '.') |
120 { | 123 { |
121 int pos = filterString.Find('['); | 124 auto pos = filterSuffix.find('['); |
122 if (pos < 0) | 125 if (pos == std::wstring::npos) |
123 { | 126 { |
124 pos = filterString.GetLength(); | 127 pos = filterSuffix.length(); |
125 } | 128 } |
126 m_tagClassName = filterString.Mid(1, pos - 1); | 129 m_tagClassName = filterSuffix.substr(1, pos - 1); |
127 filterString = filterString.Mid(pos); | 130 filterSuffix = filterSuffix.substr(pos); |
128 } | 131 } |
129 } | 132 } |
130 | 133 |
131 char chAttrStart = '['; | 134 while (!filterSuffix.empty()) |
132 char chAttrEnd = ']'; | 135 { |
| 136 if (filterSuffix[0] != '[') |
| 137 { |
| 138 throw ElementHideParseException(filterText, "expected '['"); |
| 139 } |
| 140 auto endPos = filterSuffix.find(']') ; |
| 141 if (endPos == std::wstring::npos) |
| 142 { |
| 143 throw ElementHideParseException(filterText, "expected ']'"); |
| 144 } |
| 145 std::wstring arg = filterSuffix.substr(1, endPos - 1); |
| 146 filterSuffix = filterSuffix.substr(endPos + 1); |
133 | 147 |
134 while (!filterString.IsEmpty()) | 148 CFilterElementHideAttrSelector attrSelector; |
135 { | 149 auto posEquals = arg.find('='); |
136 if (filterString.GetAt(0) != chAttrStart) | 150 if (posEquals != std::wstring::npos) |
137 { | 151 { |
138 DEBUG_FILTER("Filter::Error parsing selector:" + filterText + " (more data
)"); | 152 if (posEquals == 0) |
139 throw std::runtime_error(CStringA("Filter::Error parsing selector:" + filt
erText + " (more data)").GetString()); | |
140 } | |
141 int endPos = filterString.Find(']') ; | |
142 if (endPos < 0) | |
143 { | |
144 DEBUG_FILTER("Filter::Error parsing selector:" + filterText + " (more data
)"); | |
145 throw std::runtime_error(CStringA("Filter::Error parsing selector:" + filt
erText + " (more data)").GetString()); | |
146 } | |
147 | |
148 CFilterElementHideAttrSelector attrSelector; | |
149 | |
150 CString arg = filterString.Mid(1, endPos - 1); | |
151 filterString = filterString.Mid(endPos + 1); | |
152 | |
153 int delimiterPos = arg.Find('='); | |
154 if (delimiterPos > 0) | |
155 { | |
156 attrSelector.m_value = arg.Mid(delimiterPos + 1); | |
157 if (attrSelector.m_value.GetLength() >= 2 && attrSelector.m_value.GetAt(0)
== '\"' && attrSelector.m_value.GetAt(attrSelector.m_value.GetLength() - 1) ==
'\"') | |
158 { | 153 { |
159 attrSelector.m_value = attrSelector.m_value.Mid(1, attrSelector.m_value.
GetLength() - 2); | 154 throw ElementHideParseException(filterText, "empty attribute name before
'='"); |
| 155 } |
| 156 attrSelector.m_value = arg.substr(posEquals + 1); |
| 157 if (attrSelector.m_value.length() >= 2 && attrSelector.m_value[0] == '\"'
&& attrSelector.m_value[attrSelector.m_value.length() - 1] == '\"') |
| 158 { |
| 159 attrSelector.m_value = attrSelector.m_value.substr(1, attrSelector.m_val
ue.length() - 2); |
160 } | 160 } |
161 | 161 |
162 if (arg.GetAt(delimiterPos - 1) == '^') | 162 if (arg[posEquals - 1] == '^') |
163 { | 163 { |
164 attrSelector.m_bstrAttr = arg.Left(delimiterPos - 1); | |
165 attrSelector.m_pos = CFilterElementHideAttrPos::STARTING; | 164 attrSelector.m_pos = CFilterElementHideAttrPos::STARTING; |
166 } | 165 } |
167 else if (arg.GetAt(delimiterPos - 1) == '*') | 166 else if (arg[posEquals - 1] == '*') |
168 { | 167 { |
169 attrSelector.m_bstrAttr = arg.Left(delimiterPos - 1); | |
170 attrSelector.m_pos = CFilterElementHideAttrPos::ANYWHERE; | 168 attrSelector.m_pos = CFilterElementHideAttrPos::ANYWHERE; |
171 } | 169 } |
172 else if (arg.GetAt(delimiterPos - 1) == '$') | 170 else if (arg[posEquals - 1] == '$') |
173 { | 171 { |
174 attrSelector.m_bstrAttr = arg.Left(delimiterPos - 1); | |
175 attrSelector.m_pos = CFilterElementHideAttrPos::ENDING; | 172 attrSelector.m_pos = CFilterElementHideAttrPos::ENDING; |
176 } | 173 } |
| 174 if (attrSelector.m_pos != CFilterElementHideAttrPos::POS_NONE) |
| 175 { |
| 176 if (posEquals == 1) |
| 177 { |
| 178 throw ElementHideParseException(filterText, "empty attribute name befo
re " + std::string(1, static_cast<char>(arg[0])) + "'='"); |
| 179 } |
| 180 attrSelector.m_attr = arg.substr(0, posEquals - 1); |
| 181 } |
177 else | 182 else |
178 { | 183 { |
179 attrSelector.m_bstrAttr = arg.Left(delimiterPos); | |
180 attrSelector.m_pos = CFilterElementHideAttrPos::EXACT; | 184 attrSelector.m_pos = CFilterElementHideAttrPos::EXACT; |
| 185 attrSelector.m_attr = arg.substr(0, posEquals); |
181 } | 186 } |
182 } | 187 } |
183 CString tag = attrSelector.m_bstrAttr; | 188 |
184 if (tag == "style") | 189 if (attrSelector.m_attr == L"style") |
185 { | 190 { |
186 attrSelector.m_type = CFilterElementHideAttrType::STYLE; | 191 attrSelector.m_type = CFilterElementHideAttrType::STYLE; |
187 attrSelector.m_value.MakeLower(); | 192 attrSelector.m_value = ToLowerString(attrSelector.m_value); |
188 } | 193 } |
189 else if (tag == "id") | 194 else if (attrSelector.m_attr == L"id") |
190 { | 195 { |
191 attrSelector.m_type = CFilterElementHideAttrType::ID; | 196 attrSelector.m_type = CFilterElementHideAttrType::ID; |
192 } | 197 } |
193 else if (tag == "class") | 198 else if (attrSelector.m_attr == L"class") |
194 { | 199 { |
195 attrSelector.m_type = CFilterElementHideAttrType::CLASS; | 200 attrSelector.m_type = CFilterElementHideAttrType::CLASS; |
196 } | 201 } |
197 m_attributeSelectors.push_back(attrSelector); | 202 m_attributeSelectors.push_back(attrSelector); |
198 | |
199 } | 203 } |
200 | 204 |
201 // End check | 205 // End check |
202 if (!filterString.IsEmpty()) | 206 if (!filterSuffix.empty()) |
203 { | 207 { |
204 DEBUG_FILTER("Filter::Error parsing selector:" + filterFile + "/" + filterTe
xt + " (more data)") | 208 throw ElementHideParseException(filterText, "extra characters at end"); |
205 throw new std::runtime_error(CStringA("Filter::Error parsing selector:" + f
ilterText + " (more data)").GetString()); | |
206 } | 209 } |
207 } | 210 } |
208 | 211 |
209 CFilterElementHide::CFilterElementHide(const CFilterElementHide& filter) | 212 CFilterElementHide::CFilterElementHide(const CFilterElementHide& filter) |
210 { | 213 { |
211 m_filterText = filter.m_filterText; | 214 m_filterText = filter.m_filterText; |
212 | 215 |
213 m_tagId = filter.m_tagId; | 216 m_tagId = filter.m_tagId; |
214 m_tagClassName = filter.m_tagClassName; | 217 m_tagClassName = filter.m_tagClassName; |
215 | 218 |
(...skipping 27 matching lines...) Expand all Loading... |
243 CFilter::CFilter() : m_isMatchCase(false), m_isFirstParty(false), | 246 CFilter::CFilter() : m_isMatchCase(false), m_isFirstParty(false), |
244 m_isThirdParty(false), | 247 m_isThirdParty(false), |
245 m_isFromStart(false), m_isFromEnd(false), m_hitCount(0) | 248 m_isFromStart(false), m_isFromEnd(false), m_hitCount(0) |
246 { | 249 { |
247 } | 250 } |
248 | 251 |
249 | 252 |
250 bool CFilterElementHide::IsMatchFilterElementHide(IHTMLElement* pEl) const | 253 bool CFilterElementHide::IsMatchFilterElementHide(IHTMLElement* pEl) const |
251 { | 254 { |
252 HRESULT hr; | 255 HRESULT hr; |
253 | 256 /* |
254 if (!m_tagId.IsEmpty()) | 257 * If a tag id is specified, it must match |
| 258 */ |
| 259 if (!m_tagId.empty()) |
255 { | 260 { |
256 CComBSTR id; | 261 CComBSTR idBstr; |
257 hr = pEl->get_id(&id); | 262 if (FAILED(pEl->get_id(&idBstr)) || !idBstr || m_tagId != ToWstring(idBstr)) |
258 if ((hr != S_OK) || (id != CComBSTR(m_tagId))) | |
259 { | 263 { |
260 return false; | 264 return false; |
261 } | 265 } |
262 } | 266 } |
263 if (!m_tagClassName.IsEmpty()) | 267 /* |
| 268 * If a class name is specified, it must match |
| 269 */ |
| 270 if (!m_tagClassName.empty()) |
264 { | 271 { |
265 CComBSTR classNameBSTR; | 272 CComBSTR classNameListBstr; |
266 hr = pEl->get_className(&classNameBSTR); | 273 hr = pEl->get_className(&classNameListBstr); |
267 if (hr == S_OK) | 274 if (FAILED(hr) || !classNameListBstr) |
268 { | 275 { |
269 CString className = classNameBSTR; | 276 return false; // We can't match a class name if there's no class name |
270 int start = 0; | 277 } |
271 CString specificClass; | 278 std::wstring classNameList(ToWstring(classNameListBstr)); |
272 bool foundMatch = false; | 279 if (classNameList.empty()) |
273 while ((specificClass = className.Tokenize(L" ", start)) != L"") | 280 { |
| 281 return false; |
| 282 } |
| 283 // TODO: Consider case of multiple classes. (m_tagClassName can be something
like "foo.bar") |
| 284 /* |
| 285 * Match when 'm_tagClassName' appears as a token within classNameList |
| 286 */ |
| 287 bool foundMatch = false; |
| 288 TokenSequence<std::wstring> ts(classNameList, L" "); |
| 289 for (auto iterClassName = ts.cbegin(); iterClassName != ts.cend(); ++iterCla
ssName) |
| 290 { |
| 291 if (*iterClassName == m_tagClassName) |
274 { | 292 { |
275 // TODO: Consider case of multiple classes. (m_tagClassName can be somet
hing like "foo.bar") | 293 foundMatch = true; |
276 if (specificClass == m_tagClassName) | 294 break; |
277 { | |
278 foundMatch = true; | |
279 } | |
280 } | |
281 if (!foundMatch) | |
282 { | |
283 return false; | |
284 } | 295 } |
285 } | 296 } |
286 } | 297 if (!foundMatch) |
287 if (!m_tag.IsEmpty()) | |
288 { | |
289 CComBSTR tagName; | |
290 hr = pEl->get_tagName(&tagName); | |
291 tagName.ToLower(); | |
292 if ((hr != S_OK) || (tagName != CComBSTR(m_tag))) | |
293 { | 298 { |
294 return false; | 299 return false; |
295 } | 300 } |
296 } | 301 } |
297 | 302 /* |
298 // Check attributes | 303 * If a tag name is specified, it must match |
299 for (std::vector<CFilterElementHideAttrSelector>::const_iterator attrIt = m_at
tributeSelectors.begin(); | 304 */ |
300 attrIt != m_attributeSelectors.end(); ++ attrIt) | 305 if (!m_tag.empty()) |
301 { | 306 { |
302 ATL::CString value; | 307 CComBSTR tagNameBstr; |
| 308 if (FAILED(pEl->get_tagName(&tagNameBstr)) || !tagNameBstr) |
| 309 { |
| 310 return false; |
| 311 } |
| 312 if (m_tag != ToLowerString(ToWstring(tagNameBstr))) |
| 313 { |
| 314 return false; |
| 315 } |
| 316 } |
| 317 /* |
| 318 * Match each attribute |
| 319 */ |
| 320 for (auto attrIt = m_attributeSelectors.begin(); attrIt != m_attributeSelector
s.end(); ++attrIt) |
| 321 { |
| 322 std::wstring value; |
303 bool attrFound = false; | 323 bool attrFound = false; |
304 if (attrIt->m_type == CFilterElementHideAttrType::STYLE) | 324 if (attrIt->m_type == CFilterElementHideAttrType::STYLE) |
305 { | 325 { |
306 CComPtr<IHTMLStyle> pStyle; | 326 CComPtr<IHTMLStyle> pStyle; |
307 if (SUCCEEDED(pEl->get_style(&pStyle)) && pStyle) | 327 if (SUCCEEDED(pEl->get_style(&pStyle)) && pStyle) |
308 { | 328 { |
309 CComBSTR bstrStyle; | 329 CComBSTR styleBstr; |
310 | 330 if (SUCCEEDED(pStyle->get_cssText(&styleBstr)) && styleBstr) |
311 if (SUCCEEDED(pStyle->get_cssText(&bstrStyle)) && bstrStyle) | |
312 { | 331 { |
313 value = bstrStyle; | 332 value = ToLowerString(ToWstring(styleBstr)); |
314 value.MakeLower(); | |
315 attrFound = true; | 333 attrFound = true; |
316 } | 334 } |
317 } | 335 } |
318 } | 336 } |
319 else if (attrIt->m_type == CFilterElementHideAttrType::CLASS) | 337 else if (attrIt->m_type == CFilterElementHideAttrType::CLASS) |
320 { | 338 { |
321 CComBSTR bstrClassNames; | 339 CComBSTR classNamesBstr; |
322 if (SUCCEEDED(pEl->get_className(&bstrClassNames)) && bstrClassNames) | 340 if (SUCCEEDED(pEl->get_className(&classNamesBstr)) && classNamesBstr) |
323 { | 341 { |
324 value = bstrClassNames; | 342 value = ToWstring(classNamesBstr); |
325 attrFound = true; | 343 attrFound = true; |
326 } | 344 } |
327 } | 345 } |
328 else if (attrIt->m_type == CFilterElementHideAttrType::ID) | 346 else if (attrIt->m_type == CFilterElementHideAttrType::ID) |
329 { | 347 { |
330 CComBSTR bstrId; | 348 CComBSTR idBstr; |
331 if (SUCCEEDED(pEl->get_id(&bstrId)) && bstrId) | 349 if (SUCCEEDED(pEl->get_id(&idBstr)) && idBstr) |
332 { | 350 { |
333 value = bstrId; | 351 value = ToWstring(idBstr); |
334 attrFound = true; | 352 attrFound = true; |
335 } | 353 } |
336 } | 354 } |
337 else | 355 else |
338 { | 356 { |
339 auto attributeValue = GetHtmlElementAttribute(*pEl, attrIt->m_bstrAttr); | 357 CComBSTR attrArgument(attrIt->m_attr.length(), attrIt->m_attr.c_str()); |
340 if (attrFound = attributeValue.isAttributeFound) | 358 auto x = GetHtmlElementAttribute(*pEl, attrArgument); |
| 359 attrFound = x.isAttributeFound; |
| 360 if (attrFound) |
341 { | 361 { |
342 value = ToCString(attributeValue.attributeValue); | 362 value = x.attributeValue; |
343 } | 363 } |
344 } | 364 } |
345 | 365 |
346 if (attrFound) | 366 if (attrFound) |
347 { | 367 { |
348 if (attrIt->m_pos == CFilterElementHideAttrPos::EXACT) | 368 if (attrIt->m_pos == CFilterElementHideAttrPos::EXACT) |
349 { | 369 { |
350 // TODO: IE rearranges the style attribute completely. Figure out if any
thing can be done about it. | 370 // TODO: IE rearranges the style attribute completely. Figure out if any
thing can be done about it. |
351 if (value != attrIt->m_value) | 371 if (value != attrIt->m_value) |
352 return false; | 372 return false; |
353 } | 373 } |
354 else if (attrIt->m_pos == CFilterElementHideAttrPos::STARTING) | 374 else if (attrIt->m_pos == CFilterElementHideAttrPos::STARTING) |
355 { | 375 { |
356 if (value.Left(attrIt->m_value.GetLength()) != attrIt->m_value) | 376 if (value.compare(0, attrIt->m_value.length(), attrIt->m_value) != 0) |
357 return false; | 377 return false; |
358 } | 378 } |
359 else if (attrIt->m_pos == CFilterElementHideAttrPos::ENDING) | 379 else if (attrIt->m_pos == CFilterElementHideAttrPos::ENDING) |
360 { | 380 { |
361 if (value.Right(attrIt->m_value.GetLength()) != attrIt->m_value) | 381 size_t valueLength = value.length(); |
| 382 size_t attrLength = attrIt->m_value.length(); |
| 383 if (valueLength < attrLength) |
| 384 return false; |
| 385 if (value.compare(valueLength - attrLength, attrLength, attrIt->m_value)
!= 0) |
362 return false; | 386 return false; |
363 } | 387 } |
364 else if (attrIt->m_pos == CFilterElementHideAttrPos::ANYWHERE) | 388 else if (attrIt->m_pos == CFilterElementHideAttrPos::ANYWHERE) |
365 { | 389 { |
366 if (value.Find(attrIt->m_value) < 0) | 390 if (value.find(attrIt->m_value) == std::wstring::npos) |
367 return false; | 391 return false; |
368 } | 392 } |
369 else if (attrIt->m_value.IsEmpty()) | 393 else if (attrIt->m_value.empty()) |
370 { | 394 { |
371 return true; | 395 return true; |
372 } | 396 } |
373 } | 397 } |
374 else | 398 else |
375 { | 399 { |
376 return false; | 400 return false; |
377 } | 401 } |
378 } | 402 } |
379 | 403 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 | 440 |
417 return true; | 441 return true; |
418 } | 442 } |
419 | 443 |
420 | 444 |
421 | 445 |
422 // ============================================================================ | 446 // ============================================================================ |
423 // CPluginFilter | 447 // CPluginFilter |
424 // ============================================================================ | 448 // ============================================================================ |
425 | 449 |
426 CPluginFilter::CPluginFilter(const CString& dataPath) : m_dataPath(dataPath) | 450 CPluginFilter::CPluginFilter(const std::wstring& dataPath) |
| 451 : m_dataPath(dataPath) |
427 { | 452 { |
428 ClearFilters(); | 453 ClearFilters(); |
429 } | 454 } |
430 | 455 |
431 | 456 |
432 bool CPluginFilter::AddFilterElementHide(CString filterText) | 457 bool CPluginFilter::AddFilterElementHide(std::wstring filterText) |
433 { | 458 { |
434 DEBUG_FILTER("Input: " + filterText + " filterFile" + filterFile); | 459 DEBUG_FILTER(L"Input: " + filterText + L" filterFile" + filterFile); |
435 CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); | 460 CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); |
436 { | 461 { |
437 CString filterString = filterText; | |
438 // Create filter descriptor | 462 // Create filter descriptor |
439 std::auto_ptr<CFilterElementHide> filter; | 463 std::auto_ptr<CFilterElementHide> filter; |
440 | |
441 CString wholeFilterString = filterString; | |
442 wchar_t separatorChar; | 464 wchar_t separatorChar; |
443 do | 465 do |
444 { | 466 { |
445 int chunkEnd = filterText.FindOneOf(L"+>"); | 467 auto chunkEnd = filterText.find_first_of(L"+>"); |
446 if (chunkEnd > 0) | 468 if (chunkEnd != std::wstring::npos && chunkEnd > 0) |
447 { | 469 { |
448 separatorChar = filterText.GetAt(chunkEnd); | 470 separatorChar = filterText[chunkEnd]; |
449 } | 471 } |
450 else | 472 else |
451 { | 473 { |
452 chunkEnd = filterText.GetLength(); | 474 chunkEnd = filterText.length(); |
453 separatorChar = L'\0'; | 475 separatorChar = L'\0'; |
454 } | 476 } |
455 | 477 |
456 CString filterChunk = filterText.Left(chunkEnd).TrimRight(); | |
457 std::auto_ptr<CFilterElementHide> filterParent(filter); | 478 std::auto_ptr<CFilterElementHide> filterParent(filter); |
458 | 479 filter.reset(new CFilterElementHide(TrimStringRight(filterText.substr(0, c
hunkEnd)))); |
459 filter.reset(new CFilterElementHide(filterChunk)); | |
460 | |
461 if (filterParent.get() != 0) | 480 if (filterParent.get() != 0) |
462 { | 481 { |
463 filter->m_predecessor.reset(filterParent.release()); | 482 filter->m_predecessor.reset(filterParent.release()); |
464 } | 483 } |
465 | 484 |
466 if (separatorChar != L'\0') // complex selector | 485 if (separatorChar != L'\0') // complex selector |
467 { | 486 { |
468 filterText = filterText.Mid(chunkEnd + 1).TrimLeft(); | 487 filterText = TrimStringLeft(filterText.substr(chunkEnd + 1)); |
469 if (separatorChar == '+') | 488 if (separatorChar == '+') |
470 filter->m_type = CFilterElementHide::TRAVERSER_TYPE_IMMEDIATE; | 489 filter->m_type = CFilterElementHide::TRAVERSER_TYPE_IMMEDIATE; |
471 else if (separatorChar == '>') | 490 else if (separatorChar == '>') |
472 filter->m_type = CFilterElementHide::TRAVERSER_TYPE_PARENT; | 491 filter->m_type = CFilterElementHide::TRAVERSER_TYPE_PARENT; |
473 } | 492 } |
474 else // Terminating element (simple selector) | 493 else // Terminating element (simple selector) |
475 { | 494 { |
476 if (!filter->m_tagId.IsEmpty()) | 495 if (!filter->m_tagId.empty()) |
477 { | 496 { |
478 m_elementHideTagsId.insert(std::make_pair(std::make_pair(filter->m_tag
, filter->m_tagId), *filter)); | 497 m_elementHideTagsId.insert(std::make_pair(std::make_pair(filter->m_tag
, filter->m_tagId), *filter)); |
479 } | 498 } |
480 else if (!filter->m_tagClassName.IsEmpty()) | 499 else if (!filter->m_tagClassName.empty()) |
481 { | 500 { |
482 m_elementHideTagsClass.insert(std::make_pair(std::make_pair(filter->m_
tag, filter->m_tagClassName), *filter)); | 501 m_elementHideTagsClass.insert(std::make_pair(std::make_pair(filter->m_
tag, filter->m_tagClassName), *filter)); |
483 } | 502 } |
484 else | 503 else |
485 { | 504 { |
486 std::pair<CString, CFilterElementHide> pair = std::make_pair(filter->m
_tag, *filter); | 505 m_elementHideTags.insert(std::make_pair(filter->m_tag, *filter)); |
487 m_elementHideTags.insert(pair); | |
488 } | 506 } |
489 } | 507 } |
490 } while (separatorChar != '\0'); | 508 } while (separatorChar != '\0'); |
491 } | 509 } |
492 | 510 |
493 return true; | 511 return true; |
494 } | 512 } |
495 | 513 |
496 bool CPluginFilter::IsElementHidden(const std::wstring& tag, IHTMLElement* pEl,
const std::wstring& domain, const std::wstring& indent) const | 514 bool CPluginFilter::IsElementHidden(const std::wstring& tag, IHTMLElement* pEl,
const std::wstring& domain, const std::wstring& indent) const |
497 { | 515 { |
498 CString tagCString = ToCString(tag); | 516 std::wstring id; |
499 | 517 CComBSTR idBstr; |
500 CString id; | 518 if (SUCCEEDED(pEl->get_id(&idBstr)) && idBstr) |
501 CComBSTR bstrId; | |
502 if (SUCCEEDED(pEl->get_id(&bstrId)) && bstrId) | |
503 { | 519 { |
504 id = bstrId; | 520 id = ToWstring(idBstr); |
505 } | 521 } |
506 | 522 std::wstring classNames; |
507 CString classNames; | 523 CComBSTR classNamesBstr; |
508 CComBSTR bstrClassNames; | 524 if (SUCCEEDED(pEl->get_className(&classNamesBstr)) && classNamesBstr) |
509 if (SUCCEEDED(pEl->get_className(&bstrClassNames)) && bstrClassNames) | |
510 { | 525 { |
511 classNames = bstrClassNames; | 526 classNames = ToWstring(classNamesBstr); |
512 } | 527 } |
513 | 528 |
514 CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); | 529 CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); |
515 { | 530 { |
516 // Search tag/id filters | 531 // Search tag/id filters |
517 if (!id.IsEmpty()) | 532 if (!id.empty()) |
518 { | 533 { |
519 std::pair<TFilterElementHideTagsNamed::const_iterator, TFilterElementHideT
agsNamed::const_iterator> idItEnum = | 534 auto idItEnum = m_elementHideTagsId.equal_range(std::make_pair(tag, id)); |
520 m_elementHideTagsId.equal_range(std::make_pair(tagCString, id)); | 535 for (auto idIt = idItEnum.first; idIt != idItEnum.second; ++idIt) |
521 for (TFilterElementHideTagsNamed::const_iterator idIt = idItEnum.first; id
It != idItEnum.second; idIt ++) | |
522 { | 536 { |
523 if (idIt->second.IsMatchFilterElementHide(pEl)) | 537 if (idIt->second.IsMatchFilterElementHide(pEl)) |
524 { | 538 { |
525 #ifdef ENABLE_DEBUG_RESULT | 539 #ifdef ENABLE_DEBUG_RESULT |
526 DEBUG_HIDE_EL(indent + "HideEl::Found (tag/id) filter:" + idIt->second
.m_filterText) | 540 DEBUG_HIDE_EL(indent + L"HideEl::Found (tag/id) filter:" + idIt->secon
d.m_filterText); |
527 CPluginDebug::DebugResultHiding(tag, L"id:" + ToWstring(id), ToWstri
ng(idIt->second.m_filterText)); | 541 CPluginDebug::DebugResultHiding(tag, L"id:" + id, idIt->second.m_filte
rText); |
528 #endif | 542 #endif |
529 return true; | 543 return true; |
530 } | 544 } |
531 } | 545 } |
532 | 546 |
533 // Search general id | 547 // Search general id |
534 idItEnum = m_elementHideTagsId.equal_range(std::make_pair("", id)); | 548 idItEnum = m_elementHideTagsId.equal_range(std::make_pair(L"", id)); |
535 for (TFilterElementHideTagsNamed::const_iterator idIt = idItEnum.first; id
It != idItEnum.second; idIt ++) | 549 for (auto idIt = idItEnum.first; idIt != idItEnum.second; ++idIt) |
536 { | 550 { |
537 if (idIt->second.IsMatchFilterElementHide(pEl)) | 551 if (idIt->second.IsMatchFilterElementHide(pEl)) |
538 { | 552 { |
539 #ifdef ENABLE_DEBUG_RESULT | 553 #ifdef ENABLE_DEBUG_RESULT |
540 DEBUG_HIDE_EL(indent + "HideEl::Found (?/id) filter:" + idIt->second.m
_filterText) | 554 DEBUG_HIDE_EL(indent + L"HideEl::Found (?/id) filter:" + idIt->second.
m_filterText); |
541 CPluginDebug::DebugResultHiding(tag, L"id:" + ToWstring(id), ToWstri
ng(idIt->second.m_filterText)); | 555 CPluginDebug::DebugResultHiding(tag, L"id:" + id, idIt->second.m_filte
rText); |
542 #endif | 556 #endif |
543 return true; | 557 return true; |
544 } | 558 } |
545 } | 559 } |
546 } | 560 } |
547 | 561 |
548 // Search tag/className filters | 562 // Search tag/className filters |
549 if (!classNames.IsEmpty()) | 563 if (!classNames.empty()) |
550 { | 564 { |
551 int pos = 0; | 565 TokenSequence<std::wstring> ts(classNames, L" \t\n\r"); |
552 CString className = classNames.Tokenize(L" \t\n\r", pos); | 566 for (auto iterClassName = ts.cbegin(); iterClassName != ts.cend(); ++iterC
lassName) |
553 while (pos >= 0) | |
554 { | 567 { |
555 std::pair<TFilterElementHideTagsNamed::const_iterator, TFilterElementHid
eTagsNamed::const_iterator> classItEnum = | 568 std::wstring className = *iterClassName; |
556 m_elementHideTagsClass.equal_range(std::make_pair(tagCString, classNam
e)); | 569 auto classItEnum = m_elementHideTagsClass.equal_range(std::make_pair(tag
, className)); |
557 | 570 for (auto classIt = classItEnum.first; classIt != classItEnum.second; ++
classIt) |
558 for (TFilterElementHideTagsNamed::const_iterator classIt = classItEnum.f
irst; classIt != classItEnum.second; ++classIt) | |
559 { | 571 { |
560 if (classIt->second.IsMatchFilterElementHide(pEl)) | 572 if (classIt->second.IsMatchFilterElementHide(pEl)) |
561 { | 573 { |
562 #ifdef ENABLE_DEBUG_RESULT | 574 #ifdef ENABLE_DEBUG_RESULT |
563 DEBUG_HIDE_EL(indent + "HideEl::Found (tag/class) filter:" + classIt
->second.m_filterText) | 575 DEBUG_HIDE_EL(indent + L"HideEl::Found (tag/class) filter:" + classI
t->second.m_filterText); |
564 CPluginDebug::DebugResultHiding(tag, L"class:" + ToWstring(classNa
me), ToWstring(classIt->second.m_filterText)); | 576 CPluginDebug::DebugResultHiding(tag, L"class:" + className, classIt-
>second.m_filterText); |
565 #endif | 577 #endif |
566 return true; | 578 return true; |
567 } | 579 } |
568 } | 580 } |
569 | 581 |
570 // Search general class name | 582 // Search general class name |
571 classItEnum = m_elementHideTagsClass.equal_range(std::make_pair("", clas
sName)); | 583 classItEnum = m_elementHideTagsClass.equal_range(std::make_pair(L"", cla
ssName)); |
572 for (TFilterElementHideTagsNamed::const_iterator classIt = classItEnum.f
irst; classIt != classItEnum.second; ++ classIt) | 584 for (auto classIt = classItEnum.first; classIt != classItEnum.second; ++
classIt) |
573 { | 585 { |
574 if (classIt->second.IsMatchFilterElementHide(pEl)) | 586 if (classIt->second.IsMatchFilterElementHide(pEl)) |
575 { | 587 { |
576 #ifdef ENABLE_DEBUG_RESULT | 588 #ifdef ENABLE_DEBUG_RESULT |
577 DEBUG_HIDE_EL(indent + L"HideEl::Found (?/class) filter:" + ToWStrin
g(classIt->second.m_filterText)); | 589 DEBUG_HIDE_EL(indent + L"HideEl::Found (?/class) filter:" + classIt-
>second.m_filterText); |
578 CPluginDebug::DebugResultHiding(tag, L"class:" + ToWstring(className
), ToWstring(classIt->second.m_filterText)); | 590 CPluginDebug::DebugResultHiding(tag, L"class:" + className, classIt-
>second.m_filterText); |
579 #endif | 591 #endif |
580 return true; | 592 return true; |
581 } | 593 } |
582 } | 594 } |
583 | |
584 // Next class name | |
585 className = classNames.Tokenize(L" \t\n\r", pos); | |
586 } | 595 } |
587 } | 596 } |
588 | 597 |
589 // Search tag filters | 598 // Search tag filters |
590 std::pair<TFilterElementHideTags::const_iterator, TFilterElementHideTags::co
nst_iterator> tagItEnum | 599 auto tagItEnum = m_elementHideTags.equal_range(tag); |
591 = m_elementHideTags.equal_range(tagCString); | 600 for (auto tagIt = tagItEnum.first; tagIt != tagItEnum.second; ++tagIt) |
592 for (TFilterElementHideTags::const_iterator tagIt = tagItEnum.first; tagIt !
= tagItEnum.second; ++ tagIt) | |
593 { | 601 { |
594 if (tagIt->second.IsMatchFilterElementHide(pEl)) | 602 if (tagIt->second.IsMatchFilterElementHide(pEl)) |
595 { | 603 { |
596 #ifdef ENABLE_DEBUG_RESULT | 604 #ifdef ENABLE_DEBUG_RESULT |
597 DEBUG_HIDE_EL(indent + "HideEl::Found (tag) filter:" + tagIt->second.m_f
ilterText) | 605 DEBUG_HIDE_EL(indent + L"HideEl::Found (tag) filter:" + tagIt->second.m_
filterText); |
598 CPluginDebug::DebugResultHiding(tag, L"-", ToWstring(tagIt->second.m_f
ilterText)); | 606 CPluginDebug::DebugResultHiding(tag, L"-", tagIt->second.m_filterText); |
599 #endif | 607 #endif |
600 return true; | 608 return true; |
601 } | 609 } |
602 } | 610 } |
603 } | 611 } |
604 | 612 |
605 return false; | 613 return false; |
606 } | 614 } |
607 | 615 |
608 bool CPluginFilter::LoadHideFilters(std::vector<std::wstring> filters) | 616 bool CPluginFilter::LoadHideFilters(std::vector<std::wstring> filters) |
609 { | 617 { |
610 ClearFilters(); | 618 ClearFilters(); |
611 bool isRead = false; | 619 bool isRead = false; |
612 CPluginClient* client = CPluginClient::GetInstance(); | 620 CPluginClient* client = CPluginClient::GetInstance(); |
613 | 621 |
614 // Parse hide string | 622 // Parse hide string |
615 int pos = 0; | 623 int pos = 0; |
616 CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); | 624 CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); |
617 { | 625 { |
618 for (std::vector<std::wstring>::iterator it = filters.begin(); it < filters.
end(); ++it) | 626 for (auto it = filters.begin(); it < filters.end(); ++it) |
619 { | 627 { |
620 CString filter((*it).c_str()); | 628 std::wstring filter(TrimString(*it)); |
621 // If the line is not commented out | 629 // If the line is not commented out |
622 if (!filter.Trim().IsEmpty() && filter.GetAt(0) != '!' && filter.GetAt(0)
!= '[') | 630 if (!filter.empty() && filter[0] != '!' && filter[0] != '[') |
623 { | 631 { |
624 int filterType = 0; | 632 int filterType = 0; |
625 | 633 |
626 // See http://adblockplus.org/en/filters for further documentation | 634 // See http://adblockplus.org/en/filters for further documentation |
627 | 635 |
628 try | 636 try |
629 { | 637 { |
630 AddFilterElementHide(filter); | 638 AddFilterElementHide(filter); |
631 } | 639 } |
632 catch(...) | 640 catch(...) |
633 { | 641 { |
634 #ifdef ENABLE_DEBUG_RESULT | 642 #ifdef ENABLE_DEBUG_RESULT |
635 CPluginDebug::DebugResult(L"Error loading hide filter: " + ToWstring(f
ilter)); | 643 CPluginDebug::DebugResult(L"Error loading hide filter: " + filter); |
636 #endif | 644 #endif |
637 } | 645 } |
638 } | 646 } |
639 } | 647 } |
640 } | 648 } |
641 | 649 |
642 return isRead; | 650 return isRead; |
643 } | 651 } |
644 | 652 |
645 void CPluginFilter::ClearFilters() | 653 void CPluginFilter::ClearFilters() |
(...skipping 30 matching lines...) Expand all Loading... |
676 CPluginDebug::DebugResultBlocking(type, srcTrimmed, domain); | 684 CPluginDebug::DebugResultBlocking(type, srcTrimmed, domain); |
677 } | 685 } |
678 else | 686 else |
679 { | 687 { |
680 CPluginDebug::DebugResultIgnoring(type, srcTrimmed, domain); | 688 CPluginDebug::DebugResultIgnoring(type, srcTrimmed, domain); |
681 } | 689 } |
682 } | 690 } |
683 #endif | 691 #endif |
684 return result; | 692 return result; |
685 } | 693 } |
OLD | NEW |