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: Created June 21, 2014, 8:25 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>"
18 "<html>"
19 "<body>"
20 "<!-- blocked by AdblockPlus -->"
21 "</body>"
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 }
20 74
21 WBPassthruSink::WBPassthruSink() 75 WBPassthruSink::WBPassthruSink()
22 { 76 : m_currentPositionOfSentPage(0)
23 m_pTargetProtocol = NULL; 77 , m_contentType(CFilter::EContentType::contentTypeAny)
24 } 78 , m_isCustomResponse(false)
25 int WBPassthruSink::GetContentTypeFromMimeType( std::wstring mime_type ) 79 {
26 { 80 }
27 if ( mime_type.find( L"image/" ) != std::wstring::npos ) 81
82 int WBPassthruSink::GetContentTypeFromMimeType(const CString& mimeType)
83 {
84 if (mimeType.Find(L"image/") >= 0)
28 { 85 {
29 return CFilter::contentTypeImage; 86 return CFilter::contentTypeImage;
30 } 87 }
31 if ( mime_type.find( L"text/css" ) != std::wstring::npos ) 88 if (mimeType.Find(L"text/css") >= 0)
32 { 89 {
33 return CFilter::contentTypeStyleSheet; 90 return CFilter::contentTypeStyleSheet;
34 } 91 }
35 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))
36 || mime_type.find( L"application/json" ) != std::wstring::npos )
37 { 93 {
38 return CFilter::contentTypeScript; 94 return CFilter::contentTypeScript;
39 } 95 }
40 if ( mime_type.find( L"application/x-shockwave-flash" ) != std::wstring::npos ) 96 if (mimeType.Find(L"application/x-shockwave-flash") >= 0)
41 { 97 {
42 return CFilter::contentTypeObject; 98 return CFilter::contentTypeObject;
43 } 99 }
44 if ( mime_type.find( L"text/html" ) != std::wstring::npos ) 100 if (mimeType.Find(L"text/html") >= 0)
45 { 101 {
46 return CFilter::contentTypeSubdocument; 102 return CFilter::contentTypeSubdocument;
47 } 103 }
48 // 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
49 if ( mime_type.find( L"xml" ) != std::wstring::npos ) 105 if (mimeType.Find(L"xml") >= 0)
50 { 106 {
51 return CFilter::contentTypeXmlHttpRequest; 107 return CFilter::contentTypeXmlHttpRequest;
52 } 108 }
109
53 return CFilter::contentTypeAny; 110 return CFilter::contentTypeAny;
54 } 111 }
55 112
56 int WBPassthruSink::GetContentTypeFromURL( std::wstring src ) 113 int WBPassthruSink::GetContentTypeFromURL(const CString& src)
57 { 114 {
58 // Start search for extension at beginning of query, if any 115 CString srcExt = src;
59 size_t ext_end = src.find( L'?' ); 116
60 // Assert ext_end <= src.length --> src[ ext_end ] == '?' 117 int pos = 0;
61 // 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)
62 119 {
63 // Locate punctuation for extension, if any 120 srcExt = src.Left(pos);
64 size_t ext_begin = src.rfind( L'.', ext_end ); 121 }
65 if ( ext_begin == std::wstring::npos ) 122
66 { 123 int lastDotIndex = srcExt.ReverseFind('.');
67 // No punctuation 124 if (lastDotIndex < 0)
68 return CFilter::contentTypeAny; 125 return CFilter::contentTypeAny;
69 } 126 CString ext = srcExt.Mid(lastDotIndex);
70 // Adding 1 to ext_begin excludes punctuation 127 if (ext == L".jpg" || ext == L".gif" || ext == L".png" || ext == L".jpeg")
71 std::wstring ext = src.substr( ext_begin + 1, ext_end );
72 // Assert ext contains all text after last period character to beginning of qu ery, or if no query, to end of string
73
74 if (ext == L"jpg" || ext == L"gif" || ext == L"png" || ext == L"jpeg")
75 { 128 {
76 return CFilter::contentTypeImage; 129 return CFilter::contentTypeImage;
77 } 130 }
78 else if (ext == L"css") 131 else if (ext == L".css")
79 { 132 {
80 return CFilter::contentTypeStyleSheet; 133 return CFilter::contentTypeStyleSheet;
81 } 134 }
82 // Test for "jsp" before "js*" below 135 else if (ext.Right(3) == L".js")
83 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")
84 { 148 {
85 return CFilter::contentTypeSubdocument; 149 return CFilter::contentTypeSubdocument;
86 } 150 }
87 else if ( ABP::util::begins_with( ext, L"js" ) ) 151 return CFilter::contentTypeAny;
88 { 152 }
89 return CFilter::contentTypeScript; 153
90 } 154 int WBPassthruSink::GetContentType(const CString& mimeType, const std::wstring& domain, const CString& src)
91 else if (ext == L"xml")
92 {
93 return CFilter::contentTypeXmlHttpRequest;
94 }
95 else if (ext == L"swf")
96 {
97 return CFilter::contentTypeObject;
98 }
99 else
100 {
101 return CFilter::contentTypeAny & ~CFilter::contentTypeSubdocument;
102 }
103
104 }
105
106 int WBPassthruSink::GetContentType(std::wstring mimeType, std::wstring domain, s td::wstring src)
107 { 155 {
108 // No referer or mime type 156 // No referer or mime type
109 // BINDSTRING_XDR_ORIGIN works only for IE v8+ 157 // BINDSTRING_XDR_ORIGIN works only for IE v8+
110 if ( mimeType.empty() && domain.empty() ) 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
111 { 159 {
112 return CFilter::contentTypeXmlHttpRequest; 160 return CFilter::contentTypeXmlHttpRequest;
113 } 161 }
114 int contentType = GetContentTypeFromMimeType(mimeType); 162 int contentType = GetContentTypeFromMimeType(mimeType);
115 if (contentType == CFilter::contentTypeAny) 163 if (contentType == CFilter::contentTypeAny)
116 { 164 {
117 contentType = GetContentTypeFromURL(src); 165 contentType = GetContentTypeFromURL(src);
118 } 166 }
119 return contentType; 167 return contentType;
120 } 168 }
121 169
122 //////////////////////////////////////////////////////////////////////////////// //////// 170 //////////////////////////////////////////////////////////////////////////////// ////////
123 //WBPassthruSink 171 //WBPassthruSink
124 //Monitor and/or cancel every request and responde 172 //Monitor and/or cancel every request and responde
125 //WB makes, including images, sounds, scripts, etc 173 //WB makes, including images, sounds, scripts, etc
126 //////////////////////////////////////////////////////////////////////////////// //////// 174 //////////////////////////////////////////////////////////////////////////////// ////////
127 HRESULT WBPassthruSink::OnStart(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSin k, 175 HRESULT WBPassthruSink::OnStart(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSin k,
128 IInternetBindInfo *pOIBindInfo, DWORD grfPI, DWO RD dwReserved, 176 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HAN DLE_PTR dwReserved,
129 IInternetProtocol* pTargetProtocol) 177 IInternetProtocol* pTargetProtocol, bool& handle d)
130 { 178 {
131
132 m_pTargetProtocol = pTargetProtocol; 179 m_pTargetProtocol = pTargetProtocol;
133 bool isBlocked = false; 180 return BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTargetProtocol);
134 m_shouldBlock = false; 181 }
135 m_lastDataReported = false; 182
136 std::wstring src( szUrl ); 183 HRESULT WBPassthruSink::OnRead(void* pv, ULONG cb, ULONG* pcbRead)
137 DEBUG_GENERAL(src); 184 {
138 Wrapper::Unescape_URL( src ); 185 if (!pv || !pcbRead)
139 186 {
140 std::wstring boundDomain; 187 return E_POINTER;
141 std::wstring mime_type; 188 }
142 if (pOIBindInfo) 189 *pcbRead = 0;
143 { 190
144 Wrapper::Internet_Bind_Info bi( pOIBindInfo ); 191 if (PassthroughAPP::CustomSinkStartPolicy<WBPassthru, WBPassthruSink>::GetProt ocol(this)->m_shouldSupplyCustomContent)
145 mime_type = bi.bind_string_single( BINDSTRING_ACCEPT_MIMES ); 192 {
146 std::wstring bind_to_object = bi.bind_string_single( BINDSTRING_FLAG_BIND_TO _OBJECT ); 193 ULONG blockedByABPPageSize = static_cast<ULONG>(g_blockedByABPPage.size());
147 ABP::util::to_lower( bind_to_object ); 194 auto positionGrow = std::min<ULONG>(cb, static_cast<ULONG>(blockedByABPPageS ize - m_currentPositionOfSentPage));
148 if ( bind_to_object == L"" || bind_to_object == L"false" ) 195 if (positionGrow == 0) {
149 { 196 return S_FALSE;
150 boundDomain = bi.bind_string_single( BINDSTRING_XDR_ORIGIN ); 197 }
151 } 198 std::copy(g_blockedByABPPage.begin(), g_blockedByABPPage.begin() + positionG row,
152 } 199 stdext::make_checked_array_iterator(static_cast<char*>(pv), cb));
153 200 *pcbRead = positionGrow;
154 #ifdef SUPPORT_FILTER 201 m_currentPositionOfSentPage += positionGrow;
155 int contentType = CFilter::contentTypeAny; 202
156 203 if (m_spInternetProtocolSink)
157 CPluginTab* tab = CPluginClass::GetTab(::GetCurrentThreadId()); 204 {
158 CPluginClient* client = CPluginClient::GetInstance(); 205 m_spInternetProtocolSink->ReportData(BSCF_INTERMEDIATEDATANOTIFICATION,
159 206 static_cast<ULONG>(m_currentPositionOfSentPage), blockedByABPPageSize);
160 207 }
161 if (tab && client) 208 if (blockedByABPPageSize == m_currentPositionOfSentPage && m_spInternetProto colSink)
162 { 209 {
163 std::wstring documentUrl = tab->GetDocumentUrl(); 210 m_spInternetProtocolSink->ReportData(BSCF_DATAFULLYAVAILABLE, blockedByABP PageSize, blockedByABPPageSize);
164 // Page is identical to document => don't block 211 m_spInternetProtocolSink->ReportResult(S_OK, 0, nullptr);
165 if (documentUrl == src)
166 {
167 // fall through
168 }
169 else if (CPluginSettings::GetInstance()->IsPluginEnabled() && !client->IsWhi telistedUrl( documentUrl ))
170 {
171 boundDomain = tab->GetDocumentUrl();
172
173 contentType = CFilter::contentTypeAny;
174
175 #ifdef SUPPORT_FRAME_CACHING
176 if ((tab != 0) && (tab->IsFrameCached(src)))
177 {
178 contentType = CFilter::contentTypeSubdocument;
179 }
180 else
181 #endif // SUPPORT_FRAME_CACHING
182 contentType = GetContentType( mime_type, boundDomain, src );
183 if (client->ShouldBlock(src, contentType, boundDomain, true))
184 {
185 isBlocked = true;
186
187 DEBUG_BLOCKER("Blocker::Blocking Http-request:" + src);
188 }
189 }
190 if (!isBlocked)
191 {
192 DEBUG_BLOCKER("Blocker::Ignoring Http-request:" + src)
193 }
194 }
195
196
197 if (tab == NULL)
198 {
199 contentType = GetContentType( mime_type, boundDomain, src);
200 if (client->ShouldBlock(src, contentType, boundDomain, true))
201 {
202 isBlocked = true;
203 }
204 }
205
206 #ifdef _DEBUG
207 std::wstring type;
208
209 if (contentType == CFilter::contentTypeDocument) type = L"DOCUMENT";
210 else if (contentType == CFilter::contentTypeObject) type = L"OBJECT";
211 else if (contentType == CFilter::contentTypeImage) type = L"IMAGE";
212 else if (contentType == CFilter::contentTypeScript) type = L"SCRIPT";
213 else if (contentType == CFilter::contentTypeOther) type = L"OTHER";
214 else if (contentType == CFilter::contentTypeUnknown) type = L"OTHER";
215 else if (contentType == CFilter::contentTypeSubdocument) type = L"SUBDOCUMENT" ;
216 else if (contentType == CFilter::contentTypeStyleSheet) type = L"STYLESHEET";
217 else type = L"OTHER";
218
219 if (isBlocked)
220 {
221 CPluginDebug::DebugResultBlocking(type, src, boundDomain);
222 }
223 else
224 {
225 CPluginDebug::DebugResultIgnoring(type, src, boundDomain);
226 }
227 #endif
228
229 //Fixes the iframe back button issue
230 if ((contentType == CFilter::contentTypeImage) && (isBlocked))
231 {
232 m_shouldBlock = true;
233 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTarg etProtocol);
234
235 return INET_E_REDIRECT_FAILED;
236
237 }
238 if (((contentType == CFilter::contentTypeSubdocument))&& (isBlocked))
239 {
240 m_shouldBlock = true;
241 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTarg etProtocol);
242
243 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"tex t/html");
244
245 //Here we check if we are running on Windows 8 Consumer Preview.
246 //For some reason on that environment the next line causes IE to crash
247 if (CPluginSettings::GetInstance()->GetWindowsBuildNumber() != 8250)
248 {
249 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"res://ms html.dll/blank.htm");
250 }
251
252 return INET_E_REDIRECT_FAILED;
253 }
254 if (((contentType == CFilter::contentTypeScript))&& (isBlocked))
255 {
256 m_shouldBlock = true;
257 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTarg etProtocol);
258 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"tex t/javascript");
259 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:");
260 return INET_E_REDIRECT_FAILED;
261 }
262 if ((isBlocked))
263 {
264 m_shouldBlock = true;
265 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTarg etProtocol);
266 m_spInternetProtocolSink->ReportResult(S_FALSE, 0, L"");
267
268 return INET_E_REDIRECT_FAILED;
269 }
270 #endif // SUPPORT_FILTER
271
272 return isBlocked ? S_FALSE : BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInf o, grfPI, dwReserved, pTargetProtocol);
273 }
274
275
276 HRESULT WBPassthruSink::Read(void *pv, ULONG cb, ULONG* pcbRead)
277 {
278 if (m_shouldBlock)
279 {
280 *pcbRead = 0;
281 if (!m_lastDataReported)
282 {
283 if (cb <= 1)
284 {
285 //IE must've gone nuts if this happened, but let's be cool about it and report we have no more data
286 m_spInternetProtocolSink->ReportResult(S_FALSE, 0, NULL);
287 return S_FALSE;
288 }
289 *pcbRead = 1;
290 memcpy(pv, " ", 1);
291
292 if (m_spInternetProtocolSink != NULL)
293 {
294 m_spInternetProtocolSink->ReportResult(S_OK, 0, NULL);
295 }
296 m_lastDataReported = true;
297 m_shouldBlock = false;
298 return S_OK;
299 } 212 }
300 return S_OK; 213 return S_OK;
301 } 214 }
302 else 215 return m_pTargetProtocol->Read(pv, cb, pcbRead);
303 {
304
305 return m_pTargetProtocol->Read(pv, cb, pcbRead);
306 }
307 return S_OK;
308 } 216 }
309 STDMETHODIMP WBPassthruSink::Switch( 217 STDMETHODIMP WBPassthruSink::Switch(
310 /* [in] */ PROTOCOLDATA *pProtocolData) 218 /* [in] */ PROTOCOLDATA *pProtocolData)
311 { 219 {
312 ATLASSERT(m_spInternetProtocolSink != 0); 220 ATLASSERT(m_spInternetProtocolSink != 0);
313 221
314 /* 222 /*
315 From Igor Tandetnik "itandetnik@mvps.org" 223 From Igor Tandetnik "itandetnik@mvps.org"
316 " 224 "
317 Beware multithreading. URLMon has this nasty habit of spinning worker 225 Beware multithreading. URLMon has this nasty habit of spinning worker
318 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
319 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
320 such a thread, bad things happen (random crashes, events being lost). 228 such a thread, bad things happen (random crashes, events being lost).
321 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.
322 First, in methods of interfaces that were obtained with 230 First, in methods of interfaces that were obtained with
323 IServiceProvider, such as IHttpNegotiage::BeginningTransaction or 231 IServiceProvider, such as IHttpNegotiage::BeginningTransaction or
324 IAuthenticate::Authenticate. Second, you can call 232 IAuthenticate::Authenticate. Second, you can call
325 IInternetProtocolSink::Switch with PD_FORCE_SWITCH flag in 233 IInternetProtocolSink::Switch with PD_FORCE_SWITCH flag in
326 PROTOCOLDATA::grfFlags, eventually URLMon will turn around and call 234 PROTOCOLDATA::grfFlags, eventually URLMon will turn around and call
327 IInternetProtocol::Continue on the main thread. 235 IInternetProtocol::Continue on the main thread.
328 236
329 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
330 thread, you can post yourself a message. 238 thread, you can post yourself a message.
331 " 239 "
332 */ 240 */
333 return m_spInternetProtocolSink ? m_spInternetProtocolSink->Switch(pProtocolDa ta) : E_UNEXPECTED; 241 return m_spInternetProtocolSink ? m_spInternetProtocolSink->Switch(pProtocolDa ta) : E_UNEXPECTED;
334 } 242 }
335 243
336 244 // This is the heuristic which detects the requests issued by Flash.ocx.
337 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)
338 { 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
339 if (pszAdditionalHeaders) 288 if (pszAdditionalHeaders)
340 { 289 {
341 *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;
342 } 351 }
343 352
344 CComPtr<IHttpNegotiate> spHttpNegotiate; 353 CComPtr<IHttpNegotiate> spHttpNegotiate;
345 QueryServiceFromClient(&spHttpNegotiate); 354 QueryServiceFromClient(&spHttpNegotiate);
346 return spHttpNegotiate ? spHttpNegotiate->BeginningTransaction(szURL, szHeader s,dwReserved, pszAdditionalHeaders) : S_OK;
347 }
348
349 STDMETHODIMP WBPassthruSink::OnResponse(DWORD dwResponseCode, LPCWSTR szResponse Headers, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
350 {
351 if (pszAdditionalRequestHeaders)
352 {
353 *pszAdditionalRequestHeaders = 0;
354 }
355
356 CComPtr<IHttpNegotiate> spHttpNegotiate;
357 QueryServiceFromClient(&spHttpNegotiate);
358 355
359 return spHttpNegotiate ? spHttpNegotiate->OnResponse(dwResponseCode, szRespons eHeaders, szRequestHeaders, pszAdditionalRequestHeaders) : S_OK; 356 return spHttpNegotiate ? spHttpNegotiate->OnResponse(dwResponseCode, szRespons eHeaders, szRequestHeaders, pszAdditionalRequestHeaders) : S_OK;
360 } 357 }
361 358
362 STDMETHODIMP WBPassthruSink::ReportProgress(ULONG ulStatusCode, LPCWSTR szStatus Text) 359 STDMETHODIMP WBPassthruSink::ReportProgress(ULONG ulStatusCode, LPCWSTR szStatus Text)
363 { 360 {
364 return m_spInternetProtocolSink ? m_spInternetProtocolSink->ReportProgress(ulS tatusCode, szStatusText) : S_OK; 361 return m_spInternetProtocolSink ? m_spInternetProtocolSink->ReportProgress(ulS tatusCode, szStatusText) : S_OK;
365 } 362 }
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 }
381
382 STDMETHODIMP WBPassthru::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink ,
383 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved)
384 {
385 ATLASSERT(m_spInternetProtocol != 0);
386 if (!m_spInternetProtocol)
387 {
388 return E_UNEXPECTED;
389 }
390
391 return OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, m_spInterne tProtocol);
392 }
393
394 STDMETHODIMP WBPassthru::Read(/* [in, out] */ void *pv,/* [in] */ ULONG cb,/* [o ut] */ ULONG *pcbRead)
395 {
396 WBPassthruSink* pSink = GetSink();
397 return pSink->OnRead(pv, cb, pcbRead);
398 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld