| Left: | ||
| Right: | 
| OLD | NEW | 
|---|---|
| 1 #include "PluginStdAfx.h" | 1 #include "PluginStdAfx.h" | 
| 2 | 2 | 
| 3 #include "PluginFilter.h" | 3 #include "PluginFilter.h" | 
| 4 | 4 | 
| 5 #if (defined PRODUCT_ADBLOCKPLUS) | 5 #if (defined PRODUCT_ADBLOCKPLUS) | 
| 6 #include "PluginSettings.h" | 6 #include "PluginSettings.h" | 
| 7 #include "PluginClient.h" | 7 #include "PluginClient.h" | 
| 8 #include "PluginClientFactory.h" | 8 #include "PluginClientFactory.h" | 
| 9 #endif | 9 #endif | 
| 10 | 10 | 
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 | 73 | 
| 74 CFilterElementHideAttrSelector::~CFilterElementHideAttrSelector() | 74 CFilterElementHideAttrSelector::~CFilterElementHideAttrSelector() | 
| 75 { | 75 { | 
| 76 } | 76 } | 
| 77 | 77 | 
| 78 | 78 | 
| 79 // ============================================================================ | 79 // ============================================================================ | 
| 80 // CFilterElementHide | 80 // CFilterElementHide | 
| 81 // ============================================================================ | 81 // ============================================================================ | 
| 82 | 82 | 
| 83 CFilterElementHide::CFilterElementHide(const CString& filterText, const CString& filterFile) : m_filterText(filterText), m_filterFile(filterFile) | 83 CFilterElementHide::CFilterElementHide(const CString& filterText) : m_filterText (filterText) | 
| 84 { | 84 { | 
| 85 } | 85 } | 
| 86 | 86 | 
| 87 CFilterElementHide::CFilterElementHide(const CFilterElementHide& filter) | 87 CFilterElementHide::CFilterElementHide(const CFilterElementHide& filter) | 
| 88 { | 88 { | 
| 89 m_filterText = filter.m_filterText; | 89 m_filterText = filter.m_filterText; | 
| 90 m_filterFile = filter.m_filterFile; | |
| 91 | 90 | 
| 92 m_tagId = filter.m_tagId; | 91 m_tagId = filter.m_tagId; | 
| 93 m_tagClassName = filter.m_tagClassName; | 92 m_tagClassName = filter.m_tagClassName; | 
| 94 | 93 | 
| 95 m_domainsNot = filter.m_domainsNot; | 94 m_domainsNot = filter.m_domainsNot; | 
| 96 m_attributeSelectors = filter.m_attributeSelectors; | 95 m_attributeSelectors = filter.m_attributeSelectors; | 
| 97 } | 96 } | 
| 98 | 97 | 
| 99 | 98 | 
| 100 // ============================================================================ | 99 // ============================================================================ | 
| 101 // CFilter | 100 // CFilter | 
| 102 // ============================================================================ | 101 // ============================================================================ | 
| 103 | 102 | 
| 104 CFilter::CFilter(const CFilter& filter) | 103 CFilter::CFilter(const CFilter& filter) | 
| 105 { | 104 { | 
| 106 m_contentType = filter.m_contentType; | 105 m_contentType = filter.m_contentType; | 
| 107 m_filterType = filter.m_filterType; | 106 m_filterType = filter.m_filterType; | 
| 108 | 107 | 
| 109 m_isFirstParty = filter.m_isFirstParty; | 108 m_isFirstParty = filter.m_isFirstParty; | 
| 110 m_isThirdParty = filter.m_isThirdParty; | 109 m_isThirdParty = filter.m_isThirdParty; | 
| 111 | 110 | 
| 112 m_isMatchCase = filter.m_isMatchCase; | 111 m_isMatchCase = filter.m_isMatchCase; | 
| 113 m_isFromStart = filter.m_isFromStart; | 112 m_isFromStart = filter.m_isFromStart; | 
| 114 m_isFromStartDomain = filter.m_isFromStartDomain; | 113 m_isFromStartDomain = filter.m_isFromStartDomain; | 
| 115 m_isFromEnd = filter.m_isFromEnd; | 114 m_isFromEnd = filter.m_isFromEnd; | 
| 116 | 115 | 
| 117 m_stringElements = filter.m_stringElements; | 116 m_stringElements = filter.m_stringElements; | 
| 118 | 117 | 
| 119 m_filterText = filter.m_filterText; | 118 m_filterText = filter.m_filterText; | 
| 120 m_filterFile = filter.m_filterFile; | |
| 121 | 119 | 
| 122 m_domains = filter.m_domains; | 120 m_domains = filter.m_domains; | 
| 123 m_domainsNot = filter.m_domainsNot; | 121 m_domainsNot = filter.m_domainsNot; | 
| 124 | 122 | 
| 125 m_hitCount = filter.m_hitCount; | 123 m_hitCount = filter.m_hitCount; | 
| 126 } | 124 } | 
| 127 | 125 | 
| 128 | 126 | 
| 129 CFilter::CFilter() : m_isMatchCase(false), m_isFirstParty(false), m_isThirdParty (false), m_contentType(CFilter::contentTypeAny), | 127 CFilter::CFilter() : m_isMatchCase(false), m_isFirstParty(false), m_isThirdParty (false), m_contentType(CFilter::contentTypeAny), | 
| 130 m_isFromStart(false), m_isFromStartDomain(false), m_isFromEnd(false), m_hitCou nt(0) | 128 m_isFromStart(false), m_isFromStartDomain(false), m_isFromEnd(false), m_hitCou nt(0) | 
| 131 { | 129 { | 
| 132 } | 130 } | 
| 133 | 131 | 
| 134 | 132 | 
| 135 // ============================================================================ | 133 // ============================================================================ | 
| 136 // CPluginFilter | 134 // CPluginFilter | 
| 137 // ============================================================================ | 135 // ============================================================================ | 
| 138 | 136 | 
| 139 CPluginFilter::CPluginFilter(const TFilterFileList& list, const CString& dataPat h) : m_dataPath(dataPath) | 137 CPluginFilter::CPluginFilter(const CString& dataPath) : m_dataPath(dataPath) | 
| 140 { | 138 { | 
| 141 m_contentMap["document"] = CFilter::contentTypeDocument; | 139 m_contentMap["document"] = CFilter::contentTypeDocument; | 
| 142 m_contentMap["subdocument"] = CFilter::contentTypeSubdocument; | 140 m_contentMap["subdocument"] = CFilter::contentTypeSubdocument; | 
| 143 m_contentMap["sub-document"] = CFilter::contentTypeSubdocument; | 141 m_contentMap["sub-document"] = CFilter::contentTypeSubdocument; | 
| 144 m_contentMap["sub_document"] = CFilter::contentTypeSubdocument; | 142 m_contentMap["sub_document"] = CFilter::contentTypeSubdocument; | 
| 145 m_contentMap["other"] = CFilter::contentTypeOther; | 143 m_contentMap["other"] = CFilter::contentTypeOther; | 
| 146 m_contentMap["image"] = CFilter::contentTypeImage; | 144 m_contentMap["image"] = CFilter::contentTypeImage; | 
| 147 m_contentMap["script"] = CFilter::contentTypeScript; | 145 m_contentMap["script"] = CFilter::contentTypeScript; | 
| 148 m_contentMap["object"] = CFilter::contentTypeObject; | 146 m_contentMap["object"] = CFilter::contentTypeObject; | 
| 149 m_contentMap["object-subrequest"] = CFilter::contentTypeObjectSubrequest; | 147 m_contentMap["object-subrequest"] = CFilter::contentTypeObjectSubrequest; | 
| 150 m_contentMap["object_subrequest"] = CFilter::contentTypeObjectSubrequest; | 148 m_contentMap["object_subrequest"] = CFilter::contentTypeObjectSubrequest; | 
| 151 m_contentMap["xml-request"] = CFilter::contentTypeXmlHttpRequest; | 149 m_contentMap["xml-request"] = CFilter::contentTypeXmlHttpRequest; | 
| 152 m_contentMap["xml_request"] = CFilter::contentTypeXmlHttpRequest; | 150 m_contentMap["xml_request"] = CFilter::contentTypeXmlHttpRequest; | 
| 153 m_contentMap["xmlhttprequest"] = CFilter::contentTypeXmlHttpRequest; | 151 m_contentMap["xmlhttprequest"] = CFilter::contentTypeXmlHttpRequest; | 
| 154 m_contentMap["stylesheet"] = CFilter::contentTypeStyleSheet; | 152 m_contentMap["stylesheet"] = CFilter::contentTypeStyleSheet; | 
| 155 m_contentMap["background"] = CFilter::contentTypeBackground; | 153 m_contentMap["background"] = CFilter::contentTypeBackground; | 
| 156 | 154 | 
| 157 m_contentMapText[CFilter::contentTypeDocument] = "doc"; | 155 m_contentMapText[CFilter::contentTypeDocument] = "doc"; | 
| 158 m_contentMapText[CFilter::contentTypeObject] = "object"; | 156 m_contentMapText[CFilter::contentTypeObject] = "object"; | 
| 159 m_contentMapText[CFilter::contentTypeImage] = "img"; | 157 m_contentMapText[CFilter::contentTypeImage] = "img"; | 
| 160 m_contentMapText[CFilter::contentTypeScript] = "script"; | 158 m_contentMapText[CFilter::contentTypeScript] = "script"; | 
| 161 m_contentMapText[CFilter::contentTypeOther] = "other"; | 159 m_contentMapText[CFilter::contentTypeOther] = "other"; | 
| 162 m_contentMapText[CFilter::contentTypeUnknown] = "?"; | 160 m_contentMapText[CFilter::contentTypeUnknown] = "?"; | 
| 163 m_contentMapText[CFilter::contentTypeSubdocument] = "iframe"; | 161 m_contentMapText[CFilter::contentTypeSubdocument] = "iframe"; | 
| 164 m_contentMapText[CFilter::contentTypeStyleSheet] = "css"; | 162 m_contentMapText[CFilter::contentTypeStyleSheet] = "css"; | 
| 165 | 163 | 
| 166 ParseFilters(list); | 164 ClearFilters(); | 
| 167 } | 165 } | 
| 168 | 166 | 
| 169 | 167 | 
| 170 CPluginFilter::CPluginFilter(const CString& dataPath) : m_dataPath(dataPath) | 168 bool CPluginFilter::AddFilterElementHide(CString filterText) | 
| 171 { | |
| 172 } | |
| 173 | |
| 174 | |
| 175 bool CPluginFilter::AddFilterElementHide(CString filterText, CString filterFile) | |
| 176 { | 169 { | 
| 177 int delimiterPos = filterText.Find(L"#"); | 170 int delimiterPos = filterText.Find(L"#"); | 
| 178 if (delimiterPos < 0 || filterText.GetLength() <= delimiterPos + 1) | 171 if (delimiterPos < 0 || filterText.GetLength() <= delimiterPos + 1) | 
| 179 { | 172 { | 
| 180 DEBUG_FILTER("Filter::Error parsing filter:" + filterFile + "/" + filterText + " (no tag)") | 173 DEBUG_FILTER("Filter::Error parsing filter:" + filterFile + "/" + filterText + " (no tag)") | 
| 181 return false; | 174 return false; | 
| 182 } | 175 } | 
| 183 DEBUG_FILTER("Input: " + filterText + " filterFile" + filterFile); | 176 DEBUG_FILTER("Input: " + filterText + " filterFile" + filterFile); | 
| 184 bool isOldFormat = true; | 177 bool isOldFormat = true; | 
| 185 if (filterText.GetAt(delimiterPos + 1) == '#') | 178 if (filterText.GetAt(delimiterPos + 1) == '#') | 
| 186 { | 179 { | 
| 187 isOldFormat = false; | 180 isOldFormat = false; | 
| 188 } | 181 } | 
| 189 | 182 | 
| 190 s_criticalSectionFilterMap.Lock(); | 183 s_criticalSectionFilterMap.Lock(); | 
| 191 { | 184 { | 
| 192 // Create filter descriptor | 185 // Create filter descriptor | 
| 193 CFilterElementHide filter(filterText, filterFile); | 186 CFilterElementHide filter(filterText); | 
| 194 | 187 | 
| 195 CString filterDomains = filterText.Left(delimiterPos).MakeLower(); | 188 CString filterDomains = filterText.Left(delimiterPos).MakeLower(); | 
| 196 CString filterString = filterText.Right(filterText.GetLength() - delimiterP os - (isOldFormat ? 1 : 2)); | 189 CString filterString = filterText.Right(filterText.GetLength() - delimiterP os - (isOldFormat ? 1 : 2)); | 
| 197 | 190 | 
| 198 bool isDomainSpecific = delimiterPos > 0 && filterDomains.Find('~') < 0; | 191 bool isDomainSpecific = delimiterPos > 0 && filterDomains.Find('~') < 0; | 
| 199 | 192 | 
| 200 // Add not-domains to filter | 193 // Add not-domains to filter | 
| 201 if (!isDomainSpecific && delimiterPos > 0) | 194 if (!isDomainSpecific && delimiterPos > 0) | 
| 202 { | 195 { | 
| 203 int endPos = 0; | 196 int endPos = 0; | 
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 637 // Check all classes | 630 // Check all classes | 
| 638 if (classNames == filterIt->second.m_tagClassName || filterIt->secon d.m_tagClassName.IsEmpty()) | 631 if (classNames == filterIt->second.m_tagClassName || filterIt->secon d.m_tagClassName.IsEmpty()) | 
| 639 { | 632 { | 
| 640 isHidden = IsMatchFilterElementHide(filterIt->second, pEl, domain) ; | 633 isHidden = IsMatchFilterElementHide(filterIt->second, pEl, domain) ; | 
| 641 #ifdef ENABLE_DEBUG_RESULT | 634 #ifdef ENABLE_DEBUG_RESULT | 
| 642 if (isHidden) | 635 if (isHidden) | 
| 643 { | 636 { | 
| 644 if (!id.IsEmpty() && !classNames.IsEmpty()) | 637 if (!id.IsEmpty() && !classNames.IsEmpty()) | 
| 645 { | 638 { | 
| 646 DEBUG_HIDE_EL(indent + "HideEl::Found (domain) filter:" + filt erIt->second.m_filterText) | 639 DEBUG_HIDE_EL(indent + "HideEl::Found (domain) filter:" + filt erIt->second.m_filterText) | 
| 647 CPluginDebug::DebugResultHiding(tag, "id:" + id + " class:" + classNames, filterIt->second.m_filterText, filterIt->second.m_filterFile); | 640 CPluginDebug::DebugResultHiding(tag, "id:" + id + " class:" + classNames, filterIt->second.m_filterText); | 
| 648 } | 641 } | 
| 649 else if (!id.IsEmpty()) | 642 else if (!id.IsEmpty()) | 
| 650 { | 643 { | 
| 651 DEBUG_HIDE_EL(indent + "HideEl::Found (domain) filter:" + filt erIt->second.m_filterText) | 644 DEBUG_HIDE_EL(indent + "HideEl::Found (domain) filter:" + filt erIt->second.m_filterText) | 
| 652 CPluginDebug::DebugResultHiding(tag, "id:" + id, filterIt->s econd.m_filterText, filterIt->second.m_filterFile); | 645 CPluginDebug::DebugResultHiding(tag, "id:" + id, filterIt->s econd.m_filterText); | 
| 653 } | 646 } | 
| 654 else if (!classNames.IsEmpty()) | 647 else if (!classNames.IsEmpty()) | 
| 655 { | 648 { | 
| 656 DEBUG_HIDE_EL(indent + "HideEl::Found (domain) filter:" + filt erIt->second.m_filterText) | 649 DEBUG_HIDE_EL(indent + "HideEl::Found (domain) filter:" + filt erIt->second.m_filterText) | 
| 657 CPluginDebug::DebugResultHiding(tag, "class:" + classNames, filterIt->second.m_filterText, filterIt->second.m_filterFile); | 650 CPluginDebug::DebugResultHiding(tag, "class:" + classNames, filterIt->second.m_filterText); | 
| 658 } | 651 } | 
| 659 else | 652 else | 
| 660 { | 653 { | 
| 661 DEBUG_HIDE_EL(indent + "HideEl::Found (domain) filter:" + filt erIt->second.m_filterText) | 654 DEBUG_HIDE_EL(indent + "HideEl::Found (domain) filter:" + filt erIt->second.m_filterText) | 
| 662 CPluginDebug::DebugResultHiding(tag, "-" + classNames, filte rIt->second.m_filterText, filterIt->second.m_filterFile); | 655 CPluginDebug::DebugResultHiding(tag, "-" + classNames, filte rIt->second.m_filterText); | 
| 663 } | 656 } | 
| 664 } | 657 } | 
| 665 #endif | 658 #endif | 
| 666 } | 659 } | 
| 667 | 660 | 
| 668 // Iterate through class names | 661 // Iterate through class names | 
| 669 if (isHidden == false && !classNames.IsEmpty() && !filterIt->second. m_tagClassName.IsEmpty() && classNames.Find(' ') > 0) | 662 if (isHidden == false && !classNames.IsEmpty() && !filterIt->second. m_tagClassName.IsEmpty() && classNames.Find(' ') > 0) | 
| 670 { | 663 { | 
| 671 int pos = 0; | 664 int pos = 0; | 
| 672 CString className = classNames.Tokenize(L" \t\n\r", pos); | 665 CString className = classNames.Tokenize(L" \t\n\r", pos); | 
| 673 | 666 | 
| 674 while (isHidden == false && pos >= 0) | 667 while (isHidden == false && pos >= 0) | 
| 675 { | 668 { | 
| 676 if (className == filterIt->second.m_tagClassName) | 669 if (className == filterIt->second.m_tagClassName) | 
| 677 { | 670 { | 
| 678 isHidden = IsMatchFilterElementHide(filterIt->second, pEl, dom ain); | 671 isHidden = IsMatchFilterElementHide(filterIt->second, pEl, dom ain); | 
| 679 #ifdef ENABLE_DEBUG_RESULT | 672 #ifdef ENABLE_DEBUG_RESULT | 
| 680 if (isHidden) | 673 if (isHidden) | 
| 681 { | 674 { | 
| 682 if (!id.IsEmpty()) | 675 if (!id.IsEmpty()) | 
| 683 { | 676 { | 
| 684 DEBUG_HIDE_EL(indent + "HideEl::Found (domain) filter:" + filterIt->second.m_filterText) | 677 DEBUG_HIDE_EL(indent + "HideEl::Found (domain) filter:" + filterIt->second.m_filterText) | 
| 685 CPluginDebug::DebugResultHiding(tag, "id:" + id + " clas s:" + classNames, filterIt->second.m_filterText, filterIt->second.m_filterFile); | 678 CPluginDebug::DebugResultHiding(tag, "id:" + id + " clas s:" + classNames, filterIt->second.m_filterText); | 
| 686 } | 679 } | 
| 687 else | 680 else | 
| 688 { | 681 { | 
| 689 DEBUG_HIDE_EL(indent + "HideEl::Found (domain) filter:" + filterIt->second.m_filterText) | 682 DEBUG_HIDE_EL(indent + "HideEl::Found (domain) filter:" + filterIt->second.m_filterText) | 
| 690 CPluginDebug::DebugResultHiding(tag, "-" + classNames, f ilterIt->second.m_filterText, filterIt->second.m_filterFile); | 683 CPluginDebug::DebugResultHiding(tag, "-" + classNames, f ilterIt->second.m_filterText); | 
| 691 } | 684 } | 
| 692 } | 685 } | 
| 693 #endif | 686 #endif | 
| 694 } | 687 } | 
| 695 | 688 | 
| 696 // Next class name | 689 // Next class name | 
| 697 className = classNames.Tokenize(L" \t\n\r", pos); | 690 className = classNames.Tokenize(L" \t\n\r", pos); | 
| 698 } | 691 } | 
| 699 } | 692 } | 
| 700 } | 693 } | 
| (...skipping 14 matching lines...) Expand all Loading... | |
| 715 if (isHidden == false && !id.IsEmpty()) | 708 if (isHidden == false && !id.IsEmpty()) | 
| 716 { | 709 { | 
| 717 TFilterElementHideTagsNamed::const_iterator idIt = m_elementHideTagsId.fin d(std::make_pair(tag, id)); | 710 TFilterElementHideTagsNamed::const_iterator idIt = m_elementHideTagsId.fin d(std::make_pair(tag, id)); | 
| 718 if (idIt != m_elementHideTagsId.end()) | 711 if (idIt != m_elementHideTagsId.end()) | 
| 719 { | 712 { | 
| 720 isHidden = IsMatchFilterElementHide(idIt->second, pEl, domain); | 713 isHidden = IsMatchFilterElementHide(idIt->second, pEl, domain); | 
| 721 #ifdef ENABLE_DEBUG_RESULT | 714 #ifdef ENABLE_DEBUG_RESULT | 
| 722 if (isHidden) | 715 if (isHidden) | 
| 723 { | 716 { | 
| 724 DEBUG_HIDE_EL(indent + "HideEl::Found (tag/id) filter:" + idIt->second .m_filterText) | 717 DEBUG_HIDE_EL(indent + "HideEl::Found (tag/id) filter:" + idIt->second .m_filterText) | 
| 725 CPluginDebug::DebugResultHiding(tag, "id:" + id, idIt->second.m_filt erText, idIt->second.m_filterFile); | 718 CPluginDebug::DebugResultHiding(tag, "id:" + id, idIt->second.m_filt erText); | 
| 726 } | 719 } | 
| 727 #endif | 720 #endif | 
| 728 } | 721 } | 
| 729 | 722 | 
| 730 // Search general id | 723 // Search general id | 
| 731 if (isHidden == false) | 724 if (isHidden == false) | 
| 732 { | 725 { | 
| 733 idIt = m_elementHideTagsId.find(std::make_pair("", id)); | 726 idIt = m_elementHideTagsId.find(std::make_pair("", id)); | 
| 734 if (idIt != m_elementHideTagsId.end()) | 727 if (idIt != m_elementHideTagsId.end()) | 
| 735 { | 728 { | 
| 736 isHidden = IsMatchFilterElementHide(idIt->second, pEl, domain); | 729 isHidden = IsMatchFilterElementHide(idIt->second, pEl, domain); | 
| 737 #ifdef ENABLE_DEBUG_RESULT | 730 #ifdef ENABLE_DEBUG_RESULT | 
| 738 if (isHidden) | 731 if (isHidden) | 
| 739 { | 732 { | 
| 740 DEBUG_HIDE_EL(indent + "HideEl::Found (?/id) filter:" + idIt->second .m_filterText) | 733 DEBUG_HIDE_EL(indent + "HideEl::Found (?/id) filter:" + idIt->second .m_filterText) | 
| 741 CPluginDebug::DebugResultHiding(tag, "id:" + id, idIt->second.m_fi lterText, idIt->second.m_filterFile); | 734 CPluginDebug::DebugResultHiding(tag, "id:" + id, idIt->second.m_fi lterText); | 
| 742 } | 735 } | 
| 743 #endif | 736 #endif | 
| 744 } | 737 } | 
| 745 } | 738 } | 
| 746 } | 739 } | 
| 747 | 740 | 
| 748 // Search tag/className filters | 741 // Search tag/className filters | 
| 749 if (isHidden == false && !classNames.IsEmpty()) | 742 if (isHidden == false && !classNames.IsEmpty()) | 
| 750 { | 743 { | 
| 751 int pos = 0; | 744 int pos = 0; | 
| 752 CString className = classNames.Tokenize(L" \t\n\r", pos); | 745 CString className = classNames.Tokenize(L" \t\n\r", pos); | 
| 753 | 746 | 
| 754 while (isHidden == false && pos >= 0) | 747 while (isHidden == false && pos >= 0) | 
| 755 { | 748 { | 
| 756 TFilterElementHideTagsNamed::const_iterator classIt = m_elementHideTagsC lass.find(std::make_pair(tag, className)); | 749 TFilterElementHideTagsNamed::const_iterator classIt = m_elementHideTagsC lass.find(std::make_pair(tag, className)); | 
| 757 if (classIt != m_elementHideTagsClass.end()) | 750 if (classIt != m_elementHideTagsClass.end()) | 
| 758 { | 751 { | 
| 759 isHidden = IsMatchFilterElementHide(classIt->second, pEl, domain); | 752 isHidden = IsMatchFilterElementHide(classIt->second, pEl, domain); | 
| 760 #ifdef ENABLE_DEBUG_RESULT | 753 #ifdef ENABLE_DEBUG_RESULT | 
| 761 if (isHidden) | 754 if (isHidden) | 
| 762 { | 755 { | 
| 763 DEBUG_HIDE_EL(indent + "HideEl::Found (tag/class) filter:" + classIt ->second.m_filterText) | 756 DEBUG_HIDE_EL(indent + "HideEl::Found (tag/class) filter:" + classIt ->second.m_filterText) | 
| 764 CPluginDebug::DebugResultHiding(tag, "class:" + className, classIt ->second.m_filterText, classIt->second.m_filterFile); | 757 CPluginDebug::DebugResultHiding(tag, "class:" + className, classIt ->second.m_filterText); | 
| 765 } | 758 } | 
| 766 #endif | 759 #endif | 
| 767 } | 760 } | 
| 768 | 761 | 
| 769 // Search general class name | 762 // Search general class name | 
| 770 if (isHidden == false) | 763 if (isHidden == false) | 
| 771 { | 764 { | 
| 772 classIt = m_elementHideTagsClass.find(std::make_pair("", className)); | 765 classIt = m_elementHideTagsClass.find(std::make_pair("", className)); | 
| 773 if (classIt != m_elementHideTagsClass.end()) | 766 if (classIt != m_elementHideTagsClass.end()) | 
| 774 { | 767 { | 
| 775 isHidden = IsMatchFilterElementHide(classIt->second, pEl, domain); | 768 isHidden = IsMatchFilterElementHide(classIt->second, pEl, domain); | 
| 776 #ifdef ENABLE_DEBUG_RESULT | 769 #ifdef ENABLE_DEBUG_RESULT | 
| 777 if (isHidden) | 770 if (isHidden) | 
| 778 { | 771 { | 
| 779 DEBUG_HIDE_EL(indent + "HideEl::Found (?/class) filter:" + classIt ->second.m_filterText) | 772 DEBUG_HIDE_EL(indent + "HideEl::Found (?/class) filter:" + classIt ->second.m_filterText) | 
| 780 CPluginDebug::DebugResultHiding(tag, "class:" + className, class It->second.m_filterText, classIt->second.m_filterFile); | 773 CPluginDebug::DebugResultHiding(tag, "class:" + className, class It->second.m_filterText); | 
| 781 } | 774 } | 
| 782 #endif | 775 #endif | 
| 783 } | 776 } | 
| 784 } | 777 } | 
| 785 | 778 | 
| 786 // Next class name | 779 // Next class name | 
| 787 className = classNames.Tokenize(L" \t\n\r", pos); | 780 className = classNames.Tokenize(L" \t\n\r", pos); | 
| 788 } | 781 } | 
| 789 } | 782 } | 
| 790 | 783 | 
| 791 // Search tag filters | 784 // Search tag filters | 
| 792 if (isHidden == false) | 785 if (isHidden == false) | 
| 793 { | 786 { | 
| 794 TFilterElementHideTags::const_iterator tagIt = m_elementHideTags.find(tag) ; | 787 TFilterElementHideTags::const_iterator tagIt = m_elementHideTags.find(tag) ; | 
| 795 if (tagIt != m_elementHideTags.end()) | 788 if (tagIt != m_elementHideTags.end()) | 
| 796 { | 789 { | 
| 797 isHidden = IsMatchFilterElementHide(tagIt->second, pEl, domain); | 790 isHidden = IsMatchFilterElementHide(tagIt->second, pEl, domain); | 
| 798 #ifdef ENABLE_DEBUG_RESULT | 791 #ifdef ENABLE_DEBUG_RESULT | 
| 799 if (isHidden) | 792 if (isHidden) | 
| 800 { | 793 { | 
| 801 DEBUG_HIDE_EL(indent + "HideEl::Found (tag) filter:" + tagIt->second.m _filterText) | 794 DEBUG_HIDE_EL(indent + "HideEl::Found (tag) filter:" + tagIt->second.m _filterText) | 
| 802 CPluginDebug::DebugResultHiding(tag, "-", tagIt->second.m_filterText , tagIt->second.m_filterFile); | 795 CPluginDebug::DebugResultHiding(tag, "-", tagIt->second.m_filterText ); | 
| 803 } | 796 } | 
| 804 #endif | 797 #endif | 
| 805 } | 798 } | 
| 806 } | 799 } | 
| 807 } | 800 } | 
| 808 s_criticalSectionFilterMap.Unlock(); | 801 s_criticalSectionFilterMap.Unlock(); | 
| 809 | 802 | 
| 810 return isHidden; | 803 return isHidden; | 
| 811 } | 804 } | 
| 812 | 805 | 
| 813 | 806 bool CPluginFilter::LoadHideFilters(std::vector<std::string> filters) | 
| 814 void CPluginFilter::AddFilter(CString filterString, CString filterFile, int filt erType) | |
| 815 { | |
| 816 //We don't accept too short filters. Those are suspicious. | |
| 817 if (filterString.GetLength() < 5) | |
| 818 return; | |
| 819 | |
| 820 CString raw = filterString; | |
| 821 | |
| 822 // Here we should find a key for the filter | |
| 823 // We find a string of max 8 characters that does not contain any wildcards an d which are unique for the filter | |
| 824 | |
| 825 // Find settings part, identified by $ | |
| 826 CString filterSettings; | |
| 827 | |
| 828 int pos = filterString.Find('$'); | |
| 829 if (pos > 0) | |
| 830 { | |
| 831 filterSettings = filterString.Right(filterString.GetLength() - pos - 1); | |
| 832 filterString = filterString.Left(pos); | |
| 833 } | |
| 834 | |
| 835 // Split filterString to parts | |
| 836 | |
| 837 bool bCheckFromStartDomain = false; | |
| 838 if (filterString.Find(L"||") == 0) | |
| 839 { | |
| 840 bCheckFromStartDomain = true; | |
| 841 filterString = filterString.Right(filterString.GetLength() - 2); | |
| 842 } | |
| 843 | |
| 844 bool bCheckFromStart = false; | |
| 845 if (filterString.GetAt(0) == '|') | |
| 846 { | |
| 847 bCheckFromStart = true; | |
| 848 filterString = filterString.Right(filterString.GetLength() - 1); | |
| 849 } | |
| 850 | |
| 851 bool bCheckFromEnd = false; | |
| 852 if (filterString.Right(1) == "|") | |
| 853 { | |
| 854 bCheckFromEnd = true; | |
| 855 filterString = filterString.Left(filterString.GetLength() - 1); | |
| 856 } | |
| 857 | |
| 858 std::vector<CString> filterParts; | |
| 859 pos = 0; | |
| 860 | |
| 861 while ((pos = filterString.Find('*')) >= 0) | |
| 862 { | |
| 863 if (pos > 0) | |
| 864 { | |
| 865 filterParts.push_back(filterString.Left(pos)); | |
| 866 } | |
| 867 filterString = filterString.Right(filterString.GetLength() - pos - 1); | |
| 868 } | |
| 869 | |
| 870 if (!filterString.IsEmpty()) | |
| 871 { | |
| 872 filterParts.push_back(filterString); | |
| 873 } | |
| 874 | |
| 875 TFilterMap* filterMap = m_filterMap[filterType]; | |
| 876 | |
| 877 // Define hash key | |
| 878 DWORD dwKey = 0; | |
| 879 DWORD dwKeyMap = 0; | |
| 880 | |
| 881 int keyLength = 4; | |
| 882 int startCharacter = 0; | |
| 883 if (filterParts.size() < 1) | |
| 884 { | |
| 885 return; | |
| 886 } | |
| 887 CString filterPart = filterParts[0]; | |
| 888 filterPart.MakeLower(); | |
| 889 | |
| 890 int nFilterParts = filterParts.size(); | |
| 891 int nFilterPart = 0; | |
| 892 | |
| 893 int filterPartLength = filterPart.GetLength(); | |
| 894 | |
| 895 if (filterPartLength >= 7) | |
| 896 { | |
| 897 if (filterPart.Find(L"http://") == 0) | |
| 898 { | |
| 899 startCharacter = 7; | |
| 900 } | |
| 901 else if (filterPart.Find(L"https://") == 0) | |
| 902 { | |
| 903 startCharacter = 8; | |
| 904 } | |
| 905 } | |
| 906 | |
| 907 while (true) | |
| 908 { | |
| 909 // Part is too short as unique key? - try next filter part | |
| 910 while (filterPartLength < startCharacter + keyLength) | |
| 911 { | |
| 912 nFilterPart++; | |
| 913 if (nFilterPart >= nFilterParts) | |
| 914 { | |
| 915 break; | |
| 916 } | |
| 917 | |
| 918 filterPart = filterParts[nFilterPart]; | |
| 919 filterPart.MakeLower(); | |
| 920 filterPartLength = filterPart.GetLength(); | |
| 921 | |
| 922 startCharacter = 0; | |
| 923 } | |
| 924 | |
| 925 if (nFilterPart >= nFilterParts) | |
| 926 { | |
| 927 break; | |
| 928 } | |
| 929 | |
| 930 int posSpecial = filterPart.Find('^', startCharacter); | |
| 931 if (posSpecial >= 0 && posSpecial < startCharacter + keyLength) | |
| 932 { | |
| 933 startCharacter = posSpecial + 1; | |
| 934 } | |
| 935 else | |
| 936 { | |
| 937 // Try key | |
| 938 DWORD dwTestKey = (filterPart.GetAt(startCharacter) << 24) | (filterPart.G etAt(startCharacter+1) << 16) | (filterPart.GetAt(startCharacter+2) << 8) | filt erPart.GetAt(startCharacter+3); | |
| 939 | |
| 940 // Now we have a substring which we can check | |
| 941 if (filterMap[0].find(dwTestKey) == filterMap[0].end()) | |
| 942 { | |
| 943 dwKey = dwTestKey; | |
| 944 dwKeyMap = 0; | |
| 945 break; | |
| 946 } | |
| 947 | |
| 948 // We already had a match - increment the start character | |
| 949 startCharacter++; | |
| 950 } | |
| 951 } | |
| 952 | |
| 953 // Try second list | |
| 954 if (dwKey == 0) | |
| 955 { | |
| 956 dwKeyMap = 1; | |
| 957 | |
| 958 startCharacter = 0; | |
| 959 | |
| 960 filterPart = filterParts[0]; | |
| 961 filterPart.MakeLower(); | |
| 962 filterPartLength = filterPart.GetLength(); | |
| 963 | |
| 964 nFilterPart = 0; | |
| 965 | |
| 966 if (filterPartLength >= 7) | |
| 967 { | |
| 968 if (filterPart.Find(L"http://") == 0) | |
| 969 { | |
| 970 startCharacter = 7; | |
| 971 } | |
| 972 else if (filterPart.Find(L"https://") == 0) | |
| 973 { | |
| 974 startCharacter = 8; | |
| 975 } | |
| 976 } | |
| 977 | |
| 978 while (true) | |
| 979 { | |
| 980 // Part is too short as unique key? - try next filter part | |
| 981 while (filterPartLength < startCharacter + keyLength) | |
| 982 { | |
| 983 nFilterPart++; | |
| 984 if (nFilterPart >= nFilterParts) | |
| 985 { | |
| 986 break; | |
| 987 } | |
| 988 | |
| 989 filterPart = filterParts[nFilterPart]; | |
| 990 filterPart.MakeLower(); | |
| 991 filterPartLength = filterPart.GetLength(); | |
| 992 | |
| 993 startCharacter = 0; | |
| 994 } | |
| 995 | |
| 996 if (nFilterPart >= nFilterParts) | |
| 997 { | |
| 998 break; | |
| 999 } | |
| 1000 | |
| 1001 int posSpecial = filterPart.Find('^', startCharacter); | |
| 1002 if (posSpecial >= 0 && posSpecial < startCharacter + keyLength) | |
| 1003 { | |
| 1004 startCharacter = posSpecial + 1; | |
| 1005 } | |
| 1006 else | |
| 1007 { | |
| 1008 // Try key | |
| 1009 DWORD dwTestKey = (filterPart.GetAt(startCharacter) << 24) | (filterPart .GetAt(startCharacter+1) << 16) | (filterPart.GetAt(startCharacter+2) << 8) | fi lterPart.GetAt(startCharacter+3); | |
| 1010 | |
| 1011 // Now we have a substring which we can check | |
| 1012 if (filterMap[1].find(dwTestKey) == filterMap[1].end()) | |
| 1013 { | |
| 1014 dwKey = dwTestKey; | |
| 1015 break; | |
| 1016 } | |
| 1017 | |
| 1018 // We already had a match - increment the start character | |
| 1019 startCharacter++; | |
| 1020 } | |
| 1021 } | |
| 1022 } | |
| 1023 | |
| 1024 // Create the filter | |
| 1025 CFilter filter; | |
| 1026 filter.m_filterType = CFilter::filterTypeBlocking; | |
| 1027 filter.m_stringElements = filterParts; | |
| 1028 filter.m_isFromStart = bCheckFromStart; | |
| 1029 filter.m_isFromStartDomain = bCheckFromStartDomain; | |
| 1030 filter.m_isFromEnd = bCheckFromEnd; | |
| 1031 filter.m_filterText = raw; | |
| 1032 filter.m_filterFile = filterFile; | |
| 1033 | |
| 1034 // Set content type of filter and other settings | |
| 1035 if (!filterSettings.IsEmpty()) | |
| 1036 { | |
| 1037 // Split filterSettings to parts | |
| 1038 pos = 0; | |
| 1039 bool hasContent = false; | |
| 1040 | |
| 1041 while ((pos = filterSettings.Find(',')) >= 0 || !filterSettings.IsEmpty()) | |
| 1042 { | |
| 1043 CString setting = pos >= 0 ? filterSettings.Left(pos) : filterSettings; | |
| 1044 filterSettings = pos >= 0 ? filterSettings.Right(filterSettings.GetLength( ) - pos - 1) : ""; | |
| 1045 | |
| 1046 // Is content type negated | |
| 1047 bool bNegate = false; | |
| 1048 if (setting.GetAt(0) == '~') | |
| 1049 { | |
| 1050 bNegate = true; | |
| 1051 setting = setting.Right(setting.GetLength() - 1); | |
| 1052 } | |
| 1053 | |
| 1054 // Apply content type | |
| 1055 std::map<CString, int>::iterator it = m_contentMap.find(setting); | |
| 1056 if (it != m_contentMap.end()) | |
| 1057 { | |
| 1058 if (!hasContent) | |
| 1059 { | |
| 1060 if (bNegate) | |
| 1061 { | |
| 1062 filter.m_contentType = ~it->second; | |
| 1063 } | |
| 1064 else | |
| 1065 { | |
| 1066 filter.m_contentType = it->second; | |
| 1067 } | |
| 1068 hasContent = true; | |
| 1069 } | |
| 1070 else if (bNegate) | |
| 1071 { | |
| 1072 filter.m_contentType &= ~it->second; | |
| 1073 } | |
| 1074 else | |
| 1075 { | |
| 1076 filter.m_contentType |= it->second; | |
| 1077 } | |
| 1078 } | |
| 1079 else if (setting == "match-case") | |
| 1080 { | |
| 1081 filter.m_isMatchCase = true; | |
| 1082 } | |
| 1083 else if (setting == "third-party") | |
| 1084 { | |
| 1085 if (bNegate) | |
| 1086 { | |
| 1087 filter.m_isFirstParty = true; | |
| 1088 } | |
| 1089 else | |
| 1090 { | |
| 1091 filter.m_isThirdParty = true; | |
| 1092 } | |
| 1093 } | |
| 1094 else if (setting.Left(7) == "domain=") | |
| 1095 { | |
| 1096 int posDomain = 0; | |
| 1097 setting = setting.Right(setting.GetLength() - 7); | |
| 1098 | |
| 1099 while ((posDomain = setting.Find('|')) >= 0 || !setting.IsEmpty()) | |
| 1100 { | |
| 1101 CString domain = posDomain >= 0 ? setting.Left(posDomain) : setting; | |
| 1102 setting = posDomain >= 0 ? setting.Right(setting.GetLength() - posDoma in - 1) : ""; | |
| 1103 | |
| 1104 if (domain.GetAt(0) == '~') | |
| 1105 { | |
| 1106 domain = domain.Right(domain.GetLength() - 1); | |
| 1107 | |
| 1108 filter.m_domainsNot.insert(domain); | |
| 1109 } | |
| 1110 else | |
| 1111 { | |
| 1112 filter.m_domains.insert(domain); | |
| 1113 } | |
| 1114 } | |
| 1115 } | |
| 1116 else | |
| 1117 { | |
| 1118 DEBUG_FILTER("Filter::Error parsing filter:" + filterFile + "/" + raw + " (unhandled tag: " + setting + ")") | |
| 1119 return; | |
| 1120 } | |
| 1121 } | |
| 1122 } | |
| 1123 | |
| 1124 // Add the filter | |
| 1125 if (dwKey != 0) | |
| 1126 { | |
| 1127 filterMap[dwKeyMap][dwKey] = filter; | |
| 1128 } | |
| 1129 else | |
| 1130 { | |
| 1131 m_filterMapDefault[filterType].push_back(filter); | |
| 1132 } | |
| 1133 } | |
| 1134 | |
| 1135 #ifdef PRODUCT_ADBLOCKPLUS | |
| 1136 | |
| 1137 bool CPluginFilter::DownloadFilterFile(const CString& url, const CString& filena me) | |
| 1138 { | |
| 1139 CString tempFile = CPluginSettings::GetTempFile(TEMP_FILE_PREFIX); | |
| 1140 | |
| 1141 DEBUG_GENERAL("*** Downloading filter file:" + filename + " (to " + tempFile + ")"); | |
| 1142 | |
| 1143 bool bResult = !tempFile.IsEmpty(); | |
| 1144 if (bResult) | |
| 1145 { | |
| 1146 // if new filter urls are found download them and update the persistent data | |
| 1147 HRESULT hr = ::URLDownloadToFile(NULL, url, tempFile, 0, NULL); | |
| 1148 if (SUCCEEDED(hr)) | |
| 1149 { | |
| 1150 CPluginFilterLock lock(filename); | |
| 1151 if (lock.IsLocked()) | |
| 1152 { | |
| 1153 // Move the temporary file to the new text file. | |
| 1154 if (!::MoveFileEx(tempFile, CPluginSettings::GetDataPath(filename), MOVE FILE_REPLACE_EXISTING)) | |
| 1155 { | |
| 1156 DWORD dwError = ::GetLastError(); | |
| 1157 | |
| 1158 // Not same device? copy/delete instead | |
| 1159 if (dwError == ERROR_NOT_SAME_DEVICE) | |
| 1160 { | |
| 1161 if (!::CopyFile(tempFile, CPluginSettings::GetDataPath(filename), FA LSE)) | |
| 1162 { | |
| 1163 DEBUG_ERROR_LOG(::GetLastError(), PLUGIN_ERROR_FILTER, PLUGIN_ERRO R_FILTER_COPY_FILE, "Filter::Unable to copy file:" + filename) | |
| 1164 | |
| 1165 bResult = false; | |
| 1166 } | |
| 1167 | |
| 1168 ::DeleteFile(tempFile); | |
| 1169 } | |
| 1170 else | |
| 1171 { | |
| 1172 DEBUG_ERROR_LOG(dwError, PLUGIN_ERROR_FILTER, PLUGIN_ERROR_FILTER_MO VE_FILE, "Filter::Unable to replace file:" + filename) | |
| 1173 | |
| 1174 bResult = false; | |
| 1175 } | |
| 1176 } | |
| 1177 } | |
| 1178 else | |
| 1179 { | |
| 1180 bResult = false; | |
| 1181 } | |
| 1182 } | |
| 1183 else | |
| 1184 { | |
| 1185 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_FILTER, PLUGIN_ERROR_FILTER_DOWNLOAD_FILE , "Filter::Unable to download file: " + filename) | |
| 1186 | |
| 1187 bResult = false; | |
| 1188 } | |
| 1189 } | |
| 1190 | |
| 1191 return bResult; | |
| 1192 } | |
| 1193 | |
| 1194 #endif | |
| 1195 | |
| 1196 bool CPluginFilter::ReadFilter(const CString& filename, const CString& downloadP ath) | |
| 1197 { | 807 { | 
| 1198 bool isRead = false; | 808 bool isRead = false; | 
| 1199 | 809 | 
| 1200 #ifdef PRODUCT_ADBLOCKPLUS | 810 #ifdef PRODUCT_ADBLOCKPLUS | 
| 1201 CPluginClient* client = CPluginClient::GetInstance(); | 811 CPluginClient* client = CPluginClient::GetInstance(); | 
| 1202 #endif | 812 #endif | 
| 1203 CString fileContent; | |
| 1204 | 813 | 
| 1205 #ifdef PRODUCT_ADBLOCKPLUS | 814 // Parse hide string | 
| 1206 CPluginFilterLock lock(filename); | 815 int pos = 0; | 
| 1207 if (lock.IsLocked()) | 816 | 
| 817 s_criticalSectionFilterMap.Lock(); | |
| 1208 { | 818 { | 
| 1209 #endif | 819 for (std::vector<std::string>::iterator it = filters.begin(); it < filters.e nd(); ++it) | 
| 1210 DEBUG_GENERAL("*** Loading filter:" + m_dataPath + filename); | 820 { | 
| 821 CString filter((*it).c_str()); | |
| 822 // If the line is not commented out | |
| 823 if (!filter.Trim().IsEmpty() && filter.GetAt(0) != '!' && filter.GetAt(0) != '[') | |
| 
 
Wladimir Palant
2013/04/03 12:42:19
I think you can assume that the filter engine will
 
 | |
| 824 { | |
| 825 int filterType = 0; | |
| 1211 | 826 | 
| 1212 //Rename old filter file if exists | 827 // We need to categorize the filters | 
| 1213 if (filename == PERSONAL_FILTER_FILE) | 828 // We have three options, whitelist, block or element hiding | 
| 1214 { | 829 // See http://adblockplus.org/en/filters for further documentation | 
| 1215 HANDLE hFile = ::CreateFile(m_dataPath + PERSONAL_FILTER_FILE_OLD, GENERIC _READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
| 1216 if (hFile != INVALID_HANDLE_VALUE) | |
| 1217 { | |
| 1218 CloseHandle(hFile); | |
| 1219 int res = _wrename(m_dataPath + PERSONAL_FILTER_FILE_OLD, m_dataPath + f ilename); | |
| 1220 DWORD err = GetLastError(); | |
| 1221 err = 0; | |
| 1222 } | |
| 1223 } | |
| 1224 | 830 | 
| 1225 // Read file | 831 // @@ indicates white listing rule | 
| 1226 HANDLE hFile = ::CreateFile(m_dataPath + filename, GENERIC_READ, 0, NULL, OP EN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | 832 if (filter.Find(L"@@") == 0) | 
| 1227 if (hFile == INVALID_HANDLE_VALUE) | |
| 1228 { | |
| 1229 DWORD dwError = ::GetLastError(); | |
| 1230 #ifdef PRODUCT_ADBLOCKPLUS | |
| 1231 // File not found - request another download! | |
| 1232 if (dwError == ERROR_FILE_NOT_FOUND) | |
| 1233 { | |
| 1234 if (!downloadPath.IsEmpty()) | |
| 1235 { | 833 { | 
| 1236 client->RequestFilterDownload(filename, downloadPath); | 834 filterType = CFilter::filterTypeWhiteList; | 
| 835 | |
| 836 filter.Delete(0, 2); | |
| 1237 } | 837 } | 
| 1238 else if (filename == PERSONAL_FILTER_FILE) | 838 // If a filter contains ## then it is a element hiding rule | 
| 839 else if (filter.Find(L"#") >= 0) | |
| 1239 { | 840 { | 
| 1240 // Open new file | 841 filterType = CFilter::filterTypeElementHide; | 
| 1241 HANDLE hPersonalFile = ::CreateFile(CPluginSettings::GetDataPath(PERSO NAL_FILTER_FILE), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | 842 } | 
| 1242 if (hPersonalFile) | 843 //Anything we do not support here | 
| 1243 { | 844 else if (filter.Find(L"*") == 0) | 
| 1244 // Build filter string | 845 { | 
| 1245 CStringA line; | 846 filterType = CFilter::filterTypeUnknown; | 
| 847 } | |
| 848 // Else, it is a general rule | |
| 849 else | |
| 850 { | |
| 851 filterType = CFilter::filterTypeBlocking; | |
| 852 } | |
| 1246 | 853 | 
| 1247 line += "[Adblock Plus - personal filters]\r\n"; | 854 try | 
| 1248 line += "!\r\n"; | 855 { | 
| 1249 line += "! In this file you can enter your own filters.\r\n"; | 856 if (filterType == CFilter::filterTypeElementHide) | 
| 1250 line += "! Any updates to this file\r\n"; | 857 { | 
| 1251 line += "! will take effect the next time a new tab or window is ope ned in\r\n"; | 858 AddFilterElementHide(filter); | 
| 1252 line += "! Internet Explorer.\r\n"; | |
| 1253 line += "!\r\n"; | |
| 1254 line += "! To define filters you should use the adblockplus format, described on:\r\n"; | |
| 1255 line += "! http://adblockplus.org/en/filters\r\n"; | |
| 1256 line += "!\r\n"; | |
| 1257 line += "! File encoding: ANSI\r\n"; | |
| 1258 line += "!\r\n"; | |
| 1259 line += "!-------------------------Ad blocking rules---------------- ----------!\r\n"; | |
| 1260 | |
| 1261 // Write file | |
| 1262 DWORD dwBytesWritten = 0; | |
| 1263 ::WriteFile(hPersonalFile, line.GetBuffer(), line.GetLength(), &dwBy tesWritten, NULL); | |
| 1264 | |
| 1265 // Close file | |
| 1266 ::CloseHandle(hPersonalFile); | |
| 1267 } | 859 } | 
| 1268 } | 860 } | 
| 1269 } | 861 catch(...) | 
| 1270 else | |
| 1271 #endif | |
| 1272 { | |
| 1273 DEBUG_ERROR_LOG(dwError, PLUGIN_ERROR_FILTER, PLUGIN_ERROR_FILTER_READ_F ILE, "Filter::ParseFilters - Open file:" + filename) | |
| 1274 } | |
| 1275 } | |
| 1276 else | |
| 1277 { | |
| 1278 // Read file | |
| 1279 char buffer[8193]; | |
| 1280 LPVOID pBuffer = buffer; | |
| 1281 LPBYTE pByteBuffer = (LPBYTE)pBuffer; | |
| 1282 DWORD dwBytesRead = 0; | |
| 1283 BOOL bRead = TRUE; | |
| 1284 | |
| 1285 //Init MLang | |
| 1286 CoInitialize(NULL); | |
| 1287 HRESULT hr = S_OK; | |
| 1288 CComPtr<IMultiLanguage2> pMultiLanguage; | |
| 1289 hr = CoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, II D_IMultiLanguage2, (void**)&pMultiLanguage); | |
| 1290 | |
| 1291 | |
| 1292 bool codepageAvailable = false; | |
| 1293 DetectEncodingInfo encodingInfos[10]; | |
| 1294 int scores = 10; | |
| 1295 while ((bRead = ::ReadFile(hFile, pBuffer, 8192, &dwBytesRead, NULL)) == T RUE && dwBytesRead > 0) | |
| 1296 { | |
| 1297 //detect codepage based on first buffer | |
| 1298 if (!codepageAvailable) | |
| 1299 { | 862 { | 
| 1300 unsigned int srcLength = fileContent.GetLength(); | 863 //just ignore all errors we might get when adding filters | 
| 
 
Felix Dahlke
2013/04/03 05:35:27
We should probably at least log exceptions.
 
 | |
| 1301 char* buf = (char*)fileContent.GetBufferSetLength(fileContent.GetLengt h()); | |
| 1302 hr = pMultiLanguage->DetectInputCodepage(0, 0, (char*)pBuffer, (int*)& dwBytesRead, encodingInfos, &scores); | |
| 1303 codepageAvailable = true; | |
| 1304 } | |
| 1305 | |
| 1306 | |
| 1307 | |
| 1308 //Unicode | |
| 1309 if ((encodingInfos[0].nCodePage == 1200) || (encodingInfos[0].nCodePage == 1201)) | |
| 1310 { | |
| 1311 fileContent += CString((wchar_t*)buffer, dwBytesRead / 2); | |
| 1312 } | |
| 1313 else | |
| 1314 { | |
| 1315 pByteBuffer[dwBytesRead] = 0; | |
| 1316 fileContent += buffer; | |
| 1317 } | |
| 1318 } | |
| 1319 | |
| 1320 //Remove the BOM for UTF-8 | |
| 1321 if (((BYTE)fileContent.GetAt(0) == 0x3F) && ((BYTE)fileContent.GetAt(1) == 0xBB) && ((BYTE)fileContent.GetAt(2) == 0x57)) | |
| 1322 { | |
| 1323 fileContent.Delete(0, 3); | |
| 1324 } | |
| 1325 // Read error | |
| 1326 if (!bRead) | |
| 1327 { | |
| 1328 DEBUG_ERROR_LOG(::GetLastError(), PLUGIN_ERROR_FILTER, PLUGIN_ERROR_FILT ER_READ_FILE, "Filter::ParseFilters - Read") | |
| 1329 } | |
| 1330 else | |
| 1331 { | |
| 1332 isRead = true; | |
| 1333 | |
| 1334 UINT dstSize = 0; | |
| 1335 BYTE* buf = (BYTE*)fileContent.GetString(); | |
| 1336 UINT srcLength = fileContent.GetLength(); | |
| 1337 if (((encodingInfos[scores - 1].nCodePage) == 1200) || ((encodingInfos[s cores - 1].nCodePage) == 1201)) | |
| 1338 { | |
| 1339 srcLength = srcLength * 2; | |
| 1340 } | |
| 1341 hr = pMultiLanguage->ConvertString(NULL, encodingInfos[scores - 1].nCode Page, 1252, (BYTE*)buf, &srcLength, NULL, &dstSize); | |
| 1342 char* bufferTmp = new char[dstSize + 1]; | |
| 1343 hr = pMultiLanguage->ConvertString(NULL, encodingInfos[scores - 1].nCode Page, 1252, (BYTE*)buf, &srcLength, (BYTE*)bufferTmp, &dstSize); | |
| 1344 bufferTmp[dstSize] = 0; | |
| 1345 //Unicode | |
| 1346 if ((encodingInfos[0].nCodePage == 1200) || (encodingInfos[0].nCodePage == 1201)) | |
| 1347 { | |
| 1348 //remove BOM for Unicode | |
| 1349 fileContent = (char*)bufferTmp; | |
| 1350 fileContent.Delete(0, 1); | |
| 1351 | |
| 1352 } | |
| 1353 else | |
| 1354 { | |
| 1355 wchar_t* fileContentBuffer = fileContent.GetBufferSetLength(dstSize); | |
| 1356 memset(fileContentBuffer, 0, dstSize); | |
| 1357 memcpy(fileContentBuffer, bufferTmp, dstSize); | |
| 1358 } | |
| 1359 delete [] bufferTmp; | |
| 1360 | |
| 1361 } | |
| 1362 | |
| 1363 // Close file | |
| 1364 ::CloseHandle(hFile); | |
| 1365 } | |
| 1366 | |
| 1367 #ifdef PRODUCT_ADBLOCKPLUS | |
| 1368 } | |
| 1369 #endif | |
| 1370 if (isRead) | |
| 1371 { | |
| 1372 // Parse file string | |
| 1373 int pos = 0; | |
| 1374 CString filter = fileContent.Tokenize(L"\n\r", pos); | |
| 1375 | |
| 1376 s_criticalSectionFilterMap.Lock(); | |
| 1377 { | |
| 1378 while (pos >= 0) | |
| 1379 { | |
| 1380 // If the line is not commented out | |
| 1381 if (!filter.Trim().IsEmpty() && filter.GetAt(0) != '!' && filter.GetAt(0 ) != '[') | |
| 1382 { | |
| 1383 int filterType = 0; | |
| 1384 | |
| 1385 // We need to categorize the filters | |
| 1386 // We have three options, whitelist, block or element hiding | |
| 1387 // See http://adblockplus.org/en/filters for further documentation | |
| 1388 | |
| 1389 // @@ indicates white listing rule | |
| 1390 if (filter.Find(L"@@") == 0) | |
| 1391 { | |
| 1392 filterType = CFilter::filterTypeWhiteList; | |
| 1393 | |
| 1394 filter.Delete(0, 2); | |
| 1395 } | |
| 1396 // If a filter contains ## then it is a element hiding rule | |
| 1397 else if (filter.Find(L"#") >= 0) | |
| 1398 { | |
| 1399 filterType = CFilter::filterTypeElementHide; | |
| 1400 } | |
| 1401 //Anything we do not support here | |
| 1402 else if (filter.Find(L"*") == 0) | |
| 1403 { | |
| 1404 filterType = CFilter::filterTypeUnknown; | |
| 1405 } | |
| 1406 // Else, it is a general rule | |
| 1407 else | |
| 1408 { | |
| 1409 filterType = CFilter::filterTypeBlocking; | |
| 1410 } | |
| 1411 | |
| 1412 try | |
| 1413 { | |
| 1414 // Element hiding not supported yet | |
| 1415 if (filterType == CFilter::filterTypeElementHide) | |
| 1416 { | |
| 1417 AddFilterElementHide(filter, filename); | |
| 1418 } | |
| 1419 else if (filterType != CFilter::filterTypeUnknown) | |
| 1420 { | |
| 1421 AddFilter(filter, filename, filterType); | |
| 1422 } | |
| 1423 } | |
| 1424 catch(...) | |
| 1425 { | |
| 1426 //just ignore all errors we might get when adding filters | |
| 1427 } | |
| 1428 } | |
| 1429 | |
| 1430 CString tmp = L""; | |
| 1431 tmp.Format(L"Current %d, Total %d", pos, fileContent.GetLength()); | |
| 1432 filter = fileContent.Tokenize(L"\n\r", pos); | |
| 1433 int nextPos = fileContent.Find(L"\n", pos + 1); | |
| 1434 if (nextPos < 0) | |
| 1435 { | |
| 1436 filter = ""; | |
| 1437 pos = -1; | |
| 1438 | |
| 1439 } | |
| 1440 if ((filter.GetLength() > 5000) || (fileContent.GetLength() - 5 <= pos)) | |
| 1441 { | |
| 1442 filter = ""; | |
| 1443 } | 864 } | 
| 1444 } | 865 } | 
| 1445 } | 866 } | 
| 1446 s_criticalSectionFilterMap.Unlock(); | 867 } | 
| 1447 } | 868 s_criticalSectionFilterMap.Unlock(); | 
| 1448 | 869 | 
| 1449 return isRead; | 870 return isRead; | 
| 1450 } | 871 } | 
| 1451 | 872 | 
| 1452 void CPluginFilter::ParseFilters(const TFilterFileList& list) | 873 void CPluginFilter::ClearFilters() | 
| 1453 { | 874 { | 
| 1454 // Clear filter maps | 875 // Clear filter maps | 
| 1455 s_criticalSectionFilterMap.Lock(); | 876 s_criticalSectionFilterMap.Lock(); | 
| 1456 { | 877 { | 
| 1457 for (int i = 0; i < 2; i++) | 878 for (int i = 0; i < 2; i++) | 
| 1458 { | 879 { | 
| 1459 for (int j = 0; j < 2; j++) | 880 for (int j = 0; j < 2; j++) | 
| 1460 { | 881 { | 
| 1461 m_filterMap[i][j].clear(); | 882 m_filterMap[i][j].clear(); | 
| 1462 } | 883 } | 
| 1463 m_filterMapDefault[i].clear(); | 884 m_filterMapDefault[i].clear(); | 
| 1464 } | 885 } | 
| 1465 | 886 | 
| 1466 m_elementHideTags.clear(); | 887 m_elementHideTags.clear(); | 
| 1467 m_elementHideTagsId.clear(); | 888 m_elementHideTagsId.clear(); | 
| 1468 m_elementHideTagsClass.clear(); | 889 m_elementHideTagsClass.clear(); | 
| 1469 m_elementHideDomains.clear(); | 890 m_elementHideDomains.clear(); | 
| 1470 } | 891 } | 
| 1471 s_criticalSectionFilterMap.Unlock(); | 892 s_criticalSectionFilterMap.Unlock(); | 
| 1472 | |
| 1473 // Load the files | |
| 1474 #ifdef PRODUCT_ADBLOCKPLUS | |
| 1475 CPluginClient* client = CPluginClient::GetInstance(); | |
| 1476 #endif | |
| 1477 for (TFilterFileList::const_iterator it = list.begin(); it != list.end(); ++it ) | |
| 1478 { | |
| 1479 ReadFilter(it->first, it->second); | |
| 1480 } | |
| 1481 | |
| 1482 #ifdef PERSONAL_FILTER_FILE | |
| 1483 ReadFilter(PERSONAL_FILTER_FILE); | |
| 1484 #endif | |
| 1485 | |
| 1486 #ifdef ENABLE_DEBUG_SELFTEST | |
| 1487 CStringA sCount; | |
| 1488 s_criticalSectionFilterMap.Lock(); | |
| 1489 { | |
| 1490 sCount.Format("Block:%d/%d - BlockDef:%d - White:%d - WhiteDef:%d - Hide:%d/ %d", m_filterMap[0][0].size(), m_filterMap[0][1].size(), m_filterMapDefault[0].s ize(), m_filterMap[1][0].size(), m_filterMapDefault[1].size(), m_elementHideTags .size() + m_elementHideTagsClass.size() + m_elementHideTagsId.size(), m_elementH ideDomains.size()); | |
| 1491 } | |
| 1492 s_criticalSectionFilterMap.Unlock(); | |
| 1493 DEBUG_GENERAL("*** Filter count:" + sCount); | |
| 1494 #endif | |
| 1495 } | 893 } | 
| 1496 | 894 | 
| 1497 | 895 | 
| 1498 bool CPluginFilter::IsMatchFilter(const CFilter& filter, CString src, const CStr ing& srcDomain, const CString& domain) const | 896 bool CPluginFilter::IsMatchFilter(const CFilter& filter, CString src, const CStr ing& srcDomain, const CString& domain) const | 
| 1499 { | 897 { | 
| 1500 // Initial checks | 898 // Initial checks | 
| 1501 | 899 | 
| 1502 // $match_case | 900 // $match_case | 
| 1503 if (!filter.m_isMatchCase) | 901 if (!filter.m_isMatchCase) | 
| 1504 { | 902 { | 
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1793 { | 1191 { | 
| 1794 type = "???"; | 1192 type = "???"; | 
| 1795 | 1193 | 
| 1796 std::map<int,CString>::const_iterator it = m_contentMapText.find(contentType ); | 1194 std::map<int,CString>::const_iterator it = m_contentMapText.find(contentType ); | 
| 1797 if (it != m_contentMapText.end()) | 1195 if (it != m_contentMapText.end()) | 
| 1798 { | 1196 { | 
| 1799 type = it->second; | 1197 type = it->second; | 
| 1800 } | 1198 } | 
| 1801 } | 1199 } | 
| 1802 | 1200 | 
| 1201 CPluginClient* client = CPluginClient::GetInstance(); | |
| 1202 AdblockPlus::FilterEngine* filterEngine = client->GetFilterEngine(); | |
| 1203 | |
| 1204 src.OemToCharA(); | |
| 
 
Wladimir Palant
2013/04/03 12:42:19
Are we really getting all URLs as ASCII? What abou
 
Felix Dahlke
2013/04/03 12:51:04
The problem is that ABP for IE uses UTF-16 interna
 
Oleksandr
2013/04/03 13:12:17
I've used CT2CA in the end (not included in this p
 
 | |
| 1205 | |
| 1206 std::string contentTypeString = ""; | |
| 
 
Wladimir Palant
2013/04/03 12:42:19
This needs a TODO comment: "Need to guess the cont
 
 | |
| 1207 | |
| 1208 std::string url = (char*)src.GetBuffer(); | |
| 
 
Felix Dahlke
2013/04/03 05:35:27
I'm really leaving my comfort zone here, but some
 
 | |
| 1209 if (filterEngine->Matches(url, contentTypeString)) | |
| 1210 { | |
| 1211 if (addDebug) | |
| 1212 { | |
| 1213 DEBUG_FILTER("Filter::ShouldBlock " + type + " YES") | |
| 1214 | |
| 1215 #ifdef ENABLE_DEBUG_RESULT | |
| 1216 CPluginDebug::DebugResultBlocking(type, src); | |
| 1217 #endif | |
| 1218 } | |
| 1219 return true; | |
| 1220 } | |
| 1803 const CFilter* blockFilter = MatchFilter(CFilter::filterTypeBlocking, src, con tentType, domain); | 1221 const CFilter* blockFilter = MatchFilter(CFilter::filterTypeBlocking, src, con tentType, domain); | 
| 1804 if (blockFilter) | 1222 if (blockFilter) | 
| 1805 { | 1223 { | 
| 1806 const CFilter* whiteFilter = MatchFilter(CFilter::filterTypeWhiteList, src, contentType, domain); | 1224 const CFilter* whiteFilter = MatchFilter(CFilter::filterTypeWhiteList, src, contentType, domain); | 
| 1807 if (whiteFilter) | 1225 if (whiteFilter) | 
| 1808 { | 1226 { | 
| 1809 if (addDebug) | 1227 if (addDebug) | 
| 1810 { | 1228 { | 
| 1811 DEBUG_FILTER("Filter::ShouldBlock " + type + " NO src:" + src + " - whi telist:\"" + whiteFilter->m_filterText + "\""); | 1229 DEBUG_FILTER("Filter::ShouldBlock " + type + " NO src:" + src + " - whi telist:\"" + whiteFilter->m_filterText + "\""); | 
| 1812 } | 1230 } | 
| 1813 blockFilter = NULL; | 1231 blockFilter = NULL; | 
| 1814 } | 1232 } | 
| 1815 else if (addDebug) | 1233 else if (addDebug) | 
| 1816 { | 1234 { | 
| 1817 DEBUG_FILTER("Filter::ShouldBlock " + type + " YES src:" + src + " - \"" + blockFilter->m_filterText + "\"") | 1235 DEBUG_FILTER("Filter::ShouldBlock " + type + " YES src:" + src + " - \"" + blockFilter->m_filterText + "\"") | 
| 1818 | 1236 | 
| 1819 #ifdef ENABLE_DEBUG_RESULT | 1237 #ifdef ENABLE_DEBUG_RESULT | 
| 1820 CPluginDebug::DebugResultBlocking(type, src, blockFilter->m_filterText, blockFilter->m_filterFile); | 1238 CPluginDebug::DebugResultBlocking(type, src); | 
| 1821 #endif | 1239 #endif | 
| 1822 } | 1240 } | 
| 1823 } | 1241 } | 
| 1824 else if (addDebug) | 1242 else if (addDebug) | 
| 1825 { | 1243 { | 
| 1826 DEBUG_FILTER("Filter::ShouldBlock " + type + " NO src:" + src) | 1244 DEBUG_FILTER("Filter::ShouldBlock " + type + " NO src:" + src) | 
| 1827 } | 1245 } | 
| 1828 | 1246 | 
| 1829 return blockFilter ? true : false; | 1247 return blockFilter ? true : false; | 
| 1830 } | 1248 } | 
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1973 if (pos > 0 && domain.GetLength() + pos == subdomain.GetLength()) | 1391 if (pos > 0 && domain.GetLength() + pos == subdomain.GetLength()) | 
| 1974 { | 1392 { | 
| 1975 if (subdomain.GetAt(pos - 1) == '.') | 1393 if (subdomain.GetAt(pos - 1) == '.') | 
| 1976 { | 1394 { | 
| 1977 return true; | 1395 return true; | 
| 1978 } | 1396 } | 
| 1979 } | 1397 } | 
| 1980 | 1398 | 
| 1981 return false; | 1399 return false; | 
| 1982 } | 1400 } | 
| 1983 | |
| 1984 #ifdef PRODUCT_ADBLOCKPLUS | |
| 1985 | |
| 1986 void CPluginFilter::CreateFilters() | |
| 1987 { | |
| 1988 CPluginFilterLock lock("filter1.txt"); | |
| 1989 if (lock.IsLocked()) | |
| 1990 { | |
| 1991 // Check file existence | |
| 1992 std::ifstream is; | |
| 1993 is.open(CPluginSettings::GetDataPath("filter1.txt"), std::ios_base::in); | |
| 1994 if (is.is_open()) | |
| 1995 { | |
| 1996 is.close(); | |
| 1997 return; | |
| 1998 } | |
| 1999 | |
| 2000 // Open file | |
| 2001 HANDLE hFile = ::CreateFile(CPluginSettings::GetDataPath("filter1.txt"), GEN ERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | |
| 2002 if (hFile == INVALID_HANDLE_VALUE) | |
| 2003 { | |
| 2004 DEBUG_ERROR_LOG(::GetLastError(), PLUGIN_ERROR_FILTER, PLUGIN_ERROR_FILTER _CREATE_FILE_OPEN, "Filter::Create - CreateFile"); | |
| 2005 } | |
| 2006 else | |
| 2007 { | |
| 2008 // Build filter string | |
| 2009 CStringA line; | |
| 2010 line += "[Adblock Plus 1.1]\r\n"; | |
| 2011 line += "! Checksum: 0xN4e5SegJGeZuYZQGhShQ\r\n"; | |
| 2012 line += "! EasyList - https://easylist.adblockplus.org/\r\n"; | |
| 2013 line += "! Last modified: 4 Nov 2010 16:30 UTC\r\n"; | |
| 2014 line += "! Expires: 5 days (update frequency)\r\n"; | |
| 2015 line += "! Licence: https://easylist-downloads.adblockplus.org/COPYING\r\n "; | |
| 2016 line += "!\r\n"; | |
| 2017 line += "! Please report any unblocked adverts or problems\r\n"; | |
| 2018 line += "! in the forums (http://forums.lanik.us/)\r\n"; | |
| 2019 line += "! or via e-mail (easylist.subscription@gmail.com).\r\n"; | |
| 2020 line += "!\r\n"; | |
| 2021 line += "!-----------------General advert blocking filters---------------- -!\r\n"; | |
| 2022 | |
| 2023 | |
| 2024 // Write file | |
| 2025 DWORD dwBytesWritten = 0; | |
| 2026 if (::WriteFile(hFile, line.GetBuffer(), line.GetLength(), &dwBytesWritten , NULL) && dwBytesWritten == line.GetLength()) | |
| 2027 { | |
| 2028 // Set correct version | |
| 2029 CPluginSettings* settings = CPluginSettings::GetInstance(); | |
| 2030 | |
| 2031 settings->AddFilterUrl(CString(FILTERS_PROTOCOL) + CString(FILTERS_HOST) + "/easylist.txt", 1); | |
| 2032 settings->AddFilterFileName(CString(FILTERS_PROTOCOL) + CString(FILTERS_ HOST) + "/easylist.txt", "filter1.txt"); | |
| 2033 settings->Write(); | |
| 2034 } | |
| 2035 else | |
| 2036 { | |
| 2037 DEBUG_ERROR_LOG(::GetLastError(), PLUGIN_ERROR_FILTER, PLUGIN_ERROR_FILT ER_CREATE_FILE_WRITE, "Filter::Create - WriteFile"); | |
| 2038 } | |
| 2039 | |
| 2040 // Close file | |
| 2041 if (!::CloseHandle(hFile)) | |
| 2042 { | |
| 2043 DEBUG_ERROR_LOG(::GetLastError(), PLUGIN_ERROR_FILTER, PLUGIN_ERROR_FILT ER_CREATE_FILE_CLOSE, "Filter::Create - CloseHandle"); | |
| 2044 } | |
| 2045 } | |
| 2046 } | |
| 2047 } | |
| 2048 | |
| 2049 #endif // PRODUCT_ADBLOCKPLUS | |
| 2050 | |
| 2051 | |
| 2052 #ifdef PRODUCT_ADBLOCKPLUS | |
| 2053 | |
| 2054 bool CPluginFilter::IsAlive() const | |
| 2055 { | |
| 2056 bool isAlive; | |
| 2057 | |
| 2058 s_criticalSectionFilterMap.Lock(); | |
| 2059 { | |
| 2060 isAlive = !m_filterMap[0][0].empty(); | |
| 2061 } | |
| 2062 s_criticalSectionFilterMap.Unlock(); | |
| 2063 | |
| 2064 return isAlive; | |
| 2065 } | |
| 2066 | |
| 2067 #endif | |
| OLD | NEW |