Left: | ||
Right: |
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 #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 <WinInet.h> | 10 #include <WinInet.h> |
13 #include "wtypes.h" | 11 #include "wtypes.h" |
14 | 12 |
15 namespace | 13 namespace |
16 { | 14 { |
17 std::string g_blockedByABPPage = "<!DOCTYPE html>" | 15 std::string g_blockedByABPPage = "<!DOCTYPE html>" |
18 "<html>" | 16 "<html>" |
19 "<body>" | 17 "<body>" |
20 "<!-- blocked by AdblockPlus -->" | 18 "<!-- blocked by AdblockPlus -->" |
21 "</body>" | 19 "</body>" |
22 "</html>"; | 20 "</html>"; |
23 } | 21 } |
24 | 22 |
25 WBPassthruSink::WBPassthruSink() | 23 WBPassthruSink::WBPassthruSink() |
26 : m_currentPositionOfSentPage(0) | 24 : m_currentPositionOfSentPage(0) |
Oleksandr
2014/09/21 23:30:40
I wouldn't be entirely sure that IE does not reuse
sergei
2014/09/22 16:18:05
It does not reuse them. If it happens we will be a
Oleksandr
2014/10/03 14:36:37
Even though I can't provide an example when this m
| |
27 , m_contentType(CFilter::EContentType::contentTypeAny) | 25 , m_contentType(CFilter::EContentType::contentTypeAny) |
28 , m_blockedInTransaction(false) | 26 , m_blockedInTransaction(false) |
29 { | 27 { |
30 } | 28 } |
31 | 29 |
32 int WBPassthruSink::GetContentTypeFromMimeType(const CString& mimeType) | 30 int WBPassthruSink::GetContentTypeFromMimeType(const CString& mimeType) |
33 { | 31 { |
34 if (mimeType.Find(L"image/") >= 0) | 32 if (mimeType.Find(L"image/") >= 0) |
35 { | 33 { |
36 return CFilter::contentTypeImage; | 34 return CFilter::contentTypeImage; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
94 { | 92 { |
95 return CFilter::contentTypeObject; | 93 return CFilter::contentTypeObject; |
96 } | 94 } |
97 else if (ext == L".jsp" || ext == L".php" || ext == L".html") | 95 else if (ext == L".jsp" || ext == L".php" || ext == L".html") |
98 { | 96 { |
99 return CFilter::contentTypeSubdocument; | 97 return CFilter::contentTypeSubdocument; |
100 } | 98 } |
101 return CFilter::contentTypeAny; | 99 return CFilter::contentTypeAny; |
102 } | 100 } |
103 | 101 |
104 int WBPassthruSink::GetContentType(const CString& mimeType, const CString& domai n, const CString& src) | 102 int WBPassthruSink::GetContentType(const CString& mimeType, const std::wstring& domain, const CString& src) |
105 { | 103 { |
106 // No referer or mime type | 104 // No referer or mime type |
107 // BINDSTRING_XDR_ORIGIN works only for IE v8+ | 105 // BINDSTRING_XDR_ORIGIN works only for IE v8+ |
108 if (mimeType.IsEmpty() && domain.IsEmpty() && CPluginClient::GetInstance()->Ge tIEVersion() >= 8) | 106 if (mimeType.IsEmpty() && domain.empty() && CPluginClient::GetInstance()->GetI EVersion() >= 8) |
109 { | 107 { |
110 return CFilter::contentTypeXmlHttpRequest; | 108 return CFilter::contentTypeXmlHttpRequest; |
111 } | 109 } |
112 int contentType = GetContentTypeFromMimeType(mimeType); | 110 int contentType = GetContentTypeFromMimeType(mimeType); |
113 if (contentType == CFilter::contentTypeAny) | 111 if (contentType == CFilter::contentTypeAny) |
114 { | 112 { |
115 contentType = GetContentTypeFromURL(src); | 113 contentType = GetContentTypeFromURL(src); |
116 } | 114 } |
117 return contentType; | 115 return contentType; |
118 } | 116 } |
119 | 117 |
120 //////////////////////////////////////////////////////////////////////////////// //////// | 118 //////////////////////////////////////////////////////////////////////////////// //////// |
121 //WBPassthruSink | 119 //WBPassthruSink |
122 //Monitor and/or cancel every request and responde | 120 //Monitor and/or cancel every request and responde |
123 //WB makes, including images, sounds, scripts, etc | 121 //WB makes, including images, sounds, scripts, etc |
124 //////////////////////////////////////////////////////////////////////////////// //////// | 122 //////////////////////////////////////////////////////////////////////////////// //////// |
125 HRESULT WBPassthruSink::OnStart(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSin k, | 123 HRESULT WBPassthruSink::OnStart(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSin k, |
126 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HAN DLE_PTR dwReserved, | 124 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HAN DLE_PTR dwReserved, |
127 IInternetProtocol* pTargetProtocol, bool& handle d) | 125 IInternetProtocol* pTargetProtocol, bool& handle d) |
128 { | 126 { |
129 m_pTargetProtocol = pTargetProtocol; | 127 m_pTargetProtocol = pTargetProtocol; |
130 bool isBlocked = false; | 128 bool isBlocked = false; |
131 CString src = szUrl; | 129 CString src = szUrl; |
132 DEBUG_GENERAL(src); | 130 DEBUG_GENERAL(src); |
133 CPluginClient::UnescapeUrl(src); | 131 CPluginClient::UnescapeUrl(src); |
134 | 132 |
135 // call the impl of the base class as soon as possible because it initializes the base class | 133 // call the impl of the base class as soon as possible because it initializes the base class |
136 // members, used by this method. It queries for the required interfaces. | 134 // members, used by this method. It queries for the required interfaces. |
137 HRESULT hr = BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwRese rved, pTargetProtocol); | 135 HRESULT hr = BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwRese rved, pTargetProtocol); |
Oleksandr
2014/09/21 23:30:40
I still have my concerns if the requests are actua
sergei
2014/09/22 16:18:05
I have checked it before and now again, it works i
Oleksandr
2014/10/03 14:36:37
Not really. Just wanted to double check if you've
| |
138 if (FAILED(hr)) | 136 if (FAILED(hr)) |
139 { | 137 { |
140 return hr; | 138 return hr; |
141 } | 139 } |
142 | 140 |
143 CString mimeType; | 141 CString mimeType; |
144 if (pOIBindInfo) | 142 if (pOIBindInfo) |
145 { | 143 { |
146 ULONG resLen = 0; | 144 ULONG resLen = 0; |
147 | 145 |
(...skipping 17 matching lines...) Expand all Loading... | |
165 } | 163 } |
166 } | 164 } |
167 // We can obtain IBindCtx* here, but IEnumString obtained via IBindCtx::Enum ObjectParam | 165 // We can obtain IBindCtx* here, but IEnumString obtained via IBindCtx::Enum ObjectParam |
168 // does not return any parameter, so it's useless. | 166 // does not return any parameter, so it's useless. |
169 } | 167 } |
170 | 168 |
171 CString cookie; | 169 CString cookie; |
172 ULONG len1 = 2048; | 170 ULONG len1 = 2048; |
173 ULONG len2 = 2048; | 171 ULONG len2 = 2048; |
174 | 172 |
175 #ifdef SUPPORT_FILTER | |
176 CPluginTab* tab = CPluginClass::GetTab(::GetCurrentThreadId()); | 173 CPluginTab* tab = CPluginClass::GetTab(::GetCurrentThreadId()); |
177 CPluginClient* client = CPluginClient::GetInstance(); | 174 CPluginClient* client = CPluginClient::GetInstance(); |
178 | 175 |
179 if (tab && client) | 176 if (tab && client) |
180 { | 177 { |
181 CString documentUrl = tab->GetDocumentUrl(); | 178 CString documentUrl = tab->GetDocumentUrl(); |
182 // Page is identical to document => don't block | 179 // Page is identical to document => don't block |
183 if (documentUrl == src) | 180 if (documentUrl == src) |
184 { | 181 { |
185 // fall through | 182 // fall through |
186 } | 183 } |
187 else if (CPluginSettings::GetInstance()->IsPluginEnabled() && !client->IsWhi telistedUrl(std::wstring(documentUrl))) | 184 else if (CPluginSettings::GetInstance()->IsPluginEnabled() && !client->IsWhi telistedUrl(std::wstring(documentUrl))) |
188 { | 185 { |
189 m_boundDomain = tab->GetDocumentUrl(); | 186 m_boundDomain = tab->GetDocumentUrl(); |
190 m_contentType = CFilter::contentTypeAny; | 187 m_contentType = CFilter::contentTypeAny; |
191 #ifdef SUPPORT_FRAME_CACHING | 188 if (tab != nullptr && tab->IsFrameCached(src)) |
192 if (nullptr != tab && tab->IsFrameCached(src)) | |
Oleksandr
2014/09/21 23:30:40
No yoda conditions, please
if (tab != nullptr && .
| |
193 { | 189 { |
194 m_contentType = CFilter::contentTypeSubdocument; | 190 m_contentType = CFilter::contentTypeSubdocument; |
195 } | 191 } |
196 else | 192 else |
197 #endif // SUPPORT_FRAME_CACHING | |
198 { | 193 { |
199 m_contentType = GetContentType(mimeType, m_boundDomain, src); | 194 m_contentType = GetContentType(mimeType, m_boundDomain, src); |
200 } | 195 } |
201 } | 196 } |
202 } | 197 } |
203 | 198 |
204 if (nullptr == tab) | 199 if (tab == nullptr) |
Oleksandr
2014/09/21 23:30:40
No yoda conditions, please
| |
205 { | 200 { |
206 m_contentType = GetContentType(mimeType, m_boundDomain, src); | 201 m_contentType = GetContentType(mimeType, m_boundDomain, src); |
207 } | 202 } |
208 | 203 |
209 { | 204 { |
210 // Here is the heuristic which detects the requests issued by Flash.ocx. | 205 // Here is the heuristic which detects the requests issued by Flash.ocx. |
211 // It turned out that the implementation from ''Flash.ocx'' (tested version is 15.0.0.152) | 206 // It turned out that the implementation from ''Flash.ocx'' (tested version is 15.0.0.152) |
212 // returns quite minimal configuration in comparison with the implementation from Microsofts' | 207 // returns quite minimal configuration in comparison with the implementation from Microsofts' |
213 // libraries (see grfBINDF and bindInfo.dwOptions). The impl from MS often i ncludes something | 208 // libraries (see grfBINDF and bindInfo.dwOptions). The impl from MS often i ncludes something |
214 // else. | 209 // else. |
215 ATL::CComPtr<IBindStatusCallback> bscb; | 210 ATL::CComPtr<IBindStatusCallback> bscb; |
216 if (SUCCEEDED(QueryServiceFromClient(&bscb)) && !!bscb) | 211 if (SUCCEEDED(QueryServiceFromClient(&bscb)) && !!bscb) |
217 { | 212 { |
218 DWORD grfBINDF = 0; | 213 DWORD grfBINDF = 0; |
219 BINDINFO bindInfo = {}; | 214 BINDINFO bindInfo = {}; |
220 bindInfo.cbSize = sizeof(bindInfo); | 215 bindInfo.cbSize = sizeof(bindInfo); |
221 if (SUCCEEDED(bscb->GetBindInfo(&grfBINDF, &bindInfo)) | 216 if (SUCCEEDED(bscb->GetBindInfo(&grfBINDF, &bindInfo)) |
222 && (BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE| BINDF_PULLDATA) == grfBINDF | 217 && (BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE| BINDF_PULLDATA) == grfBINDF |
223 && (BINDINFO_OPTIONS_ENABLE_UTF8 | BINDINFO_OPTIONS_USE_IE_ENCODING) == bindInfo.dwOptions | 218 && (BINDINFO_OPTIONS_ENABLE_UTF8 | BINDINFO_OPTIONS_USE_IE_ENCODING) == bindInfo.dwOptions |
224 ) | 219 ) |
Oleksandr
2014/09/21 23:30:40
This looks quite neat, however can you maybe test
sergei
2014/09/22 16:18:05
I will test it with different <IE, Flash> as far a
| |
225 { | 220 { |
226 m_contentType = CFilter::EContentType::contentTypeObjectSubrequest; | 221 m_contentType = CFilter::EContentType::contentTypeObjectSubrequest; |
227 } | 222 } |
228 } | 223 } |
229 } | 224 } |
230 | 225 |
231 // The descision about EContentType::contentTypeAny is made later in | 226 // The descision about EContentType::contentTypeAny is made later in |
232 // WBPassthruSink::BeginningTransaction. Sometimes here we cannot detect the r equest type, but | 227 // WBPassthruSink::BeginningTransaction. Sometimes here we cannot detect the r equest type, but |
233 // in WBPassthruSink::BeginningTransaction the header Accept is available whic h allows to | 228 // in WBPassthruSink::BeginningTransaction the header Accept is available whic h allows to |
234 // obtain the "request type" in our terminology. | 229 // obtain the "request type" in our terminology. |
235 if (nullptr != client | 230 if (nullptr != client |
236 && CFilter::EContentType::contentTypeAny != m_contentType | 231 && CFilter::EContentType::contentTypeAny != m_contentType |
237 && client->ShouldBlock(src, m_contentType, m_boundDomain, true)) | 232 && client->ShouldBlock(static_cast<const wchar_t*>(src), m_contentType, m_bo undDomain, true)) |
238 { | 233 { |
239 isBlocked = true; | 234 isBlocked = true; |
240 } | 235 } |
241 | 236 |
242 // For IE6 and earlier there is iframe back button issue, so avoid it. | 237 // For IE6 and earlier there is iframe back button issue, so avoid it. |
243 if (isBlocked && client->GetIEVersion() > 6) | 238 if (isBlocked && client->GetIEVersion() > 6) |
244 { | 239 { |
245 handled = true; | 240 handled = true; |
246 if (CFilter::EContentType::contentTypeImage == m_contentType) | 241 if (CFilter::EContentType::contentTypeImage == m_contentType) |
247 { | 242 { |
248 // IE shows a cross that img is not loaded | 243 // IE shows a cross that img is not loaded |
Oleksandr
2014/09/21 23:30:40
Does this happen even if we "eat" the ReportResult
sergei
2014/09/22 16:18:05
Have not tested yet, also I'm afraid that sending
Oleksandr
2014/10/03 14:36:37
This can go into other review anyway.
On 2014/09/2
| |
249 return INET_E_REDIRECT_FAILED; | 244 return INET_E_REDIRECT_FAILED; |
250 } | 245 } |
251 if (CFilter::EContentType::contentTypeSubdocument == m_contentType) | 246 if (CFilter::EContentType::contentTypeSubdocument == m_contentType) |
252 { | 247 { |
253 PassthroughAPP::CustomSinkStartPolicy<WBPassthru, WBPassthruSink>::GetProt ocol(this)->m_shouldSupplyCustomContent = true; | 248 PassthroughAPP::CustomSinkStartPolicy<WBPassthru, WBPassthruSink>::GetProt ocol(this)->m_shouldSupplyCustomContent = true; |
254 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t ext/html"); | 249 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t ext/html"); |
255 m_spInternetProtocolSink->ReportData(BSCF_FIRSTDATANOTIFICATION, 0, static _cast<ULONG>(g_blockedByABPPage.size())); | 250 m_spInternetProtocolSink->ReportData(BSCF_FIRSTDATANOTIFICATION, 0, static _cast<ULONG>(g_blockedByABPPage.size())); |
256 return S_OK; | 251 return S_OK; |
257 } | 252 } |
258 if (CFilter::EContentType::contentTypeScript == m_contentType) | 253 if (CFilter::EContentType::contentTypeScript == m_contentType) |
259 { | 254 { |
260 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t ext/javascript"); | 255 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t ext/javascript"); |
261 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:"); | 256 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:"); |
262 return INET_E_REDIRECT_FAILED; | 257 return INET_E_REDIRECT_FAILED; |
263 } | 258 } |
264 if (CFilter::EContentType::contentTypeXmlHttpRequest == m_contentType) | 259 if (CFilter::EContentType::contentTypeXmlHttpRequest == m_contentType) |
265 { | 260 { |
266 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:"); | 261 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:"); |
267 return INET_E_REDIRECT_FAILED; | 262 return INET_E_REDIRECT_FAILED; |
268 } | 263 } |
269 if (CFilter::EContentType::contentTypeAny != m_contentType) | 264 if (CFilter::EContentType::contentTypeAny != m_contentType) |
270 { | 265 { |
271 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:"); | 266 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:"); |
272 return INET_E_REDIRECT_FAILED; | 267 return INET_E_REDIRECT_FAILED; |
273 } | 268 } |
274 } | 269 } |
275 #endif // SUPPORT_FILTER | |
276 | 270 |
277 return isBlocked ? S_FALSE : hr; | 271 return isBlocked ? S_FALSE : hr; |
278 } | 272 } |
279 | 273 |
280 HRESULT WBPassthruSink::OnRead(void* pv, ULONG cb, ULONG* pcbRead) | 274 HRESULT WBPassthruSink::OnRead(void* pv, ULONG cb, ULONG* pcbRead) |
281 { | 275 { |
282 if (nullptr == pv) | 276 if (pv == nullptr) |
Oleksandr
2014/09/21 23:30:40
if (pv == nullptr) looks better, imho
| |
283 { | 277 { |
284 return E_POINTER; | 278 return E_POINTER; |
285 } | 279 } |
286 if (nullptr == pcbRead) | 280 if (pcbRead == nullptr) |
Oleksandr
2014/09/21 23:30:40
Same as above
| |
287 { | 281 { |
288 return E_POINTER; | 282 return E_POINTER; |
289 } | 283 } |
290 *pcbRead = 0; | 284 *pcbRead = 0; |
291 | 285 |
292 if (PassthroughAPP::CustomSinkStartPolicy<WBPassthru, WBPassthruSink>::GetProt ocol(this)->m_shouldSupplyCustomContent) | 286 if (PassthroughAPP::CustomSinkStartPolicy<WBPassthru, WBPassthruSink>::GetProt ocol(this)->m_shouldSupplyCustomContent) |
293 { | 287 { |
294 ULONG myPageSize = static_cast<ULONG>(g_blockedByABPPage.size()); | 288 ULONG blockedByABPPageSize = static_cast<ULONG>(g_blockedByABPPage.size()); |
Oleksandr
2014/09/21 23:30:40
abpPageSize would be a better name, IMHO
sergei
2014/09/22 16:18:05
Sorry, forgot to change the name. During the playi
| |
295 auto positionGrow = std::min<ULONG>(cb, static_cast<ULONG>(g_blockedByABPPag e.size() - m_currentPositionOfSentPage)); | 289 auto positionGrow = std::min<ULONG>(cb, static_cast<ULONG>(blockedByABPPageS ize - m_currentPositionOfSentPage)); |
296 if (0 == positionGrow) { | 290 if (positionGrow == 0) { |
Oleksandr
2014/09/21 23:30:40
positionGrow == 0 seems more logical
| |
297 return S_FALSE; | 291 return S_FALSE; |
298 } | 292 } |
299 std::copy(g_blockedByABPPage.begin(), g_blockedByABPPage.begin() + positionG row, | 293 std::copy(g_blockedByABPPage.begin(), g_blockedByABPPage.begin() + positionG row, |
300 stdext::make_checked_array_iterator(static_cast<char*>(pv), cb)); | 294 stdext::make_checked_array_iterator(static_cast<char*>(pv), cb)); |
Oleksandr
2014/09/21 23:30:40
So this will throw a runtime error if cb < positio
sergei
2014/09/22 16:18:05
- It's not possible to compile without checked ite
Oleksandr
2014/10/03 14:36:37
I suppose you could use memcpy here instead, but I
| |
301 *pcbRead = positionGrow; | 295 *pcbRead = positionGrow; |
302 m_currentPositionOfSentPage += positionGrow; | 296 m_currentPositionOfSentPage += positionGrow; |
303 | 297 |
304 if (m_spInternetProtocolSink) | 298 if (m_spInternetProtocolSink) |
305 { | 299 { |
306 m_spInternetProtocolSink->ReportData(BSCF_INTERMEDIATEDATANOTIFICATION, | 300 m_spInternetProtocolSink->ReportData(BSCF_INTERMEDIATEDATANOTIFICATION, |
307 static_cast<ULONG>(m_currentPositionOfSentPage), myPageSize); | 301 static_cast<ULONG>(m_currentPositionOfSentPage), blockedByABPPageSize); |
308 } | 302 } |
309 if (myPageSize == m_currentPositionOfSentPage && m_spInternetProtocolSink) | 303 if (blockedByABPPageSize == m_currentPositionOfSentPage && m_spInternetProto colSink) |
310 { | 304 { |
311 m_spInternetProtocolSink->ReportData(BSCF_DATAFULLYAVAILABLE, myPageSize, myPageSize); | 305 m_spInternetProtocolSink->ReportData(BSCF_DATAFULLYAVAILABLE, blockedByABP PageSize, blockedByABPPageSize); |
312 m_spInternetProtocolSink->ReportResult(S_OK, 0, nullptr); | 306 m_spInternetProtocolSink->ReportResult(S_OK, 0, nullptr); |
313 } | 307 } |
314 return S_OK; | 308 return S_OK; |
315 } | 309 } |
316 return m_pTargetProtocol->Read(pv, cb, pcbRead); | 310 return m_pTargetProtocol->Read(pv, cb, pcbRead); |
317 } | 311 } |
318 STDMETHODIMP WBPassthruSink::Switch( | 312 STDMETHODIMP WBPassthruSink::Switch( |
319 /* [in] */ PROTOCOLDATA *pProtocolData) | 313 /* [in] */ PROTOCOLDATA *pProtocolData) |
320 { | 314 { |
321 ATLASSERT(m_spInternetProtocolSink != 0); | 315 ATLASSERT(m_spInternetProtocolSink != 0); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
469 } | 463 } |
470 | 464 |
471 STDMETHODIMP WBPassthru::UnlockRequest() | 465 STDMETHODIMP WBPassthru::UnlockRequest() |
472 { | 466 { |
473 if (!m_hasOriginalStartCalled) | 467 if (!m_hasOriginalStartCalled) |
474 { | 468 { |
475 return S_OK; | 469 return S_OK; |
476 } | 470 } |
477 return BaseClass::UnlockRequest(); | 471 return BaseClass::UnlockRequest(); |
478 } | 472 } |
LEFT | RIGHT |