Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: src/plugin/PluginWbPassThrough.cpp

Issue 4974480757620736: Issue #1356 - Improve detection of the issuer of the request (Closed)
Patch Set: Update to the repositorory tip Created Oct. 24, 2014, 9:38 a.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/plugin/PluginFilter.cpp ('k') | src/shared/Utils.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/plugin/PluginWbPassThrough.cpp
===================================================================
--- a/src/plugin/PluginWbPassThrough.cpp
+++ b/src/plugin/PluginWbPassThrough.cpp
@@ -9,6 +9,7 @@
#include "PluginSystem.h"
#include <WinInet.h>
#include "wtypes.h"
+#include "../shared/Utils.h"
namespace
{
@@ -125,150 +126,7 @@
IInternetProtocol* pTargetProtocol, bool& handled)
{
m_pTargetProtocol = pTargetProtocol;
- bool isBlocked = false;
- CString src = szUrl;
- DEBUG_GENERAL(src);
- CPluginClient::UnescapeUrl(src);
-
- // call the impl of the base class as soon as possible because it initializes the base class
- // members, used by this method. It queries for the required interfaces.
- HRESULT hr = BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTargetProtocol);
- if (FAILED(hr))
- {
- return hr;
- }
-
- CString mimeType;
- if (pOIBindInfo)
- {
- ULONG resLen = 0;
-
- // Apparently IE will report random mime type if there's more then 1 in the list.
- // So we get the whole list and just use the first one (top priority one)
- LPOLESTR mime[10];
- pOIBindInfo->GetBindString(BINDSTRING_ACCEPT_MIMES, mime, 10, &resLen);
sergei 2014/10/28 14:08:46 so, can we rely only on the Accept header?
Oleksandr 2014/10/30 23:40:48 From my experience the Accept header in BeginningT
sergei 2014/10/31 12:47:57 No any idea, I observe the same.
- if (mime && resLen > 0)
- {
- mimeType.SetString(mime[0]);
- }
- LPOLESTR bindString = nullptr;
- pOIBindInfo->GetBindString(BINDSTRING_FLAG_BIND_TO_OBJECT, &bindString, 1, &resLen);
- LPOLESTR domainRetrieved = nullptr;
- if (resLen == 0 || wcscmp(bindString, L"FALSE") == 0)
- {
- HRESULT hr = pOIBindInfo->GetBindString(BINDSTRING_XDR_ORIGIN, &domainRetrieved, 1, &resLen);
- if ((hr == S_OK) && domainRetrieved && (resLen > 0))
- {
- m_boundDomain = domainRetrieved;
- }
- }
- // We can obtain IBindCtx* here, but IEnumString obtained via IBindCtx::EnumObjectParam
- // does not return any parameter, so it's useless.
- }
-
- CString cookie;
- ULONG len1 = 2048;
- ULONG len2 = 2048;
-
- CPluginTab* tab = CPluginClass::GetTab(::GetCurrentThreadId());
- CPluginClient* client = CPluginClient::GetInstance();
-
- if (tab && client)
- {
- CString documentUrl = tab->GetDocumentUrl();
- // Page is identical to document => don't block
- if (documentUrl == src)
- {
- // fall through
- }
- else if (CPluginSettings::GetInstance()->IsPluginEnabled() && !client->IsWhitelistedUrl(std::wstring(documentUrl)))
- {
- m_boundDomain = tab->GetDocumentUrl();
- m_contentType = CFilter::contentTypeAny;
- if (tab != nullptr && tab->IsFrameCached(src))
- {
- m_contentType = CFilter::contentTypeSubdocument;
- }
- else
- {
- m_contentType = GetContentType(mimeType, m_boundDomain, src);
- }
- }
- }
-
- if (tab == nullptr)
- {
- m_contentType = GetContentType(mimeType, m_boundDomain, src);
- }
-
- {
- // Here is the heuristic which detects the requests issued by Flash.ocx.
- // It turned out that the implementation from ''Flash.ocx'' (tested version is 15.0.0.152)
- // returns quite minimal configuration in comparison with the implementation from Microsofts'
- // libraries (see grfBINDF and bindInfo.dwOptions). The impl from MS often includes something
- // else.
- ATL::CComPtr<IBindStatusCallback> bscb;
- if (SUCCEEDED(QueryServiceFromClient(&bscb)) && !!bscb)
- {
- DWORD grfBINDF = 0;
- BINDINFO bindInfo = {};
- bindInfo.cbSize = sizeof(bindInfo);
- if (SUCCEEDED(bscb->GetBindInfo(&grfBINDF, &bindInfo))
- && (BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE| BINDF_PULLDATA) == grfBINDF
- && (BINDINFO_OPTIONS_ENABLE_UTF8 | BINDINFO_OPTIONS_USE_IE_ENCODING) == bindInfo.dwOptions
- )
- {
- m_contentType = CFilter::EContentType::contentTypeObjectSubrequest;
- }
- }
- }
-
- // The descision about EContentType::contentTypeAny is made later in
- // WBPassthruSink::BeginningTransaction. Sometimes here we cannot detect the request type, but
- // in WBPassthruSink::BeginningTransaction the header Accept is available which allows to
- // obtain the "request type" in our terminology.
- if (nullptr != client
- && CFilter::EContentType::contentTypeAny != m_contentType
- && client->ShouldBlock(static_cast<const wchar_t*>(src), m_contentType, m_boundDomain, true))
- {
- isBlocked = true;
- }
-
- // For IE6 and earlier there is iframe back button issue, so avoid it.
- if (isBlocked && client->GetIEVersion() > 6)
- {
- handled = true;
- if (CFilter::EContentType::contentTypeImage == m_contentType)
- {
- // IE shows a cross that img is not loaded
- return INET_E_REDIRECT_FAILED;
- }
- if (CFilter::EContentType::contentTypeSubdocument == m_contentType)
- {
- PassthroughAPP::CustomSinkStartPolicy<WBPassthru, WBPassthruSink>::GetProtocol(this)->m_shouldSupplyCustomContent = true;
- m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"text/html");
- m_spInternetProtocolSink->ReportData(BSCF_FIRSTDATANOTIFICATION, 0, static_cast<ULONG>(g_blockedByABPPage.size()));
- return S_OK;
- }
- if (CFilter::EContentType::contentTypeScript == m_contentType)
- {
- m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"text/javascript");
- m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:");
sergei 2014/10/28 14:08:46 Previously we did that trick for such content type
Oleksandr 2014/10/30 23:40:48 I don't think it's a problem at all. We did the "d
sergei 2014/10/31 12:47:57 It's OK for me.
- return INET_E_REDIRECT_FAILED;
- }
- if (CFilter::EContentType::contentTypeXmlHttpRequest == m_contentType)
- {
- m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:");
- return INET_E_REDIRECT_FAILED;
- }
- if (CFilter::EContentType::contentTypeAny != m_contentType)
- {
- m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:");
- return INET_E_REDIRECT_FAILED;
- }
- }
-
- return isBlocked ? S_FALSE : hr;
+ return BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTargetProtocol);
}
HRESULT WBPassthruSink::OnRead(void* pv, ULONG cb, ULONG* pcbRead)
@@ -342,60 +200,97 @@
{
*pszAdditionalHeaders = nullptr;
}
+ std::wstring src = szURL;
+ DEBUG_GENERAL(src);
sergei 2014/10/28 14:08:46 DEBUG_GENERAL expects ATL::CString, it's not compi
- CPluginClient* client = nullptr;
- if (CFilter::EContentType::contentTypeAny == m_contentType && (client = CPluginClient::GetInstance()))
+ CComPtr<IHttpNegotiate> spHttpNegotiate;
+ QueryServiceFromClient(&spHttpNegotiate);
+ // This fills the pszAdditionalHeaders with more headers. One of which is the Referer header, which we need.
+ // There doesn't seem to be any other way to get this header before the request has been made.
+ HRESULT nativeHr = spHttpNegotiate ? spHttpNegotiate->BeginningTransaction(szURL, szHeaders,dwReserved, pszAdditionalHeaders) : S_OK;
+
+ auto acceptHeader = [&]() -> std::string
{
- auto acceptHeader = [&]() -> std::string
+ // Despite there is HTTP_QUERY_ACCEPT and other query info flags, they don't work here,
+ // only HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS does dork.
+ ATL::CComPtr<IWinInetHttpInfo> winInetHttpInfo;
+ HRESULT hr = m_spTargetProtocol->QueryInterface(&winInetHttpInfo);
+ if(FAILED(hr))
{
- // Despite there is HTTP_QUERY_ACCEPT and other query info flags, they don't work here,
- // only HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS does dork.
- ATL::CComPtr<IWinInetHttpInfo> winInetHttpInfo;
- HRESULT hr = m_spTargetProtocol->QueryInterface(&winInetHttpInfo);
- if(FAILED(hr))
+ return "";
+ }
+ DWORD size = 0;
+ DWORD flags = 0;
+ hr = winInetHttpInfo->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS,
+ /*buffer*/nullptr, /* get size */&size, &flags, /*reserved*/ 0);
+ if(FAILED(hr))
+ {
+ return "";
+ }
+ std::string buf(size, '\0');
+ hr = winInetHttpInfo->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS,
+ &buf[0], &size, &flags, 0);
+ if(FAILED(hr))
+ {
+ return "";
+ }
+ return ExtractHTTPHeader<std::string>(buf, "Accept:", "\r\n");
+ }();
+ m_contentType = GetContentTypeFromMimeType(ATL::CString(acceptHeader.c_str()));
+ if (*pszAdditionalHeaders != 0)
+ {
+ m_boundDomain = ExtractHTTPHeader<std::wstring>(std::wstring(*pszAdditionalHeaders), L"Referer:", L"\n").c_str();
+ }
+ m_boundDomain = TrimString(m_boundDomain);
+ CPluginTab* tab = CPluginClass::GetTab(::GetCurrentThreadId());
+ CPluginClient* client = CPluginClient::GetInstance();
+
+ if (tab && client)
+ {
+ CString documentUrl = tab->GetDocumentUrl();
+ // Page is identical to document => don't block
+ if (documentUrl == ToCString(src))
+ {
+ return nativeHr;
+ }
+ else if (CPluginSettings::GetInstance()->IsPluginEnabled() && !client->IsWhitelistedUrl(std::wstring(documentUrl)))
+ {
+ if (tab->IsFrameCached(ToCString(src)))
+ {
+ m_contentType = CFilter::contentTypeSubdocument;
+ }
+ }
+ }
+
+ {
+ // Here is the heuristic which detects the requests issued by Flash.ocx.
sergei 2014/10/28 14:08:46 I've also discovered that flash plugin on my compu
+ // It turned out that the implementation from ''Flash.ocx'' (tested version is 15.0.0.152)
+ // returns quite minimal configuration in comparison with the implementation from Microsofts'
+ // libraries (see grfBINDF and bindInfo.dwOptions). The impl from MS often includes something
+ // else.
+ ATL::CComPtr<IBindStatusCallback> bscb;
+ if (SUCCEEDED(QueryServiceFromClient(&bscb)) && !!bscb)
+ {
+ DWORD grfBINDF = 0;
+ BINDINFO bindInfo = {};
+ bindInfo.cbSize = sizeof(bindInfo);
+ if (SUCCEEDED(bscb->GetBindInfo(&grfBINDF, &bindInfo))
+ && (BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE| BINDF_PULLDATA) == grfBINDF
+ && (BINDINFO_OPTIONS_ENABLE_UTF8 | BINDINFO_OPTIONS_USE_IE_ENCODING) == bindInfo.dwOptions
+ )
{
- return "";
+ m_contentType = CFilter::EContentType::contentTypeObjectSubrequest;
}
- DWORD size = 0;
- DWORD flags = 0;
- hr = winInetHttpInfo->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS,
- /*buffer*/nullptr, /* get size */&size, &flags, /*reserved*/ 0);
- if(FAILED(hr))
- {
- return "";
- }
- std::string buf(size, '\0');
- hr = winInetHttpInfo->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS,
- &buf[0], &size, &flags, 0);
- if(FAILED(hr))
- {
- return "";
- }
- char acceptHeader[] = "Accept:";
- auto acceptHeaderBeginsAt = buf.find(acceptHeader);
- if (std::string::npos == acceptHeaderBeginsAt)
- {
- return "";
- }
- acceptHeaderBeginsAt += sizeof(acceptHeader);
- auto acceptHeaderEndsAt = buf.find("\n", acceptHeaderBeginsAt);
- if (std::string::npos == acceptHeaderEndsAt)
- {
- return "";
- }
- return buf.substr(acceptHeaderBeginsAt, acceptHeaderEndsAt - acceptHeaderBeginsAt);
- }();
- m_contentType = GetContentTypeFromMimeType(ATL::CString(acceptHeader.c_str()));
- bool isBlocked = client->ShouldBlock(szURL, m_contentType, m_boundDomain, /*debug flag but must be set*/true);
- if (isBlocked)
- {
- m_blockedInTransaction = true;
- return E_ABORT;
}
}
- CComPtr<IHttpNegotiate> spHttpNegotiate;
- QueryServiceFromClient(&spHttpNegotiate);
- return spHttpNegotiate ? spHttpNegotiate->BeginningTransaction(szURL, szHeaders,dwReserved, pszAdditionalHeaders) : S_OK;
+
+ m_blockedInTransaction = client->ShouldBlock(szURL, m_contentType, m_boundDomain, /*debug flag but must be set*/true);
+ // For IE6 and earlier there is iframe back button issue, so avoid it.
sergei 2014/10/28 14:08:46 the comment is not relevant here
+ if (m_blockedInTransaction)
+ {
+ return E_ABORT;
+ }
+ return nativeHr;
}
STDMETHODIMP WBPassthruSink::OnResponse(DWORD dwResponseCode, LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
« no previous file with comments | « src/plugin/PluginFilter.cpp ('k') | src/shared/Utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld