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

Delta Between Two Patch Sets: src/plugin/PluginWbPassThrough.cpp

Issue 5171515343503360: Issue #41 - Bring method of determining IE version up to date (Closed)
Left Patch Set: Second version Created June 25, 2014, 6:53 p.m.
Right Patch Set: Final (?) 2 Created Jan. 5, 2015, 1:02 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
LEFTRIGHT
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 #ifdef SUPPORT_FILTER
7 #include "PluginFilter.h" 6 #include "PluginFilter.h"
8 #endif
9 #include "PluginSettings.h" 7 #include "PluginSettings.h"
10 #include "PluginClass.h" 8 #include "PluginClass.h"
11 #include "PluginSystem.h" 9 #include "PluginSystem.h"
12 #include "Wrapper.h" 10 #include <WinInet.h>
13 #include "PluginUtil.h" 11 #include "wtypes.h"
14 #include "../shared/Utils.h" 12 #include "../shared/Utils.h"
15 13 #include "../shared/IE_version.h"
16 #include "wtypes.h" 14
17 15 namespace
18 EXTERN_C IMAGE_DOS_HEADER __ImageBase; 16 {
19 17 const std::string g_blockedByABPPage = "<!DOCTYPE html>"
20 18 "<html>"
21 19 "<body>"
22 int WBPassthruSink::GetContentTypeFromMimeType( std::wstring mime_type ) 20 "<!-- blocked by AdblockPlus -->"
23 { 21 "</body>"
24 if ( mime_type.find( L"image/" ) != std::wstring::npos ) 22 "</html>";
23
24 template <class T>
25 T ExtractHttpHeader(const T& allHeaders, const T& targetHeaderNameWithColon, c onst T& delimiter)
26 {
27 auto targetHeaderBeginsAt = allHeaders.find(targetHeaderNameWithColon);
28 if (targetHeaderBeginsAt == T::npos)
29 {
30 return T();
31 }
32 targetHeaderBeginsAt += targetHeaderNameWithColon.length();
33 auto targetHeaderEndsAt = allHeaders.find(delimiter, targetHeaderBeginsAt);
34 if (targetHeaderEndsAt == T::npos)
35 {
36 return T();
37 }
38 return allHeaders.substr(targetHeaderBeginsAt, targetHeaderEndsAt - targetHe aderBeginsAt);
39 }
40
41 std::string ExtractHttpAcceptHeader(IInternetProtocol* internetProtocol)
42 {
43 // Despite there being HTTP_QUERY_ACCEPT and other query info flags, they do n't work here,
44 // only HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS does w ork.
45 ATL::CComPtr<IWinInetHttpInfo> winInetHttpInfo;
46 HRESULT hr = internetProtocol->QueryInterface(&winInetHttpInfo);
47 if (FAILED(hr) || !winInetHttpInfo)
48 {
49 return "";
50 }
51 DWORD size = 0;
52 DWORD flags = 0;
53 DWORD queryOption = HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HE ADERS;
54 hr = winInetHttpInfo->QueryInfo(queryOption, /*buffer*/ nullptr, /*get size* / &size, &flags, /*reserved*/ 0);
55 if (FAILED(hr))
56 {
57 return "";
58 }
59 std::string buf(size, '\0');
60 hr = winInetHttpInfo->QueryInfo(queryOption, &buf[0], &size, &flags, 0);
61 if (FAILED(hr))
62 {
63 return "";
64 }
65 return ExtractHttpHeader<std::string>(buf, "Accept:", "\r\n");
66 }
67
68 bool IsXmlHttpRequest(const std::wstring& additionalHeaders)
69 {
70 auto requestedWithHeader = ExtractHttpHeader<std::wstring>(additionalHeaders , L"X-Requested-With:", L"\n");
71 return TrimString(requestedWithHeader) == L"XMLHttpRequest";
72 }
73 }
74
75 WBPassthruSink::WBPassthruSink()
76 : m_currentPositionOfSentPage(0)
77 , m_contentType(CFilter::EContentType::contentTypeAny)
78 , m_isCustomResponse(false)
79 {
80 }
81
82 int WBPassthruSink::GetContentTypeFromMimeType(const CString& mimeType)
83 {
84 if (mimeType.Find(L"image/") >= 0)
25 { 85 {
26 return CFilter::contentTypeImage; 86 return CFilter::contentTypeImage;
27 } 87 }
28 if ( mime_type.find( L"text/css" ) != std::wstring::npos ) 88 if (mimeType.Find(L"text/css") >= 0)
29 { 89 {
30 return CFilter::contentTypeStyleSheet; 90 return CFilter::contentTypeStyleSheet;
31 } 91 }
32 if ( mime_type.find( L"application/javascript" ) != std::wstring::npos 92 if ((mimeType.Find(L"application/javascript") >= 0) || (mimeType.Find(L"applic ation/json") >= 0))
33 || mime_type.find( L"application/json" ) != std::wstring::npos )
34 { 93 {
35 return CFilter::contentTypeScript; 94 return CFilter::contentTypeScript;
36 } 95 }
37 if ( mime_type.find( L"application/x-shockwave-flash" ) != std::wstring::npos ) 96 if (mimeType.Find(L"application/x-shockwave-flash") >= 0)
38 { 97 {
39 return CFilter::contentTypeObject; 98 return CFilter::contentTypeObject;
40 } 99 }
41 if ( mime_type.find( L"text/html" ) != std::wstring::npos ) 100 if (mimeType.Find(L"text/html") >= 0)
42 { 101 {
43 return CFilter::contentTypeSubdocument; 102 return CFilter::contentTypeSubdocument;
44 } 103 }
45 // It is important to have this check last, since it is rather generic, and mi ght overlay text/html, for example 104 // It is important to have this check last, since it is rather generic, and mi ght overlay text/html, for example
46 if ( mime_type.find( L"xml" ) != std::wstring::npos ) 105 if (mimeType.Find(L"xml") >= 0)
47 { 106 {
48 return CFilter::contentTypeXmlHttpRequest; 107 return CFilter::contentTypeXmlHttpRequest;
49 } 108 }
109
50 return CFilter::contentTypeAny; 110 return CFilter::contentTypeAny;
51 } 111 }
52 112
53 int WBPassthruSink::GetContentTypeFromURL( std::wstring src ) 113 int WBPassthruSink::GetContentTypeFromURL(const CString& src)
54 { 114 {
55 // Start search for extension at beginning of query, if any 115 CString srcExt = src;
56 size_t ext_end = src.find( L'?' ); 116
57 // Assert ext_end <= src.length --> src[ ext_end ] == '?' 117 int pos = 0;
58 // Assert ext_end == npos --> there's no '?' character and ext_end == npos, wh ich represents "end of string" in wstring::substr() 118 if ((pos = src.Find('?')) > 0)
59 119 {
60 // Locate punctuation for extension, if any 120 srcExt = src.Left(pos);
61 size_t ext_begin = src.rfind( L'.', ext_end ); 121 }
62 if ( ext_begin == std::wstring::npos ) 122
63 { 123 int lastDotIndex = srcExt.ReverseFind('.');
64 // No punctuation 124 if (lastDotIndex < 0)
65 return CFilter::contentTypeAny; 125 return CFilter::contentTypeAny;
66 } 126 CString ext = srcExt.Mid(lastDotIndex);
67 // Adding 1 to ext_begin excludes punctuation 127 if (ext == L".jpg" || ext == L".gif" || ext == L".png" || ext == L".jpeg")
68 std::wstring ext = src.substr( ext_begin + 1, ext_end );
69 // Assert ext contains all text after last period character to beginning of qu ery, or if no query, to end of string
70
71 if (ext == L"jpg" || ext == L"gif" || ext == L"png" || ext == L"jpeg")
72 { 128 {
73 return CFilter::contentTypeImage; 129 return CFilter::contentTypeImage;
74 } 130 }
75 else if (ext == L"css") 131 else if (ext == L".css")
76 { 132 {
77 return CFilter::contentTypeStyleSheet; 133 return CFilter::contentTypeStyleSheet;
78 } 134 }
79 // Test for "jsp" before "js*" below 135 else if (ext.Right(3) == L".js")
80 else if ( ext == L"jsp" || ext == L"php" || ABP::util::begins_with( ext, L"htm " ) ) 136 {
137 return CFilter::contentTypeScript;
138 }
139 else if (ext == L".xml")
140 {
141 return CFilter::contentTypeXmlHttpRequest;
142 }
143 else if (ext == L".swf")
144 {
145 return CFilter::contentTypeObject;
146 }
147 else if (ext == L".jsp" || ext == L".php" || ext == L".html")
81 { 148 {
82 return CFilter::contentTypeSubdocument; 149 return CFilter::contentTypeSubdocument;
83 } 150 }
84 else if ( ABP::util::begins_with( ext, L"js" ) ) 151 return CFilter::contentTypeAny;
85 { 152 }
86 return CFilter::contentTypeScript; 153
87 } 154 int WBPassthruSink::GetContentType(const CString& mimeType, const std::wstring& domain, const CString& src)
88 else if (ext == L"xml")
89 {
90 return CFilter::contentTypeXmlHttpRequest;
91 }
92 else if (ext == L"swf")
93 {
94 return CFilter::contentTypeObject;
95 }
96 else
97 {
98 return CFilter::contentTypeAny & ~CFilter::contentTypeSubdocument;
99 }
100
101 }
102
103 int WBPassthruSink::GetContentType(std::wstring mimeType, std::wstring domain, s td::wstring src)
104 { 155 {
105 // No referer or mime type 156 // No referer or mime type
106 // BINDSTRING_XDR_ORIGIN works only for IE v8+ 157 // BINDSTRING_XDR_ORIGIN works only for IE v8+
107 if (mimeType.empty() && domain.empty() && ABP::IE::installed_major_version() > = 8) 158 if (mimeType.IsEmpty() && domain.empty() && AdblockPlus::IE::InstalledMajorVer sion() >= 8)
sergei 2015/01/06 13:39:11 Actually we are supporting only versions starting
Eric 2015/01/06 17:10:34 You and Oleksandr and I had a discussion about thi
108 { 159 {
109 return CFilter::contentTypeXmlHttpRequest; 160 return CFilter::contentTypeXmlHttpRequest;
110 } 161 }
111 int contentType = GetContentTypeFromMimeType(mimeType); 162 int contentType = GetContentTypeFromMimeType(mimeType);
112 if (contentType == CFilter::contentTypeAny) 163 if (contentType == CFilter::contentTypeAny)
113 { 164 {
114 contentType = GetContentTypeFromURL(src); 165 contentType = GetContentTypeFromURL(src);
115 } 166 }
116 return contentType; 167 return contentType;
117 } 168 }
118 169
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) 177 IInternetProtocol* pTargetProtocol, bool& handle d)
127 { 178 {
128
129 m_pTargetProtocol = pTargetProtocol; 179 m_pTargetProtocol = pTargetProtocol;
130 bool isBlocked = false; 180 return BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTargetProtocol);
131 m_shouldBlock = false; 181 }
132 m_lastDataReported = false; 182
133 std::wstring src( szUrl ); 183 HRESULT WBPassthruSink::OnRead(void* pv, ULONG cb, ULONG* pcbRead)
134 DEBUG_GENERAL(src); 184 {
135 Wrapper::Unescape_URL( src ); 185 if (!pv || !pcbRead)
136 186 {
137 std::wstring boundDomain; 187 return E_POINTER;
138 std::wstring mime_type; 188 }
139 if (pOIBindInfo) 189 *pcbRead = 0;
140 { 190
141 Wrapper::Internet_Bind_Info bi( pOIBindInfo ); 191 if (PassthroughAPP::CustomSinkStartPolicy<WBPassthru, WBPassthruSink>::GetProt ocol(this)->m_shouldSupplyCustomContent)
142 mime_type = bi.bind_string_single( BINDSTRING_ACCEPT_MIMES ); 192 {
143 std::wstring bind_to_object = bi.bind_string_single( BINDSTRING_FLAG_BIND_TO _OBJECT ); 193 ULONG blockedByABPPageSize = static_cast<ULONG>(g_blockedByABPPage.size());
144 ABP::util::to_lower( bind_to_object ); 194 auto positionGrow = std::min<ULONG>(cb, static_cast<ULONG>(blockedByABPPageS ize - m_currentPositionOfSentPage));
145 if ( bind_to_object == L"" || bind_to_object == L"false" ) 195 if (positionGrow == 0) {
146 { 196 return S_FALSE;
147 boundDomain = bi.bind_string_single( BINDSTRING_XDR_ORIGIN ); 197 }
148 } 198 std::copy(g_blockedByABPPage.begin(), g_blockedByABPPage.begin() + positionG row,
149 } 199 stdext::make_checked_array_iterator(static_cast<char*>(pv), cb));
150 200 *pcbRead = positionGrow;
151 #ifdef SUPPORT_FILTER 201 m_currentPositionOfSentPage += positionGrow;
152 int contentType = CFilter::contentTypeAny; 202
153 203 if (m_spInternetProtocolSink)
154 CPluginTab* tab = CPluginClass::GetTab(::GetCurrentThreadId()); 204 {
155 CPluginClient* client = CPluginClient::GetInstance(); 205 m_spInternetProtocolSink->ReportData(BSCF_INTERMEDIATEDATANOTIFICATION,
156 206 static_cast<ULONG>(m_currentPositionOfSentPage), blockedByABPPageSize);
157 207 }
158 if (tab && client) 208 if (blockedByABPPageSize == m_currentPositionOfSentPage && m_spInternetProto colSink)
159 { 209 {
160 std::wstring documentUrl = tab->GetDocumentUrl(); 210 m_spInternetProtocolSink->ReportData(BSCF_DATAFULLYAVAILABLE, blockedByABP PageSize, blockedByABPPageSize);
161 // Page is identical to document => don't block 211 m_spInternetProtocolSink->ReportResult(S_OK, 0, nullptr);
162 if (documentUrl == src)
163 {
164 // fall through
165 }
166 else if (CPluginSettings::GetInstance()->IsPluginEnabled() && !client->IsWhi telistedUrl( documentUrl ))
167 {
168 boundDomain = tab->GetDocumentUrl();
169
170 contentType = CFilter::contentTypeAny;
171
172 #ifdef SUPPORT_FRAME_CACHING
173 if ((tab != 0) && (tab->IsFrameCached(src)))
174 {
175 contentType = CFilter::contentTypeSubdocument;
176 }
177 else
178 #endif // SUPPORT_FRAME_CACHING
179 contentType = GetContentType( mime_type, boundDomain, src );
180 if (client->ShouldBlock(src, contentType, boundDomain, true))
181 {
182 isBlocked = true;
183
184 DEBUG_BLOCKER("Blocker::Blocking Http-request:" + src);
185 }
186 }
187 if (!isBlocked)
188 {
189 DEBUG_BLOCKER("Blocker::Ignoring Http-request:" + src)
190 }
191 }
192
193
194 if (tab == NULL)
195 {
196 contentType = GetContentType( mime_type, boundDomain, src);
197 if (client->ShouldBlock(src, contentType, boundDomain, true))
198 {
199 isBlocked = true;
200 }
201 }
202
203 #ifdef _DEBUG
204 std::wstring type;
205
206 if (contentType == CFilter::contentTypeDocument) type = L"DOCUMENT";
207 else if (contentType == CFilter::contentTypeObject) type = L"OBJECT";
208 else if (contentType == CFilter::contentTypeImage) type = L"IMAGE";
209 else if (contentType == CFilter::contentTypeScript) type = L"SCRIPT";
210 else if (contentType == CFilter::contentTypeOther) type = L"OTHER";
211 else if (contentType == CFilter::contentTypeUnknown) type = L"OTHER";
212 else if (contentType == CFilter::contentTypeSubdocument) type = L"SUBDOCUMENT" ;
213 else if (contentType == CFilter::contentTypeStyleSheet) type = L"STYLESHEET";
214 else type = L"OTHER";
215
216 if (isBlocked)
217 {
218 CPluginDebug::DebugResultBlocking(type, src, boundDomain);
219 }
220 else
221 {
222 CPluginDebug::DebugResultIgnoring(type, src, boundDomain);
223 }
224 #endif
225
226 //Fixes the iframe back button issue
227 if (ABP::IE::installed_major_version() > 6)
228 {
229 if ((contentType == CFilter::contentTypeImage) && (isBlocked))
230 {
231 m_shouldBlock = true;
232 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTa rgetProtocol);
233
234 return INET_E_REDIRECT_FAILED;
235
236 }
237 if (((contentType == CFilter::contentTypeSubdocument))&& (isBlocked))
238 {
239 m_shouldBlock = true;
240 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTa rgetProtocol);
241
242 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t ext/html");
243
244 //Here we check if we are running on Windows 8 Consumer Preview.
245 //For some reason on that environment the next line causes IE to crash
246 if (CPluginSettings::GetInstance()->GetWindowsBuildNumber() != 8250)
247 {
248 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"res:// mshtml.dll/blank.htm");
249 }
250
251 return INET_E_REDIRECT_FAILED;
252 }
253 if (((contentType == CFilter::contentTypeScript))&& (isBlocked))
254 {
255 m_shouldBlock = true;
256 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTa rgetProtocol);
257 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t ext/javascript");
258 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:");
259 return INET_E_REDIRECT_FAILED;
260 }
261 if ((isBlocked))
262 {
263 /* WCHAR tmp[256];
264 wsprintf(tmp, L"URL: %s, domain: %s, mime: %s, type: %d", szUrl, boundDoma in, mimeType, contentType);
265 MessageBox(NULL, tmp, L"", MB_OK);
266 contentType = GetContentType(mimeType, boundDomain, src);
267 */
268 m_shouldBlock = true;
269 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTa rgetProtocol);
270 m_spInternetProtocolSink->ReportResult(S_FALSE, 0, L"");
271
272 return INET_E_REDIRECT_FAILED;
273 }
274 }
275 #endif // SUPPORT_FILTER
276
277 return isBlocked ? S_FALSE : BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInf o, grfPI, dwReserved, pTargetProtocol);
278 }
279
280
281 HRESULT WBPassthruSink::Read(void *pv, ULONG cb, ULONG* pcbRead)
282 {
283 if (m_shouldBlock)
284 {
285 *pcbRead = 0;
286 if (!m_lastDataReported)
287 {
288 if (cb <= 1)
289 {
290 //IE must've gone nuts if this happened, but let's be cool about it and report we have no more data
291 m_spInternetProtocolSink->ReportResult(S_FALSE, 0, NULL);
292 return S_FALSE;
293 }
294 *pcbRead = 1;
295 memcpy(pv, " ", 1);
296
297 if (m_spInternetProtocolSink != NULL)
298 {
299 m_spInternetProtocolSink->ReportResult(S_OK, 0, NULL);
300 }
301 m_lastDataReported = true;
302 m_shouldBlock = false;
303 return S_OK;
304 } 212 }
305 return S_OK; 213 return S_OK;
306 } 214 }
307 else 215 return m_pTargetProtocol->Read(pv, cb, pcbRead);
308 {
309
310 return m_pTargetProtocol->Read(pv, cb, pcbRead);
311 }
312 return S_OK;
313 } 216 }
314 STDMETHODIMP WBPassthruSink::Switch( 217 STDMETHODIMP WBPassthruSink::Switch(
315 /* [in] */ PROTOCOLDATA *pProtocolData) 218 /* [in] */ PROTOCOLDATA *pProtocolData)
316 { 219 {
317 ATLASSERT(m_spInternetProtocolSink != 0); 220 ATLASSERT(m_spInternetProtocolSink != 0);
318 221
319 /* 222 /*
320 From Igor Tandetnik "itandetnik@mvps.org" 223 From Igor Tandetnik "itandetnik@mvps.org"
321 " 224 "
322 Beware multithreading. URLMon has this nasty habit of spinning worker 225 Beware multithreading. URLMon has this nasty habit of spinning worker
323 threads, not even bothering to initialize COM on them, and calling APP 226 threads, not even bothering to initialize COM on them, and calling APP
324 methods on those threads. If you try to raise COM events directly from 227 methods on those threads. If you try to raise COM events directly from
325 such a thread, bad things happen (random crashes, events being lost). 228 such a thread, bad things happen (random crashes, events being lost).
326 You are only guaranteed to be on the main STA thread in two cases. 229 You are only guaranteed to be on the main STA thread in two cases.
327 First, in methods of interfaces that were obtained with 230 First, in methods of interfaces that were obtained with
328 IServiceProvider, such as IHttpNegotiage::BeginningTransaction or 231 IServiceProvider, such as IHttpNegotiage::BeginningTransaction or
329 IAuthenticate::Authenticate. Second, you can call 232 IAuthenticate::Authenticate. Second, you can call
330 IInternetProtocolSink::Switch with PD_FORCE_SWITCH flag in 233 IInternetProtocolSink::Switch with PD_FORCE_SWITCH flag in
331 PROTOCOLDATA::grfFlags, eventually URLMon will turn around and call 234 PROTOCOLDATA::grfFlags, eventually URLMon will turn around and call
332 IInternetProtocol::Continue on the main thread. 235 IInternetProtocol::Continue on the main thread.
333 236
334 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
335 thread, you can post yourself a message. 238 thread, you can post yourself a message.
336 " 239 "
337 */ 240 */
338 return m_spInternetProtocolSink ? m_spInternetProtocolSink->Switch(pProtocolDa ta) : E_UNEXPECTED; 241 return m_spInternetProtocolSink ? m_spInternetProtocolSink->Switch(pProtocolDa ta) : E_UNEXPECTED;
339 } 242 }
340 243
341 244 // This is the heuristic which detects the requests issued by Flash.ocx.
342 STDMETHODIMP WBPassthruSink::BeginningTransaction(LPCWSTR szURL, LPCWSTR szHeade rs, DWORD dwReserved, LPWSTR *pszAdditionalHeaders) 245 // It turned out that the implementation from ''Flash.ocx'' (tested version is 1 5.0.0.152)
343 { 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
276 STDMETHODIMP WBPassthruSink::BeginningTransaction(LPCWSTR szURL, LPCWSTR szHeade rs, DWORD dwReserved, LPWSTR* pszAdditionalHeaders)
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
344 if (pszAdditionalHeaders) 288 if (pszAdditionalHeaders)
345 { 289 {
346 *pszAdditionalHeaders = 0; 290 *pszAdditionalHeaders = nullptr;
291 }
292
293 CComPtr<IHttpNegotiate> httpNegotiate;
294 QueryServiceFromClient(&httpNegotiate);
295 // This fills the pszAdditionalHeaders with more headers. One of which is the Referer header, which we need.
296 // There doesn't seem to be any other way to get this header before the reques t has been made.
297 HRESULT nativeHr = httpNegotiate ? httpNegotiate->BeginningTransaction(szURL, szHeaders, dwReserved, pszAdditionalHeaders) : S_OK;
298
299 if (pszAdditionalHeaders && *pszAdditionalHeaders)
300 {
301 m_boundDomain = ExtractHttpHeader<std::wstring>(*pszAdditionalHeaders, L"Ref erer:", L"\n");
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 CString documentUrl = tab->GetDocumentUrl();
310 // Page is identical to document => don't block
311 if (documentUrl == ToCString(src))
312 {
313 return nativeHr;
314 }
315 else if (CPluginSettings::GetInstance()->IsPluginEnabled() && !client->IsWhi telistedUrl(std::wstring(documentUrl)))
316 {
317 if (tab->IsFrameCached(ToCString(src)))
318 {
319 m_contentType = CFilter::contentTypeSubdocument;
320 }
321 }
322 }
323
324 if (IsFlashRequest(pszAdditionalHeaders))
325 {
326 m_contentType = CFilter::EContentType::contentTypeObjectSubrequest;
327 }
328
329 if (pszAdditionalHeaders && *pszAdditionalHeaders && IsXmlHttpRequest(*pszAddi tionalHeaders))
330 {
331 m_contentType = CFilter::EContentType::contentTypeXmlHttpRequest;
332 }
333
334 if (client->ShouldBlock(szURL, m_contentType, m_boundDomain, /*debug flag but must be set*/true))
335 {
336 // NOTE: Feeding custom HTML to Flash, instead of original object subrequest
337 // doesn't have much sense. It also can manifest in unwanted result»
338 // like video being blocked (See https://issues.adblockplus.org/ticket/1669) »
339 // So we report blocked object subrequests as failed, not just empty HTML.
340 m_isCustomResponse = m_contentType != CFilter::contentTypeObjectSubrequest;
341 return E_ABORT;
342 }
343 return nativeHr;
344 }
345
346 STDMETHODIMP WBPassthruSink::OnResponse(DWORD dwResponseCode, LPCWSTR szResponse Headers, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
347 {
348 if (pszAdditionalRequestHeaders)
349 {
350 *pszAdditionalRequestHeaders = 0;
347 } 351 }
348 352
349 CComPtr<IHttpNegotiate> spHttpNegotiate; 353 CComPtr<IHttpNegotiate> spHttpNegotiate;
350 QueryServiceFromClient(&spHttpNegotiate); 354 QueryServiceFromClient(&spHttpNegotiate);
351 return spHttpNegotiate ? spHttpNegotiate->BeginningTransaction(szURL, szHeader s,dwReserved, pszAdditionalHeaders) : S_OK;
352 }
353
354 STDMETHODIMP WBPassthruSink::OnResponse(DWORD dwResponseCode, LPCWSTR szResponse Headers, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
355 {
356 if (pszAdditionalRequestHeaders)
357 {
358 *pszAdditionalRequestHeaders = 0;
359 }
360
361 CComPtr<IHttpNegotiate> spHttpNegotiate;
362 QueryServiceFromClient(&spHttpNegotiate);
363 355
364 return spHttpNegotiate ? spHttpNegotiate->OnResponse(dwResponseCode, szRespons eHeaders, szRequestHeaders, pszAdditionalRequestHeaders) : S_OK; 356 return spHttpNegotiate ? spHttpNegotiate->OnResponse(dwResponseCode, szRespons eHeaders, szRequestHeaders, pszAdditionalRequestHeaders) : S_OK;
365 } 357 }
366 358
367 STDMETHODIMP WBPassthruSink::ReportProgress(ULONG ulStatusCode, LPCWSTR szStatus Text) 359 STDMETHODIMP WBPassthruSink::ReportProgress(ULONG ulStatusCode, LPCWSTR szStatus Text)
368 { 360 {
369 return m_spInternetProtocolSink ? m_spInternetProtocolSink->ReportProgress(ulS tatusCode, szStatusText) : S_OK; 361 return m_spInternetProtocolSink ? m_spInternetProtocolSink->ReportProgress(ulS tatusCode, szStatusText) : S_OK;
370 } 362 }
371 363
364 STDMETHODIMP WBPassthruSink::ReportResult(/* [in] */ HRESULT hrResult, /* [in] * / DWORD dwError, /* [in] */ LPCWSTR szResult)
365 {
366 if (m_isCustomResponse)
367 {
368 // Don't notify the client about aborting of the operation, thus don't call BaseClass::ReportResult.
369 // Current method is called by the original protocol implementation and we a re intercepting the
370 // call here and eating it, we will call the proper ReportResult later by ou rself.
371 return S_OK;
372 }
373 return BaseClass::ReportResult(hrResult, dwError, szResult);
374 }
375
376
377 WBPassthru::WBPassthru()
378 : m_shouldSupplyCustomContent(false)
379 {
380 }
372 381
373 STDMETHODIMP WBPassthru::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink , 382 STDMETHODIMP WBPassthru::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink ,
374 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) 383 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved)
375 { 384 {
376 ATLASSERT(m_spInternetProtocol != 0); 385 ATLASSERT(m_spInternetProtocol != 0);
377 if (!m_spInternetProtocol) 386 if (!m_spInternetProtocol)
378 { 387 {
379 return E_UNEXPECTED; 388 return E_UNEXPECTED;
380 } 389 }
381 390
382 return OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, 391 return OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, m_spInterne tProtocol);
383 dwReserved, m_spInternetProtocol); 392 }
384 } 393
385 394 STDMETHODIMP WBPassthru::Read(/* [in, out] */ void *pv,/* [in] */ ULONG cb,/* [o ut] */ ULONG *pcbRead)
386 STDMETHODIMP WBPassthru::Read(»/* [in, out] */ void *pv,/* [in] */ ULONG cb,/* [out] */ ULONG *pcbRead) 395 {
387 { 396 WBPassthruSink* pSink = GetSink();
388 397 return pSink->OnRead(pv, cb, pcbRead);
389 WBPassthruSink* pSink = GetSink(); 398 }
390 return pSink->Read(pv, cb, pcbRead);
391 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld