| LEFT | RIGHT | 
|---|
| 1 #include "PluginStdAfx.h" | 1 #include "PluginStdAfx.h" | 
| 2 | 2 | 
| 3 #include "PluginWbPassThrough.h" | 3 #include "PluginWbPassThrough.h" | 
| 4 #include "PluginClient.h" | 4 #include "PluginClient.h" | 
| 5 #include "PluginClientFactory.h" | 5 #include "PluginClientFactory.h" | 
| 6 #include "PluginFilter.h" | 6 #include "PluginFilter.h" | 
| 7 #include "PluginSettings.h" | 7 #include "PluginSettings.h" | 
| 8 #include "PluginClass.h" | 8 #include "PluginClass.h" | 
| 9 #include "PluginSystem.h" | 9 #include "PluginSystem.h" | 
| 10 #include <WinInet.h> | 10 #include <WinInet.h> | 
| 11 #include "wtypes.h" | 11 #include "wtypes.h" | 
|  | 12 #include "../shared/Utils.h" | 
| 12 | 13 | 
| 13 namespace | 14 namespace | 
| 14 { | 15 { | 
| 15   std::string g_blockedByABPPage = "<!DOCTYPE html>" | 16   const std::string g_blockedByABPPage = "<!DOCTYPE html>" | 
| 16     "<html>" | 17     "<html>" | 
| 17         "<body>" | 18         "<body>" | 
| 18           "<!-- blocked by AdblockPlus -->" | 19           "<!-- blocked by AdblockPlus -->" | 
| 19         "</body>" | 20         "</body>" | 
| 20     "</html>"; | 21     "</html>"; | 
|  | 22 | 
|  | 23   template <class T> | 
|  | 24   T ExtractHttpHeader(const T& allHeaders, const T& targetHeaderNameWithColon, c
     onst T& delimiter) | 
|  | 25   { | 
|  | 26     auto targetHeaderBeginsAt = allHeaders.find(targetHeaderNameWithColon); | 
|  | 27     if (targetHeaderBeginsAt == T::npos) | 
|  | 28     { | 
|  | 29       return T(); | 
|  | 30     } | 
|  | 31     targetHeaderBeginsAt += targetHeaderNameWithColon.length(); | 
|  | 32     auto targetHeaderEndsAt = allHeaders.find(delimiter, targetHeaderBeginsAt); | 
|  | 33     if (targetHeaderEndsAt == T::npos) | 
|  | 34     { | 
|  | 35       return T(); | 
|  | 36     } | 
|  | 37     return allHeaders.substr(targetHeaderBeginsAt, targetHeaderEndsAt - targetHe
     aderBeginsAt); | 
|  | 38   } | 
|  | 39 | 
|  | 40   std::string ExtractHttpAcceptHeader(IInternetProtocol* internetProtocol) | 
|  | 41   { | 
|  | 42     // Despite there being HTTP_QUERY_ACCEPT and other query info flags, they do
     n't work here, | 
|  | 43     // only HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS does w
     ork. | 
|  | 44     ATL::CComPtr<IWinInetHttpInfo> winInetHttpInfo; | 
|  | 45     HRESULT hr = internetProtocol->QueryInterface(&winInetHttpInfo); | 
|  | 46     if (FAILED(hr) || !winInetHttpInfo) | 
|  | 47     { | 
|  | 48       return ""; | 
|  | 49     } | 
|  | 50     DWORD size = 0; | 
|  | 51     DWORD flags = 0; | 
|  | 52     DWORD queryOption = HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HE
     ADERS; | 
|  | 53     hr = winInetHttpInfo->QueryInfo(queryOption, /*buffer*/ nullptr, /*get size*
     / &size, &flags, /*reserved*/ 0); | 
|  | 54     if (FAILED(hr)) | 
|  | 55     { | 
|  | 56       return ""; | 
|  | 57     } | 
|  | 58     std::string buf(size, '\0'); | 
|  | 59     hr = winInetHttpInfo->QueryInfo(queryOption, &buf[0], &size, &flags, 0); | 
|  | 60     if (FAILED(hr)) | 
|  | 61     { | 
|  | 62       return ""; | 
|  | 63     } | 
|  | 64     return ExtractHttpHeader<std::string>(buf, "Accept:", "\r\n"); | 
|  | 65   } | 
|  | 66 | 
|  | 67   bool IsXmlHttpRequest(const std::wstring& additionalHeaders) | 
|  | 68   { | 
|  | 69     auto requestedWithHeader = ExtractHttpHeader<std::wstring>(additionalHeaders
     , L"X-Requested-With:", L"\n"); | 
|  | 70     return TrimString(requestedWithHeader) == L"XMLHttpRequest"; | 
|  | 71   } | 
| 21 } | 72 } | 
| 22 | 73 | 
| 23 WBPassthruSink::WBPassthruSink() | 74 WBPassthruSink::WBPassthruSink() | 
| 24   : m_currentPositionOfSentPage(0) | 75   : m_currentPositionOfSentPage(0) | 
| 25   , m_contentType(CFilter::EContentType::contentTypeAny) | 76   , m_contentType(CFilter::EContentType::contentTypeAny) | 
| 26   , m_blockedInTransaction(false) | 77   , m_isCustomResponse(false) | 
| 27 { | 78 { | 
| 28 } | 79 } | 
| 29 | 80 | 
| 30 int WBPassthruSink::GetContentTypeFromMimeType(const CString& mimeType) | 81 int WBPassthruSink::GetContentTypeFromMimeType(const CString& mimeType) | 
| 31 { | 82 { | 
| 32   if (mimeType.Find(L"image/") >= 0) | 83   if (mimeType.Find(L"image/") >= 0) | 
| 33   { | 84   { | 
| 34     return CFilter::contentTypeImage; | 85     return CFilter::contentTypeImage; | 
| 35   } | 86   } | 
| 36   if (mimeType.Find(L"text/css") >= 0) | 87   if (mimeType.Find(L"text/css") >= 0) | 
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 119 ////////////////////////////////////////////////////////////////////////////////
     //////// | 170 ////////////////////////////////////////////////////////////////////////////////
     //////// | 
| 120 //WBPassthruSink | 171 //WBPassthruSink | 
| 121 //Monitor and/or cancel every request and responde | 172 //Monitor and/or cancel every request and responde | 
| 122 //WB makes, including images, sounds, scripts, etc | 173 //WB makes, including images, sounds, scripts, etc | 
| 123 ////////////////////////////////////////////////////////////////////////////////
     //////// | 174 ////////////////////////////////////////////////////////////////////////////////
     //////// | 
| 124 HRESULT WBPassthruSink::OnStart(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSin
     k, | 175 HRESULT WBPassthruSink::OnStart(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSin
     k, | 
| 125                                 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HAN
     DLE_PTR dwReserved, | 176                                 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HAN
     DLE_PTR dwReserved, | 
| 126                                 IInternetProtocol* pTargetProtocol, bool& handle
     d) | 177                                 IInternetProtocol* pTargetProtocol, bool& handle
     d) | 
| 127 { | 178 { | 
| 128   m_pTargetProtocol = pTargetProtocol; | 179   m_pTargetProtocol = pTargetProtocol; | 
| 129   bool isBlocked = false; | 180   return BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, 
     pTargetProtocol); | 
| 130   std::wstring src(szUrl); |  | 
| 131   DEBUG_GENERAL(ToCString(src)); |  | 
| 132   UnescapeUrl(src); |  | 
| 133 |  | 
| 134   // call the impl of the base class as soon as possible because it initializes 
     the base class |  | 
| 135   // members, used by this method. It queries for the required interfaces. |  | 
| 136   HRESULT hr = BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwRese
     rved, pTargetProtocol); |  | 
| 137   if (FAILED(hr)) |  | 
| 138   { |  | 
| 139     return hr; |  | 
| 140   } |  | 
| 141 |  | 
| 142   CString mimeType; |  | 
| 143   if (pOIBindInfo) |  | 
| 144   { |  | 
| 145     ULONG resLen = 0; |  | 
| 146 |  | 
| 147     // Apparently IE will report random mime type if there's more then 1 in the 
     list. |  | 
| 148     // So we get the whole list and just use the first one (top priority one) |  | 
| 149     LPOLESTR mime[10]; |  | 
| 150     pOIBindInfo->GetBindString(BINDSTRING_ACCEPT_MIMES, mime, 10, &resLen); |  | 
| 151     if (mime && resLen > 0) |  | 
| 152     { |  | 
| 153       mimeType.SetString(mime[0]); |  | 
| 154     } |  | 
| 155     LPOLESTR bindString = nullptr; |  | 
| 156     pOIBindInfo->GetBindString(BINDSTRING_FLAG_BIND_TO_OBJECT, &bindString, 1, &
     resLen); |  | 
| 157     LPOLESTR domainRetrieved = nullptr; |  | 
| 158     if (resLen == 0 || wcscmp(bindString, L"FALSE") == 0) |  | 
| 159     { |  | 
| 160       HRESULT hr = pOIBindInfo->GetBindString(BINDSTRING_XDR_ORIGIN, &domainRetr
     ieved, 1, &resLen); |  | 
| 161       if ((hr == S_OK) && domainRetrieved && (resLen > 0)) |  | 
| 162       { |  | 
| 163         m_boundDomain = domainRetrieved; |  | 
| 164       } |  | 
| 165     } |  | 
| 166     // We can obtain IBindCtx* here, but IEnumString obtained via IBindCtx::Enum
     ObjectParam |  | 
| 167     // does not return any parameter, so it's useless. |  | 
| 168   } |  | 
| 169 |  | 
| 170   CString cookie; |  | 
| 171   ULONG len1 = 2048; |  | 
| 172   ULONG len2 = 2048; |  | 
| 173 |  | 
| 174   CPluginTab* tab = CPluginClass::GetTab(::GetCurrentThreadId()); |  | 
| 175   CPluginClient* client = CPluginClient::GetInstance(); |  | 
| 176 |  | 
| 177   if (tab && client) |  | 
| 178   { |  | 
| 179     std::wstring documentUrl = tab->GetDocumentUrl(); |  | 
| 180     // Page is identical to document => don't block |  | 
| 181     if (documentUrl == src) |  | 
| 182     { |  | 
| 183       // fall through |  | 
| 184     } |  | 
| 185     else if (CPluginSettings::GetInstance()->IsPluginEnabled() && !client->IsWhi
     telistedUrl(documentUrl)) |  | 
| 186     { |  | 
| 187       m_boundDomain = tab->GetDocumentUrl(); |  | 
| 188       m_contentType = CFilter::contentTypeAny; |  | 
| 189       if (tab != nullptr && tab->IsFrameCached(src)) |  | 
| 190       { |  | 
| 191         m_contentType = CFilter::contentTypeSubdocument; |  | 
| 192       } |  | 
| 193       else |  | 
| 194       { |  | 
| 195         m_contentType = GetContentType(mimeType, m_boundDomain, src); |  | 
| 196       } |  | 
| 197     } |  | 
| 198   } |  | 
| 199 |  | 
| 200   if (tab == nullptr) |  | 
| 201   { |  | 
| 202     m_contentType = GetContentType(mimeType, m_boundDomain, src); |  | 
| 203   } |  | 
| 204 |  | 
| 205   { |  | 
| 206     // Here is the heuristic which detects the requests issued by Flash.ocx. |  | 
| 207     // It turned out that the implementation from ''Flash.ocx'' (tested version 
     is 15.0.0.152) |  | 
| 208     // returns quite minimal configuration in comparison with the implementation
      from Microsofts' |  | 
| 209     // libraries (see grfBINDF and bindInfo.dwOptions). The impl from MS often i
     ncludes something |  | 
| 210     // else. |  | 
| 211     ATL::CComPtr<IBindStatusCallback> bscb; |  | 
| 212     if (SUCCEEDED(QueryServiceFromClient(&bscb)) && !!bscb) |  | 
| 213     { |  | 
| 214       DWORD grfBINDF = 0; |  | 
| 215       BINDINFO bindInfo = {}; |  | 
| 216       bindInfo.cbSize = sizeof(bindInfo); |  | 
| 217       if (SUCCEEDED(bscb->GetBindInfo(&grfBINDF, &bindInfo)) |  | 
| 218         && (BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE| BINDF_PULLDATA) == grfBINDF |  | 
| 219         && (BINDINFO_OPTIONS_ENABLE_UTF8 | BINDINFO_OPTIONS_USE_IE_ENCODING) == 
     bindInfo.dwOptions |  | 
| 220         ) |  | 
| 221       { |  | 
| 222         m_contentType = CFilter::EContentType::contentTypeObjectSubrequest; |  | 
| 223       } |  | 
| 224     } |  | 
| 225   } |  | 
| 226 |  | 
| 227   // The descision about EContentType::contentTypeAny is made later in |  | 
| 228   // WBPassthruSink::BeginningTransaction. Sometimes here we cannot detect the r
     equest type, but |  | 
| 229   // in WBPassthruSink::BeginningTransaction the header Accept is available whic
     h allows to |  | 
| 230   // obtain the "request type" in our terminology. |  | 
| 231   if (nullptr != client |  | 
| 232     && CFilter::EContentType::contentTypeAny != m_contentType |  | 
| 233     && client->ShouldBlock(src, m_contentType, m_boundDomain, true)) |  | 
| 234   { |  | 
| 235     isBlocked = true; |  | 
| 236   } |  | 
| 237 |  | 
| 238   // For IE6 and earlier there is iframe back button issue, so avoid it. |  | 
| 239   if (isBlocked && client->GetIEVersion() > 6) |  | 
| 240   { |  | 
| 241     handled = true; |  | 
| 242     if (CFilter::EContentType::contentTypeImage == m_contentType) |  | 
| 243     { |  | 
| 244       // IE shows a cross that img is not loaded |  | 
| 245       return INET_E_REDIRECT_FAILED; |  | 
| 246     } |  | 
| 247     if (CFilter::EContentType::contentTypeSubdocument == m_contentType) |  | 
| 248     { |  | 
| 249       PassthroughAPP::CustomSinkStartPolicy<WBPassthru, WBPassthruSink>::GetProt
     ocol(this)->m_shouldSupplyCustomContent = true; |  | 
| 250       m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t
     ext/html"); |  | 
| 251       m_spInternetProtocolSink->ReportData(BSCF_FIRSTDATANOTIFICATION, 0, static
     _cast<ULONG>(g_blockedByABPPage.size())); |  | 
| 252       return S_OK; |  | 
| 253     } |  | 
| 254     if (CFilter::EContentType::contentTypeScript == m_contentType) |  | 
| 255     { |  | 
| 256       m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t
     ext/javascript"); |  | 
| 257       m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:"); |  | 
| 258       return INET_E_REDIRECT_FAILED; |  | 
| 259     } |  | 
| 260     if (CFilter::EContentType::contentTypeXmlHttpRequest == m_contentType) |  | 
| 261     { |  | 
| 262       m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:"); |  | 
| 263       return INET_E_REDIRECT_FAILED; |  | 
| 264     } |  | 
| 265     if (CFilter::EContentType::contentTypeAny != m_contentType) |  | 
| 266     { |  | 
| 267       m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:"); |  | 
| 268       return INET_E_REDIRECT_FAILED; |  | 
| 269     } |  | 
| 270   } |  | 
| 271 |  | 
| 272   return isBlocked ? S_FALSE : hr; |  | 
| 273 } | 181 } | 
| 274 | 182 | 
| 275 HRESULT WBPassthruSink::OnRead(void* pv, ULONG cb, ULONG* pcbRead) | 183 HRESULT WBPassthruSink::OnRead(void* pv, ULONG cb, ULONG* pcbRead) | 
| 276 { | 184 { | 
| 277   if (pv == nullptr) | 185   if (!pv || !pcbRead) | 
| 278   { |  | 
| 279     return E_POINTER; |  | 
| 280   } |  | 
| 281   if (pcbRead == nullptr) |  | 
| 282   { | 186   { | 
| 283     return E_POINTER; | 187     return E_POINTER; | 
| 284   } | 188   } | 
| 285   *pcbRead = 0; | 189   *pcbRead = 0; | 
| 286 | 190 | 
| 287   if (PassthroughAPP::CustomSinkStartPolicy<WBPassthru, WBPassthruSink>::GetProt
     ocol(this)->m_shouldSupplyCustomContent) | 191   if (PassthroughAPP::CustomSinkStartPolicy<WBPassthru, WBPassthruSink>::GetProt
     ocol(this)->m_shouldSupplyCustomContent) | 
| 288   { | 192   { | 
| 289     ULONG blockedByABPPageSize = static_cast<ULONG>(g_blockedByABPPage.size()); | 193     ULONG blockedByABPPageSize = static_cast<ULONG>(g_blockedByABPPage.size()); | 
| 290     auto positionGrow = std::min<ULONG>(cb, static_cast<ULONG>(blockedByABPPageS
     ize - m_currentPositionOfSentPage)); | 194     auto positionGrow = std::min<ULONG>(cb, static_cast<ULONG>(blockedByABPPageS
     ize - m_currentPositionOfSentPage)); | 
| 291     if (positionGrow == 0) { | 195     if (positionGrow == 0) { | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 330   PROTOCOLDATA::grfFlags, eventually URLMon will turn around and call | 234   PROTOCOLDATA::grfFlags, eventually URLMon will turn around and call | 
| 331   IInternetProtocol::Continue on the main thread. | 235   IInternetProtocol::Continue on the main thread. | 
| 332 | 236 | 
| 333   Or, if you happen to have a window handy that was created on the main | 237   Or, if you happen to have a window handy that was created on the main | 
| 334   thread, you can post yourself a message. | 238   thread, you can post yourself a message. | 
| 335   " | 239   " | 
| 336   */ | 240   */ | 
| 337   return m_spInternetProtocolSink ? m_spInternetProtocolSink->Switch(pProtocolDa
     ta) : E_UNEXPECTED; | 241   return m_spInternetProtocolSink ? m_spInternetProtocolSink->Switch(pProtocolDa
     ta) : E_UNEXPECTED; | 
| 338 } | 242 } | 
| 339 | 243 | 
|  | 244 // This is the heuristic which detects the requests issued by Flash.ocx. | 
|  | 245 // It turned out that the implementation from ''Flash.ocx'' (tested version is 1
     5.0.0.152) | 
|  | 246 // returns quite minimal configuration in comparison with the implementation fro
     m Microsofts' | 
|  | 247 // libraries (see grfBINDF and bindInfo.dwOptions). The impl from MS often inclu
     des something | 
|  | 248 // else. | 
|  | 249 bool WBPassthruSink::IsFlashRequest(const wchar_t* const* additionalHeaders) | 
|  | 250 { | 
|  | 251   if (additionalHeaders && *additionalHeaders) | 
|  | 252   { | 
|  | 253     auto flashVersionHeader = ExtractHttpHeader<std::wstring>(*additionalHeaders
     , L"x-flash-version:", L"\n"); | 
|  | 254     if (!TrimString(flashVersionHeader).empty()) | 
|  | 255     { | 
|  | 256       return true; | 
|  | 257     } | 
|  | 258   } | 
|  | 259   ATL::CComPtr<IBindStatusCallback> bscb; | 
|  | 260   if (SUCCEEDED(QueryServiceFromClient(&bscb)) && !!bscb) | 
|  | 261   { | 
|  | 262     DWORD grfBINDF = 0; | 
|  | 263     BINDINFO bindInfo = {}; | 
|  | 264     bindInfo.cbSize = sizeof(bindInfo); | 
|  | 265     if (SUCCEEDED(bscb->GetBindInfo(&grfBINDF, &bindInfo)) && | 
|  | 266       (BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE| BINDF_PULLDATA) == grfBINDF && | 
|  | 267       (BINDINFO_OPTIONS_ENABLE_UTF8 | BINDINFO_OPTIONS_USE_IE_ENCODING) == bindI
     nfo.dwOptions | 
|  | 268       ) | 
|  | 269     { | 
|  | 270       return true; | 
|  | 271     } | 
|  | 272   } | 
|  | 273   return false; | 
|  | 274 } | 
|  | 275 | 
| 340 STDMETHODIMP WBPassthruSink::BeginningTransaction(LPCWSTR szURL, LPCWSTR szHeade
     rs, DWORD dwReserved, LPWSTR* pszAdditionalHeaders) | 276 STDMETHODIMP WBPassthruSink::BeginningTransaction(LPCWSTR szURL, LPCWSTR szHeade
     rs, DWORD dwReserved, LPWSTR* pszAdditionalHeaders) | 
| 341 { | 277 { | 
|  | 278   if (!szURL) | 
|  | 279   { | 
|  | 280     return E_POINTER; | 
|  | 281   } | 
|  | 282   std::wstring src = szURL; | 
|  | 283   DEBUG_GENERAL(ToCString(src)); | 
|  | 284 | 
|  | 285   std::string acceptHeader = ExtractHttpAcceptHeader(m_spTargetProtocol); | 
|  | 286   m_contentType = GetContentTypeFromMimeType(ATL::CString(acceptHeader.c_str()))
     ; | 
|  | 287 | 
| 342   if (pszAdditionalHeaders) | 288   if (pszAdditionalHeaders) | 
| 343   { | 289   { | 
| 344     *pszAdditionalHeaders = nullptr; | 290     *pszAdditionalHeaders = nullptr; | 
| 345   } | 291   } | 
| 346 | 292 | 
| 347   CPluginClient* client = nullptr; | 293   CComPtr<IHttpNegotiate> httpNegotiate; | 
| 348   if (CFilter::EContentType::contentTypeAny == m_contentType && (client = CPlugi
     nClient::GetInstance())) | 294   QueryServiceFromClient(&httpNegotiate); | 
| 349   { | 295   // This fills the pszAdditionalHeaders with more headers. One of which is the 
     Referer header, which we need. | 
| 350     auto acceptHeader = [&]() -> std::string | 296   // There doesn't seem to be any other way to get this header before the reques
     t has been made. | 
| 351     { | 297   HRESULT nativeHr = httpNegotiate ? httpNegotiate->BeginningTransaction(szURL, 
     szHeaders, dwReserved, pszAdditionalHeaders) : S_OK; | 
| 352       // Despite there is HTTP_QUERY_ACCEPT and other query info flags, they don
     't work here, | 298 | 
| 353       // only HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS does
      dork. | 299   if (pszAdditionalHeaders && *pszAdditionalHeaders) | 
| 354       ATL::CComPtr<IWinInetHttpInfo> winInetHttpInfo; | 300   { | 
| 355       HRESULT hr = m_spTargetProtocol->QueryInterface(&winInetHttpInfo); | 301     m_boundDomain = ExtractHttpHeader<std::wstring>(*pszAdditionalHeaders, L"Ref
     erer:", L"\n"); | 
| 356       if(FAILED(hr)) | 302   } | 
|  | 303   m_boundDomain = TrimString(m_boundDomain); | 
|  | 304   CPluginTab* tab = CPluginClass::GetTab(::GetCurrentThreadId()); | 
|  | 305   CPluginClient* client = CPluginClient::GetInstance(); | 
|  | 306 | 
|  | 307   if (tab && client) | 
|  | 308   { | 
|  | 309     std::wstring documentUrl = tab->GetDocumentUrl(); | 
|  | 310     // Page is identical to document => don't block | 
|  | 311     if (documentUrl == src) | 
|  | 312     { | 
|  | 313       return nativeHr; | 
|  | 314     } | 
|  | 315     else if (CPluginSettings::GetInstance()->IsPluginEnabled() && !client->IsWhi
     telistedUrl(documentUrl)) | 
|  | 316     { | 
|  | 317       if (tab->IsFrameCached(src)) | 
| 357       { | 318       { | 
| 358         return ""; | 319         m_contentType = CFilter::contentTypeSubdocument; | 
| 359       } | 320       } | 
| 360       DWORD size = 0; | 321     } | 
| 361       DWORD flags = 0; | 322   } | 
| 362       hr = winInetHttpInfo->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_F
     LAG_REQUEST_HEADERS, | 323 | 
| 363           /*buffer*/nullptr, /* get size */&size, &flags, /*reserved*/ 0); | 324   if (IsFlashRequest(pszAdditionalHeaders)) | 
| 364       if(FAILED(hr)) | 325   { | 
| 365       { | 326     m_contentType = CFilter::EContentType::contentTypeObjectSubrequest; | 
| 366         return ""; | 327   } | 
| 367       } | 328 | 
| 368       std::string buf(size, '\0'); | 329   if (pszAdditionalHeaders && *pszAdditionalHeaders && IsXmlHttpRequest(*pszAddi
     tionalHeaders)) | 
| 369       hr = winInetHttpInfo->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_F
     LAG_REQUEST_HEADERS, | 330   { | 
| 370         &buf[0], &size, &flags, 0); | 331     m_contentType = CFilter::EContentType::contentTypeXmlHttpRequest; | 
| 371       if(FAILED(hr)) | 332   } | 
| 372       { | 333 | 
| 373         return ""; | 334   if (client->ShouldBlock(szURL, m_contentType, m_boundDomain, /*debug flag but 
     must be set*/true)) | 
| 374       } | 335   { | 
| 375       char acceptHeader[] = "Accept:"; | 336     // NOTE: Feeding custom HTML to Flash, instead of original object subrequest | 
| 376       auto acceptHeaderBeginsAt = buf.find(acceptHeader); | 337     // doesn't have much sense. It also can manifest in unwanted result» | 
| 377       if (std::string::npos == acceptHeaderBeginsAt) | 338     // like video being blocked (See https://issues.adblockplus.org/ticket/1669)
     » | 
| 378       { | 339     // So we report blocked object subrequests as failed, not just empty HTML. | 
| 379         return ""; | 340     m_isCustomResponse = m_contentType != CFilter::contentTypeObjectSubrequest; | 
| 380       } | 341     return E_ABORT; | 
| 381       acceptHeaderBeginsAt += sizeof(acceptHeader); | 342   } | 
| 382       auto acceptHeaderEndsAt = buf.find("\n", acceptHeaderBeginsAt); | 343   return nativeHr; | 
| 383       if (std::string::npos == acceptHeaderEndsAt) | 344 } | 
| 384       { | 345 | 
| 385         return ""; | 346 STDMETHODIMP WBPassthruSink::OnResponse(DWORD dwResponseCode, LPCWSTR szResponse
     Headers, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders) | 
| 386       } | 347 { | 
| 387       return buf.substr(acceptHeaderBeginsAt, acceptHeaderEndsAt - acceptHeaderB
     eginsAt); | 348   if (pszAdditionalRequestHeaders) | 
| 388     }(); | 349   { | 
| 389     m_contentType = GetContentTypeFromMimeType(ATL::CString(acceptHeader.c_str()
     )); | 350     *pszAdditionalRequestHeaders = 0; | 
| 390     bool isBlocked = client->ShouldBlock(szURL, m_contentType, m_boundDomain, /*
     debug flag but must be set*/true); | 351   } | 
| 391     if (isBlocked) | 352 | 
| 392     { |  | 
| 393       m_blockedInTransaction = true; |  | 
| 394       return E_ABORT; |  | 
| 395     } |  | 
| 396   } |  | 
| 397   CComPtr<IHttpNegotiate> spHttpNegotiate; | 353   CComPtr<IHttpNegotiate> spHttpNegotiate; | 
| 398   QueryServiceFromClient(&spHttpNegotiate); | 354   QueryServiceFromClient(&spHttpNegotiate); | 
| 399   return spHttpNegotiate ? spHttpNegotiate->BeginningTransaction(szURL, szHeader
     s,dwReserved, pszAdditionalHeaders) : S_OK; |  | 
| 400 } |  | 
| 401 |  | 
| 402 STDMETHODIMP WBPassthruSink::OnResponse(DWORD dwResponseCode, LPCWSTR szResponse
     Headers, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders) |  | 
| 403 { |  | 
| 404   if (pszAdditionalRequestHeaders) |  | 
| 405   { |  | 
| 406     *pszAdditionalRequestHeaders = 0; |  | 
| 407   } |  | 
| 408 |  | 
| 409   CComPtr<IHttpNegotiate> spHttpNegotiate; |  | 
| 410   QueryServiceFromClient(&spHttpNegotiate); |  | 
| 411 | 355 | 
| 412   return spHttpNegotiate ? spHttpNegotiate->OnResponse(dwResponseCode, szRespons
     eHeaders, szRequestHeaders, pszAdditionalRequestHeaders) : S_OK; | 356   return spHttpNegotiate ? spHttpNegotiate->OnResponse(dwResponseCode, szRespons
     eHeaders, szRequestHeaders, pszAdditionalRequestHeaders) : S_OK; | 
| 413 } | 357 } | 
| 414 | 358 | 
| 415 STDMETHODIMP WBPassthruSink::ReportProgress(ULONG ulStatusCode, LPCWSTR szStatus
     Text) | 359 STDMETHODIMP WBPassthruSink::ReportProgress(ULONG ulStatusCode, LPCWSTR szStatus
     Text) | 
| 416 { | 360 { | 
| 417   return m_spInternetProtocolSink ? m_spInternetProtocolSink->ReportProgress(ulS
     tatusCode, szStatusText) : S_OK; | 361   return m_spInternetProtocolSink ? m_spInternetProtocolSink->ReportProgress(ulS
     tatusCode, szStatusText) : S_OK; | 
| 418 } | 362 } | 
| 419 | 363 | 
| 420 STDMETHODIMP WBPassthruSink::ReportResult(/* [in] */ HRESULT hrResult, /* [in] *
     / DWORD dwError, /* [in] */ LPCWSTR szResult) | 364 STDMETHODIMP WBPassthruSink::ReportResult(/* [in] */ HRESULT hrResult, /* [in] *
     / DWORD dwError, /* [in] */ LPCWSTR szResult) | 
| 421 { | 365 { | 
| 422   if (m_blockedInTransaction) | 366   if (m_isCustomResponse) | 
| 423   { | 367   { | 
| 424     // Don't notify the client about aborting of the operation, thus don't call 
     BaseClass::ReportResult. | 368     // Don't notify the client about aborting of the operation, thus don't call 
     BaseClass::ReportResult. | 
| 425     // Current method is called by the original protocol implementation and we a
     re intercepting the | 369     // Current method is called by the original protocol implementation and we a
     re intercepting the | 
| 426     // call here and eating it, we will call the proper ReportResult later by ou
     rself. | 370     // call here and eating it, we will call the proper ReportResult later by ou
     rself. | 
| 427     return S_OK; | 371     return S_OK; | 
| 428   } | 372   } | 
| 429   return BaseClass::ReportResult(hrResult, dwError, szResult); | 373   return BaseClass::ReportResult(hrResult, dwError, szResult); | 
| 430 } | 374 } | 
| 431 | 375 | 
| 432 | 376 | 
| 433 WBPassthru::WBPassthru() | 377 WBPassthru::WBPassthru() | 
| 434   : m_shouldSupplyCustomContent(false) | 378   : m_shouldSupplyCustomContent(false) | 
| 435   , m_hasOriginalStartCalled(false) |  | 
| 436 { | 379 { | 
| 437 } | 380 } | 
| 438 | 381 | 
| 439 STDMETHODIMP WBPassthru::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink
     , | 382 STDMETHODIMP WBPassthru::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink
     , | 
| 440     IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) | 383     IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) | 
| 441 { | 384 { | 
| 442   ATLASSERT(m_spInternetProtocol != 0); | 385   ATLASSERT(m_spInternetProtocol != 0); | 
| 443   if (!m_spInternetProtocol) | 386   if (!m_spInternetProtocol) | 
| 444   { | 387   { | 
| 445     return E_UNEXPECTED; | 388     return E_UNEXPECTED; | 
| 446   } | 389   } | 
| 447 | 390 | 
| 448   return OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, m_spInterne
     tProtocol); | 391   return OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, m_spInterne
     tProtocol); | 
