| Index: src/plugin/PluginFilter.cpp |
| =================================================================== |
| --- a/src/plugin/PluginFilter.cpp |
| +++ b/src/plugin/PluginFilter.cpp |
| @@ -11,12 +11,89 @@ |
| #include "mlang.h" |
| #include "..\shared\CriticalSection.h" |
| +#include "..\shared\Utils.h" |
| // The filters are described at http://adblockplus.org/en/filters |
| static CriticalSection s_criticalSectionFilterMap; |
| +namespace |
| +{ |
| + // Returns attribute value and the bool flag which indicates whether the attribute is found. |
| + // For the cases like <some-tag on-some-event="do();"/> IE returns the value of 'on-some-event' |
| + // attribute as 'function(event){\ndo();\n}'. Our filters are not designed for such |
| + // transformations, so this method retrives the value of (body) of /^.*?\{(body)\}$/ as well. |
| + std::pair<std::wstring, bool> GetHtmlElementAttribute(IHTMLElement& htmlElement, const ATL::CComBSTR& attributeName) |
| + { |
| + std::pair<std::wstring, bool> retResult; |
| + retResult.second = false; |
| + ATL::CComVariant vAttr; |
| + // Performs a property search that is not case-sensitive, |
| + // and returns an interpolated value if the property is found. |
| + LONG flags = 0; |
| + if (FAILED(htmlElement.getAttribute(attributeName, flags, &vAttr))) |
| + { |
| + return retResult; |
| + } |
| + // we set that attribute found but it's not necessary that we can retrieve its value |
| + retResult.second = true; |
| + if (vAttr.vt == VT_BSTR && vAttr.bstrVal) |
| + { |
| + retResult.first.assign(vAttr.bstrVal); |
| + } |
| + else if (vAttr.vt == VT_I4) |
| + { |
| + retResult.first = std::to_wstring(vAttr.iVal); |
| + } |
| + else if (vAttr.vt == VT_DISPATCH) |
| + { |
| + wchar_t* toStringMethod = L"toString"; |
| + DISPID methodId = 0; |
| + if (FAILED(vAttr.pdispVal->GetIDsOfNames(/*must be null iid*/IID_NULL, &toStringMethod, |
| + /*cNames*/1, LOCALE_SYSTEM_DEFAULT, &methodId))) |
| + { |
| + return retResult; |
| + } |
| + ATL::CComVariant variantFunctionAsString; // result of IDispatch::Invoke |
| + DISPID dispidNamed = DISPATCH_METHOD | DISPATCH_PROPERTYGET; |
| + DISPPARAMS dispparams; |
| + dispparams.rgvarg = &variantFunctionAsString; |
| + dispparams.cArgs = 1; |
| + dispparams.cNamedArgs = 1; |
| + dispparams.rgdispidNamedArgs = &dispidNamed; |
| + UINT ArgErr = 0; |
| + if (FAILED(vAttr.pdispVal->Invoke(methodId, /*must be null iid*/IID_NULL, |
| + LOCALE_SYSTEM_DEFAULT, dispidNamed, &dispparams, &variantFunctionAsString, /*exception info*/nullptr, |
| + &ArgErr))) |
| + { |
| + return retResult; |
| + } |
| + if (variantFunctionAsString.vt != VT_BSTR) |
| + { |
| + return retResult; |
| + } |
| + std::wstring functionAsString = variantFunctionAsString.bstrVal; |
| + auto bodyBeginsAt = functionAsString.find(L'{'); |
| + if (bodyBeginsAt == std::wstring::npos) |
| + { |
| + return retResult; |
| + } |
| + // eat spaces |
| + while (::iswspace(functionAsString[++bodyBeginsAt])); |
| + auto bodyEndsAt = functionAsString.rfind(L'}'); |
| + if (bodyEndsAt == std::wstring::npos || bodyEndsAt < bodyBeginsAt) |
| + { |
| + return retResult; |
| + } |
| + // eat spaces |
| + while(::iswspace(functionAsString[--bodyEndsAt])); |
| + retResult.first = functionAsString.substr(bodyBeginsAt, bodyEndsAt - bodyBeginsAt + 1); |
| + } |
| + return retResult; |
| + } |
| +} |
| + |
| // ============================================================================ |
| // CFilterElementHideAttrSelector |
| // ============================================================================ |
| @@ -272,8 +349,8 @@ |
| if (!m_tag.IsEmpty()) |
| { |
| CComBSTR tagName; |
| + hr = pEl->get_tagName(&tagName); |
| tagName.ToLower(); |
| - hr = pEl->get_tagName(&tagName); |
| if ((hr != S_OK) || (tagName != CComBSTR(m_tag))) |
| { |
| return false; |
| @@ -284,7 +361,7 @@ |
| for (std::vector<CFilterElementHideAttrSelector>::const_iterator attrIt = m_attributeSelectors.begin(); |
| attrIt != m_attributeSelectors.end(); ++ attrIt) |
| { |
| - CString value; |
| + ATL::CString value; |
| bool attrFound = false; |
| if (attrIt->m_type == CFilterElementHideAttrType::STYLE) |
| { |
| @@ -319,20 +396,12 @@ |
| attrFound = true; |
| } |
| } |
| - else |
| + else |
| { |
| - CComVariant vAttr; |
| - if (SUCCEEDED(pEl->getAttribute(attrIt->m_bstrAttr, 0, &vAttr))) |
| + auto attribute = GetHtmlElementAttribute(*pEl, attrIt->m_bstrAttr); |
| + if (attrFound = attribute.second) |
| { |
| - attrFound = true; |
| - if (vAttr.vt == VT_BSTR) |
| - { |
| - value = vAttr.bstrVal; |
| - } |
| - else if (vAttr.vt == VT_I4) |
| - { |
| - value.Format(L"%u", vAttr.iVal); |
| - } |
| + value = ToCString(attribute.first); |
| } |
| } |
| @@ -435,13 +504,9 @@ |
| bool CPluginFilter::AddFilterElementHide(CString filterText) |
| { |
| - |
| - |
| DEBUG_FILTER("Input: " + filterText + " filterFile" + filterFile); |
| - |
| - CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); |
| + CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); |
| { |
| - |
| CString filterString = filterText; |
| // Create filter descriptor |
| std::auto_ptr<CFilterElementHide> filter; |
| @@ -464,7 +529,7 @@ |
| CString filterChunk = filterText.Left(chunkEnd).TrimRight(); |
| std::auto_ptr<CFilterElementHide> filterParent(filter); |
| - filter.reset(new CFilterElementHide(filterChunk)); |
| + filter.reset(new CFilterElementHide(filterChunk)); |
| if (filterParent.get() != 0) |
| { |
| @@ -519,7 +584,7 @@ |
| classNames = bstrClassNames; |
| } |
| - CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); |
| + CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); |
| { |
| // Search tag/id filters |
| if (!id.IsEmpty()) |
| @@ -621,7 +686,7 @@ |
| // Parse hide string |
| int pos = 0; |
| - CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); |
| + CriticalSection::Lock filterEngineLock(s_criticalSectionFilterMap); |
| { |
| for (std::vector<std::wstring>::iterator it = filters.begin(); it < filters.end(); ++it) |
| { |