| LEFT | RIGHT |
| 1 /* |
| 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
| 3 * Copyright (C) 2006-2015 Eyeo GmbH |
| 4 * |
| 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 |
| 7 * published by the Free Software Foundation. |
| 8 * |
| 9 * Adblock Plus is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 * GNU General Public License for more details. |
| 13 * |
| 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/>. |
| 16 */ |
| 17 |
| 1 #include "PluginStdAfx.h" | 18 #include "PluginStdAfx.h" |
| 2 | 19 |
| 3 #include "PluginFilter.h" | 20 #include "PluginFilter.h" |
| 4 #include "PluginSettings.h" | 21 #include "PluginSettings.h" |
| 5 #include "PluginClient.h" | 22 #include "PluginClient.h" |
| 6 #include "PluginClientFactory.h" | 23 #include "PluginClientFactory.h" |
| 7 #include "PluginMutex.h" | 24 #include "PluginMutex.h" |
| 8 #include "PluginSettings.h" | 25 #include "PluginSettings.h" |
| 9 #include "PluginSystem.h" | 26 #include "PluginSystem.h" |
| 10 #include "PluginClass.h" | 27 #include "PluginClass.h" |
| 11 #include "mlang.h" | 28 #include "mlang.h" |
| 12 | 29 |
| 13 #include "..\shared\CriticalSection.h" | 30 #include "..\shared\CriticalSection.h" |
| 14 #include "..\shared\Utils.h" | 31 #include "..\shared\Utils.h" |
| 15 #include "..\shared\ContentType.h" | |
| 16 | |
| 17 | 32 |
| 18 // The filters are described at http://adblockplus.org/en/filters | 33 // The filters are described at http://adblockplus.org/en/filters |
| 19 | 34 |
| 20 static CriticalSection s_criticalSectionFilterMap; | 35 static CriticalSection s_criticalSectionFilterMap; |
| 21 | 36 |
| 22 namespace | 37 namespace |
| 23 { | 38 { |
| 24 struct GetHtmlElementAttributeResult | 39 struct GetHtmlElementAttributeResult |
| 25 { | 40 { |
| 26 GetHtmlElementAttributeResult() : isAttributeFound(false) | 41 GetHtmlElementAttributeResult() : isAttributeFound(false) |
| 27 { | 42 { |
| 28 } | 43 } |
| 29 std::wstring attributeValue; | 44 std::wstring attributeValue; |
| 30 bool isAttributeFound; | 45 bool isAttributeFound; |
| 31 }; | 46 }; |
| 32 | 47 |
| 33 bool GetHtmlElementAttribute(IHTMLElement* htmlElement, | 48 GetHtmlElementAttributeResult GetHtmlElementAttribute(IHTMLElement& htmlElemen
t, |
| 34 const ATL::CComBSTR& attributeName, GetHtmlElementAttributeResult& retValue) | 49 const ATL::CComBSTR& attributeName) |
| 35 { | 50 { |
| 36 if (!htmlElement) | 51 GetHtmlElementAttributeResult retValue; |
| 37 { | |
| 38 return false; | |
| 39 } | |
| 40 ATL::CComVariant vAttr; | 52 ATL::CComVariant vAttr; |
| 41 ATL::CComPtr<IHTMLElement4> htmlElement4; | 53 ATL::CComPtr<IHTMLElement4> htmlElement4; |
| 42 if (FAILED(htmlElement->QueryInterface(&htmlElement4)) || !htmlElement4) | 54 if (FAILED(htmlElement.QueryInterface(&htmlElement4)) || !htmlElement4) |
| 43 { | 55 { |
| 44 return false; | 56 return retValue; |
| 45 } | 57 } |
| 46 ATL::CComPtr<IHTMLDOMAttribute> attributeNode; | 58 ATL::CComPtr<IHTMLDOMAttribute> attributeNode; |
| 47 if (FAILED(htmlElement4->getAttributeNode(attributeName, &attributeNode)) ||
!attributeNode) | 59 if (FAILED(htmlElement4->getAttributeNode(attributeName, &attributeNode)) ||
!attributeNode) |
| 48 { | 60 { |
| 49 return false; | 61 return retValue; |
| 50 } | 62 } |
| 51 // we set that attribute found but it's not necessary that we can retrieve i
ts value | 63 // we set that attribute found but it's not necessary that we can retrieve i
ts value |
| 52 retValue.isAttributeFound = true; | 64 retValue.isAttributeFound = true; |
| 53 if (FAILED(attributeNode->get_nodeValue(&vAttr))) | 65 if (FAILED(attributeNode->get_nodeValue(&vAttr))) |
| 54 { | 66 { |
| 55 return false; | 67 return retValue; |
| 56 } | 68 } |
| 57 if (vAttr.vt == VT_BSTR && vAttr.bstrVal) | 69 if (vAttr.vt == VT_BSTR && vAttr.bstrVal) |
| 58 { | 70 { |
| 59 retValue.attributeValue = vAttr.bstrVal; | 71 retValue.attributeValue = vAttr.bstrVal; |
| 60 } | 72 } |
| 61 else if (vAttr.vt == VT_I4) | 73 else if (vAttr.vt == VT_I4) |
| 62 { | 74 { |
| 63 retValue.attributeValue = std::to_wstring(vAttr.iVal); | 75 retValue.attributeValue = std::to_wstring(vAttr.iVal); |
| 64 } | 76 } |
| 65 return true; | 77 return retValue; |
| 66 } | 78 } |
| 67 } | 79 } |
| 68 | 80 |
| 69 // ============================================================================ | 81 // ============================================================================ |
| 70 // CFilterElementHideAttrSelector | 82 // CFilterElementHideAttrSelector |
| 71 // ============================================================================ | 83 // ============================================================================ |
| 72 | 84 |
| 73 CFilterElementHideAttrSelector::CFilterElementHideAttrSelector() : m_type(TYPE_N
ONE), m_pos(POS_NONE), m_bstrAttr(NULL) | 85 CFilterElementHideAttrSelector::CFilterElementHideAttrSelector() : m_type(TYPE_N
ONE), m_pos(POS_NONE), m_bstrAttr(NULL) |
| 74 { | 86 { |
| 75 } | 87 } |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 m_predecessor = filter.m_predecessor; | 264 m_predecessor = filter.m_predecessor; |
| 253 } | 265 } |
| 254 | 266 |
| 255 | 267 |
| 256 // ============================================================================ | 268 // ============================================================================ |
| 257 // CFilter | 269 // CFilter |
| 258 // ============================================================================ | 270 // ============================================================================ |
| 259 | 271 |
| 260 CFilter::CFilter(const CFilter& filter) | 272 CFilter::CFilter(const CFilter& filter) |
| 261 { | 273 { |
| 262 m_contentType = filter.m_contentType; | |
| 263 m_filterType = filter.m_filterType; | 274 m_filterType = filter.m_filterType; |
| 264 | 275 |
| 265 m_isFirstParty = filter.m_isFirstParty; | 276 m_isFirstParty = filter.m_isFirstParty; |
| 266 m_isThirdParty = filter.m_isThirdParty; | 277 m_isThirdParty = filter.m_isThirdParty; |
| 267 | 278 |
| 268 m_isMatchCase = filter.m_isMatchCase; | 279 m_isMatchCase = filter.m_isMatchCase; |
| 269 m_isFromStart = filter.m_isFromStart; | 280 m_isFromStart = filter.m_isFromStart; |
| 270 m_isFromEnd = filter.m_isFromEnd; | 281 m_isFromEnd = filter.m_isFromEnd; |
| 271 | 282 |
| 272 m_filterText = filter.m_filterText; | 283 m_filterText = filter.m_filterText; |
| 273 | 284 |
| 274 m_hitCount = filter.m_hitCount; | 285 m_hitCount = filter.m_hitCount; |
| 275 } | 286 } |
| 276 | 287 |
| 277 | 288 |
| 278 CFilter::CFilter() : m_isMatchCase(false), m_isFirstParty(false), | 289 CFilter::CFilter() : m_isMatchCase(false), m_isFirstParty(false), |
| 279 m_isThirdParty(false), m_contentType(AdblockPlus::FilterEngine::ContentType::C
ONTENT_TYPE_OTHER), | 290 m_isThirdParty(false), |
| 280 m_isFromStart(false), m_isFromEnd(false), m_hitCount(0) | 291 m_isFromStart(false), m_isFromEnd(false), m_hitCount(0) |
| 281 { | 292 { |
| 282 } | 293 } |
| 283 | 294 |
| 284 | 295 |
| 285 bool CFilterElementHide::IsMatchFilterElementHide(IHTMLElement* pEl) const | 296 bool CFilterElementHide::IsMatchFilterElementHide(IHTMLElement* pEl) const |
| 286 { | 297 { |
| 287 HRESULT hr; | 298 HRESULT hr; |
| 288 | 299 |
| 289 if (!m_tagId.IsEmpty()) | 300 if (!m_tagId.IsEmpty()) |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 { | 375 { |
| 365 CComBSTR bstrId; | 376 CComBSTR bstrId; |
| 366 if (SUCCEEDED(pEl->get_id(&bstrId)) && bstrId) | 377 if (SUCCEEDED(pEl->get_id(&bstrId)) && bstrId) |
| 367 { | 378 { |
| 368 value = bstrId; | 379 value = bstrId; |
| 369 attrFound = true; | 380 attrFound = true; |
| 370 } | 381 } |
| 371 } | 382 } |
| 372 else | 383 else |
| 373 { | 384 { |
| 374 GetHtmlElementAttributeResult attributeValue; | 385 auto attributeValue = GetHtmlElementAttribute(*pEl, attrIt->m_bstrAttr); |
| 375 bool rc = GetHtmlElementAttribute(pEl, attrIt->m_bstrAttr, attributeValue)
; | 386 if (attrFound = attributeValue.isAttributeFound) |
| 376 if (rc && (attrFound = attributeValue.isAttributeFound)) | |
| 377 { | 387 { |
| 378 value = ToCString(attributeValue.attributeValue); | 388 value = ToCString(attributeValue.attributeValue); |
| 379 } | 389 } |
| 380 } | 390 } |
| 381 | 391 |
| 382 if (attrFound) | 392 if (attrFound) |
| 383 { | 393 { |
| 384 if (attrIt->m_pos == CFilterElementHideAttrPos::EXACT) | 394 if (attrIt->m_pos == CFilterElementHideAttrPos::EXACT) |
| 385 { | 395 { |
| 386 // TODO: IE rearranges the style attribute completely. Figure out if any
thing can be done about it. | 396 // TODO: IE rearranges the style attribute completely. Figure out if any
thing can be done about it. |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 } | 534 } |
| 525 } | 535 } |
| 526 } while (separatorChar != '\0'); | 536 } while (separatorChar != '\0'); |
| 527 } | 537 } |
| 528 | 538 |
| 529 return true; | 539 return true; |
| 530 } | 540 } |
| 531 | 541 |
| 532 bool CPluginFilter::IsElementHidden(const std::wstring& tag, IHTMLElement* pEl,
const std::wstring& domain, const std::wstring& indent) const | 542 bool CPluginFilter::IsElementHidden(const std::wstring& tag, IHTMLElement* pEl,
const std::wstring& domain, const std::wstring& indent) const |
| 533 { | 543 { |
| 534 CString tagCString = to_CString(tag); | 544 CString tagCString = ToCString(tag); |
| 535 | 545 |
| 536 CString id; | 546 CString id; |
| 537 CComBSTR bstrId; | 547 CComBSTR bstrId; |
| 538 if (SUCCEEDED(pEl->get_id(&bstrId)) && bstrId) | 548 if (SUCCEEDED(pEl->get_id(&bstrId)) && bstrId) |
| 539 { | 549 { |
| 540 id = bstrId; | 550 id = bstrId; |
| 541 } | 551 } |
| 542 | 552 |
| 543 CString classNames; | 553 CString classNames; |
| 544 CComBSTR bstrClassNames; | 554 CComBSTR bstrClassNames; |
| 545 if (SUCCEEDED(pEl->get_className(&bstrClassNames)) && bstrClassNames) | 555 if (SUCCEEDED(pEl->get_className(&bstrClassNames)) && bstrClassNames) |
| 546 { | 556 { |
| 547 classNames = bstrClassNames; | 557 classNames = bstrClassNames; |
| 548 } | 558 } |
| 549 | 559 |
| 550 CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); | 560 CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); |
| 551 { | 561 { |
| 552 // Search tag/id filters | 562 // Search tag/id filters |
| 553 if (!id.IsEmpty()) | 563 if (!id.IsEmpty()) |
| 554 { | 564 { |
| 555 std::pair<TFilterElementHideTagsNamed::const_iterator, TFilterElementHideT
agsNamed::const_iterator> idItEnum = | 565 std::pair<TFilterElementHideTagsNamed::const_iterator, TFilterElementHideT
agsNamed::const_iterator> idItEnum = |
| 556 m_elementHideTagsId.equal_range(std::make_pair(tagCString, id)); | 566 m_elementHideTagsId.equal_range(std::make_pair(tagCString, id)); |
| 557 for (TFilterElementHideTagsNamed::const_iterator idIt = idItEnum.first; id
It != idItEnum.second; idIt ++) | 567 for (TFilterElementHideTagsNamed::const_iterator idIt = idItEnum.first; id
It != idItEnum.second; idIt ++) |
| 558 { | 568 { |
| 559 if (idIt->second.IsMatchFilterElementHide(pEl)) | 569 if (idIt->second.IsMatchFilterElementHide(pEl)) |
| 560 { | 570 { |
| 561 #ifdef ENABLE_DEBUG_RESULT | 571 #ifdef ENABLE_DEBUG_RESULT |
| 562 DEBUG_HIDE_EL(indent + "HideEl::Found (tag/id) filter:" + idIt->second
.m_filterText) | 572 DEBUG_HIDE_EL(indent + "HideEl::Found (tag/id) filter:" + idIt->second
.m_filterText) |
| 563 CPluginDebug::DebugResultHiding(tagCString, "id:" + id, idIt->second
.m_filterText); | 573 CPluginDebug::DebugResultHiding(tagCString, L"id:" + id, idIt->secon
d.m_filterText); |
| 564 #endif | 574 #endif |
| 565 return true; | 575 return true; |
| 566 } | 576 } |
| 567 } | 577 } |
| 568 | 578 |
| 569 // Search general id | 579 // Search general id |
| 570 idItEnum = m_elementHideTagsId.equal_range(std::make_pair("", id)); | 580 idItEnum = m_elementHideTagsId.equal_range(std::make_pair("", id)); |
| 571 for (TFilterElementHideTagsNamed::const_iterator idIt = idItEnum.first; id
It != idItEnum.second; idIt ++) | 581 for (TFilterElementHideTagsNamed::const_iterator idIt = idItEnum.first; id
It != idItEnum.second; idIt ++) |
| 572 { | 582 { |
| 573 if (idIt->second.IsMatchFilterElementHide(pEl)) | 583 if (idIt->second.IsMatchFilterElementHide(pEl)) |
| 574 { | 584 { |
| 575 #ifdef ENABLE_DEBUG_RESULT | 585 #ifdef ENABLE_DEBUG_RESULT |
| 576 DEBUG_HIDE_EL(indent + "HideEl::Found (?/id) filter:" + idIt->second.m
_filterText) | 586 DEBUG_HIDE_EL(indent + "HideEl::Found (?/id) filter:" + idIt->second.m
_filterText) |
| 577 CPluginDebug::DebugResultHiding(tagCString, "id:" + id, idIt->second
.m_filterText); | 587 CPluginDebug::DebugResultHiding(tagCString, L"id:" + id, idIt->secon
d.m_filterText); |
| 578 #endif | 588 #endif |
| 579 return true; | 589 return true; |
| 580 } | 590 } |
| 581 } | 591 } |
| 582 } | 592 } |
| 583 | 593 |
| 584 // Search tag/className filters | 594 // Search tag/className filters |
| 585 if (!classNames.IsEmpty()) | 595 if (!classNames.IsEmpty()) |
| 586 { | 596 { |
| 587 int pos = 0; | 597 int pos = 0; |
| 588 CString className = classNames.Tokenize(L" \t\n\r", pos); | 598 CString className = classNames.Tokenize(L" \t\n\r", pos); |
| 589 while (pos >= 0) | 599 while (pos >= 0) |
| 590 { | 600 { |
| 591 std::pair<TFilterElementHideTagsNamed::const_iterator, TFilterElementHid
eTagsNamed::const_iterator> classItEnum = | 601 std::pair<TFilterElementHideTagsNamed::const_iterator, TFilterElementHid
eTagsNamed::const_iterator> classItEnum = |
| 592 m_elementHideTagsClass.equal_range(std::make_pair(tagCString, classNam
e)); | 602 m_elementHideTagsClass.equal_range(std::make_pair(tagCString, classNam
e)); |
| 593 | 603 |
| 594 for (TFilterElementHideTagsNamed::const_iterator classIt = classItEnum.f
irst; classIt != classItEnum.second; ++classIt) | 604 for (TFilterElementHideTagsNamed::const_iterator classIt = classItEnum.f
irst; classIt != classItEnum.second; ++classIt) |
| 595 { | 605 { |
| 596 if (classIt->second.IsMatchFilterElementHide(pEl)) | 606 if (classIt->second.IsMatchFilterElementHide(pEl)) |
| 597 { | 607 { |
| 598 #ifdef ENABLE_DEBUG_RESULT | 608 #ifdef ENABLE_DEBUG_RESULT |
| 599 DEBUG_HIDE_EL(indent + "HideEl::Found (tag/class) filter:" + classIt
->second.m_filterText) | 609 DEBUG_HIDE_EL(indent + "HideEl::Found (tag/class) filter:" + classIt
->second.m_filterText) |
| 600 CPluginDebug::DebugResultHiding(tagCString, "class:" + className,
classIt->second.m_filterText); | 610 CPluginDebug::DebugResultHiding(tagCString, L"class:" + className,
classIt->second.m_filterText); |
| 601 #endif | 611 #endif |
| 602 return true; | 612 return true; |
| 603 } | 613 } |
| 604 } | 614 } |
| 605 | 615 |
| 606 // Search general class name | 616 // Search general class name |
| 607 classItEnum = m_elementHideTagsClass.equal_range(std::make_pair("", clas
sName)); | 617 classItEnum = m_elementHideTagsClass.equal_range(std::make_pair("", clas
sName)); |
| 608 for (TFilterElementHideTagsNamed::const_iterator classIt = classItEnum.f
irst; classIt != classItEnum.second; ++ classIt) | 618 for (TFilterElementHideTagsNamed::const_iterator classIt = classItEnum.f
irst; classIt != classItEnum.second; ++ classIt) |
| 609 { | 619 { |
| 610 if (classIt->second.IsMatchFilterElementHide(pEl)) | 620 if (classIt->second.IsMatchFilterElementHide(pEl)) |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 } | 684 } |
| 675 } | 685 } |
| 676 } | 686 } |
| 677 | 687 |
| 678 return isRead; | 688 return isRead; |
| 679 } | 689 } |
| 680 | 690 |
| 681 void CPluginFilter::ClearFilters() | 691 void CPluginFilter::ClearFilters() |
| 682 { | 692 { |
| 683 // Clear filter maps | 693 // Clear filter maps |
| 684 CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); | 694 CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); |
| 685 { | 695 { |
| 686 for (int i = 0; i < 2; i++) | 696 for (int i = 0; i < 2; i++) |
| 687 { | 697 { |
| 688 for (int j = 0; j < 2; j++) | 698 for (int j = 0; j < 2; j++) |
| 689 { | 699 { |
| 690 m_filterMap[i][j].clear(); | 700 m_filterMap[i][j].clear(); |
| 691 } | 701 } |
| 692 m_filterMapDefault[i].clear(); | 702 m_filterMapDefault[i].clear(); |
| 693 } | 703 } |
| 694 | 704 |
| 695 m_elementHideTags.clear(); | 705 m_elementHideTags.clear(); |
| 696 m_elementHideTagsId.clear(); | 706 m_elementHideTagsId.clear(); |
| 697 m_elementHideTagsClass.clear(); | 707 m_elementHideTagsClass.clear(); |
| 698 } | 708 } |
| 699 } | 709 } |
| 700 | 710 |
| 701 bool CPluginFilter::ShouldBlock(const std::wstring& src, AdblockPlus::FilterEngi
ne::ContentType contentType, const std::wstring& domain, bool addDebug) const | 711 bool CPluginFilter::ShouldBlock(const std::wstring& src, AdblockPlus::FilterEngi
ne::ContentType contentType, const std::wstring& domain, bool addDebug) const |
| 702 { | 712 { |
| 703 CString srcCString = to_CString(src); | 713 std::wstring srcTrimmed = TrimString(src); |
| 704 | 714 |
| 705 // We should not block the empty string, so all filtering does not make sense | 715 // We should not block the empty string, so all filtering does not make sense |
| 706 // Therefore we just return | 716 // Therefore we just return |
| 707 if (srcCString.Trim().IsEmpty()) | 717 if (srcTrimmed.empty()) |
| 708 { | 718 { |
| 709 return false; | 719 return false; |
| 710 } | 720 } |
| 711 | 721 |
| 712 CPluginSettings* settings = CPluginSettings::GetInstance(); | 722 CPluginSettings* settings = CPluginSettings::GetInstance(); |
| 713 | 723 |
| 714 CPluginClient* client = CPluginClient::GetInstance(); | 724 CPluginClient* client = CPluginClient::GetInstance(); |
| 715 bool result = client->Matches(to_wstring(srcCString), contentType, domain); | 725 bool result = client->Matches(srcTrimmed, contentType, domain); |
| 716 | 726 |
| 717 #ifdef ENABLE_DEBUG_RESULT | 727 #ifdef ENABLE_DEBUG_RESULT |
| 718 if (addDebug) | 728 if (addDebug) |
| 719 { | 729 { |
| 720 std::wstring type = ToUtf16String(ContentTypeToString(contentType)); | 730 std::wstring type = ToUtf16String(AdblockPlus::FilterEngine::ContentTypeToSt
ring(contentType)); |
| 721 if (result) | 731 if (result) |
| 722 { | 732 { |
| 723 DEBUG_FILTER("Filter::ShouldBlock " + type + " YES"); | 733 CPluginDebug::DebugResultBlocking(ToCString(type), srcTrimmed, domain); |
| 724 CPluginDebug::DebugResultBlocking(to_CString(type), srcCString, domain); | |
| 725 } | 734 } |
| 726 else | 735 else |
| 727 { | 736 { |
| 728 CPluginDebug::DebugResultIgnoring(to_CString(type), srcCString, domain); | 737 CPluginDebug::DebugResultIgnoring(ToCString(type), srcTrimmed, domain); |
| 729 } | 738 } |
| 730 } | 739 } |
| 731 #endif | 740 #endif |
| 732 return result; | 741 return result; |
| 733 } | 742 } |
| LEFT | RIGHT |