| 449 } | 392 } | 
| 450 | 393 | 
| 451 STDMETHODIMP WBPassthru::Read(/* [in, out] */ void *pv,/* [in] */ ULONG cb,/* [o
     ut] */ ULONG *pcbRead) | 394 STDMETHODIMP WBPassthru::Read(/* [in, out] */ void *pv,/* [in] */ ULONG cb,/* [o
     ut] */ ULONG *pcbRead) | 
| 452 { | 395 { | 
| 453   WBPassthruSink* pSink = GetSink(); | 396   WBPassthruSink* pSink = GetSink(); | 
| 454   return pSink->OnRead(pv, cb, pcbRead); | 397   return pSink->OnRead(pv, cb, pcbRead); | 
| 455 } |  | 
| 456 |  | 
| 457 STDMETHODIMP WBPassthru::LockRequest(/* [in] */ DWORD options) |  | 
| 458 { |  | 
| 459   if (!m_hasOriginalStartCalled) |  | 
| 460   { |  | 
| 461     return S_OK; |  | 
| 462   } |  | 
| 463   return BaseClass::LockRequest(options); |  | 
| 464 } |  | 
| 465 |  | 
| 466 STDMETHODIMP WBPassthru::UnlockRequest() |  | 
| 467 { |  | 
| 468   if (!m_hasOriginalStartCalled) |  | 
| 469   { |  | 
| 470     return S_OK; |  | 
| 471   } |  | 
| 472   return BaseClass::UnlockRequest(); |  | 
| 473 } | 398 } | 
| LEFT | RIGHT | 
|---|