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

Side by Side Diff: src/plugin/PluginHttpRequest.cpp

Issue 11013110: Cleanup (Closed)
Patch Set: Minor CallEngine refactoring Created July 26, 2013, 2:12 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 #include "PluginStdAfx.h"
2
3 #include "PluginIniFile.h"
4 #include "PluginChecksum.h"
5 #include "PluginHttpRequest.h"
6 #include "PluginClient.h"
7 #include "PluginSettings.h"
8 #include "PluginSystem.h"
9 #include "config.h"
10
11 #include <winhttp.h>
12
13
14 //class to ensure that HInternet always is closed
15 class HINTERNETHandle
16 {
17
18 private:
19
20 HINTERNET m_handle;
21
22 public:
23
24 HINTERNETHandle() : m_handle(NULL) {}
25
26 HINTERNETHandle(HINTERNET hInternet) : m_handle(hInternet) {}
27
28 HINTERNETHandle(HINTERNETHandle& handle)
29 {
30 m_handle = handle.m_handle;
31 handle.m_handle = NULL;
32 }
33
34 HINTERNETHandle& operator=(HINTERNET hInternet)
35 {
36 assert(!m_handle);
37 m_handle = hInternet;
38 return *this;
39 }
40
41 HINTERNET operator*()
42 {
43 return m_handle;
44 }
45
46 ~HINTERNETHandle()
47 {
48 // close the handle
49 if (m_handle)
50 {
51 if (!::WinHttpCloseHandle(m_handle))
52 {
53 DEBUG_ERROR_LOG(::GetLastError(), PLUGIN_ERROR_HTTP, PLUGIN_ERROR_HTTP_C LOSE_HANDLE, "Http::~HINTERNETHandle - WinHttpCloseHandle")
54 }
55 }
56 }
57 };
58
59
60 CPluginHttpRequest::CPluginHttpRequest(const CString& script, bool addChecksum) :
61 m_script(script), m_urlPrefix("?"), m_addChecksum(addChecksum)
62 {
63 m_checksum = std::auto_ptr<CPluginChecksum>(new CPluginChecksum());
64 m_checksum->Add(script);
65
66 m_responseFile = std::auto_ptr<CPluginIniFile>(new CPluginIniFile("", true));
67
68 m_url = CString(USERS_PATH) + script;
69 }
70
71
72 CPluginHttpRequest::~CPluginHttpRequest()
73 {
74 }
75
76
77 void CPluginHttpRequest::AddPluginId()
78 {
79 CPluginSettings* settings = CPluginSettings::GetInstance();
80
81 CPluginSystem* system = CPluginSystem::GetInstance();
82
83 Add("version", IEPLUGIN_VERSION);
84 }
85
86 void CPluginHttpRequest::AddOsInfo()
87 {
88 DWORD osVersion = ::GetVersion();
89
90 Add("os1", (LOBYTE(LOWORD(osVersion))));
91 Add("os2", (HIBYTE(LOWORD(osVersion))));
92 }
93
94 bool CPluginHttpRequest::Send(bool checkResponse)
95 {
96 if (m_addChecksum)
97 {
98 m_url += m_urlPrefix + "checksum=" + m_checksum->GetAsString();
99
100 m_urlPrefix = "&";
101 }
102
103 DEBUG_GENERAL("*** Sending HTTP request:" + m_url)
104
105 bool isOk = SendHttpRequest(USERS_HOST, m_url, &m_responseText, USERS_PORT) ? true:false;
106 if (isOk && checkResponse)
107 {
108 isOk = IsValidResponse();
109 }
110
111 return isOk;
112 }
113
114 void CPluginHttpRequest::Add(const CString& arg, const CString& value, bool addT oChecksum)
115 {
116 if (!arg.IsEmpty() && !value.IsEmpty())
117 {
118 CString valueEncoded;
119 DWORD cb = 2048;
120
121 HRESULT hr = ::UrlEscape(value, valueEncoded.GetBufferSetLength(cb), &cb, UR L_ESCAPE_SEGMENT_ONLY);
122 if (SUCCEEDED(hr))
123 {
124 valueEncoded.Truncate(cb);
125 }
126 else
127 {
128 valueEncoded = value;
129
130 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_HTTP_REQUEST, PLUGIN_ERROR_HTTP_REQUEST_U RL_ESCAPE, "HttpRequest::Add - UrlEscape failed on " + value)
131 }
132
133 m_url += m_urlPrefix + arg + "=" + valueEncoded;
134
135 if (addToChecksum)
136 {
137 m_checksum->Add(arg);
138 m_checksum->Add(valueEncoded);
139 }
140
141 m_urlPrefix = "&";
142 }
143 }
144
145 void CPluginHttpRequest::Add(const CString& arg, unsigned int value, bool addToC hecksum)
146 {
147 CString valueStr;
148 valueStr.Format(L"%u", value);
149
150 Add(arg, valueStr, addToChecksum);
151 }
152
153 CString CPluginHttpRequest::GetUrl()
154 {
155 if (m_addChecksum)
156 {
157 m_url += m_urlPrefix + "checksum=" + m_checksum->GetAsString();
158 m_urlPrefix = "&";
159 }
160
161 return CString(USERS_HOST) + m_url;
162 }
163
164
165 CString CPluginHttpRequest::GetStandardUrl(const CString& script)
166 {
167 CPluginHttpRequest httpRequest(script);
168
169 httpRequest.AddPluginId();
170
171 return httpRequest.GetUrl();
172 }
173
174
175 CStringA CPluginHttpRequest::GetResponseText() const
176 {
177 return m_responseText;
178 }
179
180 const std::auto_ptr<CPluginIniFile>& CPluginHttpRequest::GetResponseFile() const
181 {
182 return m_responseFile;
183 }
184
185 bool CPluginHttpRequest::IsValidResponse() const
186 {
187 m_responseFile->Clear();
188 m_responseFile->SetInitialChecksumString(m_script);
189
190 bool isValidResponse = m_responseFile->ReadString(m_responseText);
191 if (isValidResponse)
192 {
193 CPluginIniFile::TSectionData status = m_responseFile->GetSectionData(_T("Sta tus"));
194 CPluginIniFile::TSectionData::iterator it;
195
196 it = status.find(_T("status"));
197 if (it != status.end())
198 {
199 isValidResponse = (it->second == "OK");
200 }
201 else
202 {
203 isValidResponse = false;
204 }
205 }
206
207 return isValidResponse;
208 }
209
210 BOOL CPluginHttpRequest::GetProxySettings(CString& proxyName, CString& proxyBypa ss)
211 {
212 BOOL bResult = TRUE;
213
214 proxyName.Empty();
215 proxyBypass.Empty();
216
217 // Get Proxy config info.
218 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig;
219
220 ::ZeroMemory(&proxyConfig, sizeof(proxyConfig));
221
222 if (::WinHttpGetIEProxyConfigForCurrentUser(&proxyConfig))
223 {
224 proxyName = proxyConfig.lpszProxy;
225 proxyBypass = proxyConfig.lpszProxyBypass;
226 }
227 else
228 {
229 DEBUG_ERROR_LOG(::GetLastError(), PLUGIN_ERROR_HTTP, PLUGIN_ERROR_HTTP_PROXY _SETTINGS, "Http::GetProxySettings - WinHttpGetIEProxyConfigForCurrentUser")
230 bResult = FALSE;
231 }
232
233 // The strings need to be freed.
234 if (proxyConfig.lpszProxy != NULL)
235 {
236 ::GlobalFree(proxyConfig.lpszProxy);
237 }
238 if (proxyConfig.lpszAutoConfigUrl != NULL)
239 {
240 ::GlobalFree(proxyConfig.lpszAutoConfigUrl);
241 }
242 if (proxyConfig.lpszProxyBypass!= NULL)
243 {
244 ::GlobalFree(proxyConfig.lpszProxyBypass);
245 }
246
247 return bResult;
248 }
249
250 bool CPluginHttpRequest::SendHttpRequest(LPCWSTR server, LPCWSTR file, CStringA* response, WORD nServerPort)
251 {
252 // Prepare url
253 DWORD cb = 2049;
254 CString url;
255 HRESULT hr = ::UrlCanonicalize(file, url.GetBufferSetLength(cb), &cb, URL_ESCA PE_UNSAFE);
256 if (FAILED(hr))
257 {
258 DEBUG_ERROR_CODE(hr, "HttpRequest::SendHttpRequest::UrlCanonicalize failed o n " + CString(file))
259 return false;
260 }
261
262 DWORD dwSize = 0;
263 DWORD dwDownloaded = 0;
264 bool bResult = false;
265 HINTERNETHandle hSession, hConnect, hRequest;
266
267 // Get Proxy config info.
268 CString proxyName;
269 CString proxyBypass;
270
271 CPluginHttpRequest::GetProxySettings(proxyName, proxyBypass);
272
273 // If there is is proxy setting, use it.
274 if (proxyName.IsEmpty())
275 {
276 hSession = ::WinHttpOpen(BHO_NAME, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTT P_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
277 }
278 // Use WinHttpOpen to obtain a session handle.
279 else
280 {
281 hSession = ::WinHttpOpen(BHO_NAME, WINHTTP_ACCESS_TYPE_NAMED_PROXY, proxyNam e, proxyBypass, 0);
282 }
283
284 // Specify an HTTP server.
285 if (*hSession)
286 {
287 hConnect = ::WinHttpConnect(*hSession, server, nServerPort, 0);
288 }
289 else
290 {
291 DEBUG_ERROR_LOG(::GetLastError(), PLUGIN_ERROR_HTTP_REQUEST, PLUGIN_ERROR_HT TP_REQUEST_OPEN, "HttpRequest::SendHttpRequest - WinHttpOpen")
292 }
293
294 // Create an HTTP request handle.
295 if (*hConnect)
296 {
297 DWORD dwFlags = 0;
298 if (nServerPort == INTERNET_DEFAULT_HTTPS_PORT)
299 {
300 dwFlags = WINHTTP_FLAG_SECURE;
301 }
302
303 hRequest = ::WinHttpOpenRequest(*hConnect, L"GET", url, NULL, WINHTTP_NO_REF ERER, WINHTTP_DEFAULT_ACCEPT_TYPES, dwFlags);
304 }
305 else
306 {
307 DEBUG_ERROR_LOG(::GetLastError(), PLUGIN_ERROR_HTTP_REQUEST, PLUGIN_ERROR_HT TP_REQUEST_CONNECT, "HttpRequest::SendHttpRequest - WinHttpConnect")
308 }
309
310 // close the url, wont be needed anymore
311 url.ReleaseBuffer();
312
313 // Send a request.
314 if (*hRequest)
315 {
316 HTTP_VERSION_INFO ver;
317 DWORD l = sizeof(ver);
318 WinHttpQueryOption(NULL, WINHTTP_OPTION_HTTP_VERSION, (void*)&ver, &l);
319 if (ver.dwMinorVersion == 1)
320 {
321 bResult = ::WinHttpSendRequest(*hRequest, L"Accept-Encoding: gzip, deflate ", 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0) ? true : false;
322 }
323 else
324 {
325 bResult = ::WinHttpSendRequest(*hRequest, L"", 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0) ? true : false;
326 }
327 if (!bResult)
328 {
329 DWORD dwError = ::GetLastError();
330
331 if (dwError == 12007L) // ERROR_INTERNET_NAME_NOT_RESOLVED
332 {
333 DEBUG_GENERAL("*** Trying to detect proxy for URL")
334
335 // Set up the autoproxy call
336 WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions;
337 WINHTTP_PROXY_INFO proxyInfo;
338 DWORD cbProxyInfoSize = sizeof(proxyInfo);
339
340 ::ZeroMemory(&autoProxyOptions, sizeof(autoProxyOptions));
341 ::ZeroMemory(&proxyInfo, sizeof(proxyInfo));
342
343 // Use auto-detection because the Proxy
344 // Auto-Config URL is not known.
345 autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
346
347 // Use DHCP and DNS-based auto-detection.
348 autoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WIN HTTP_AUTO_DETECT_TYPE_DNS_A;
349
350 // If obtaining the PAC script requires NTLM/Negotiate
351 // authentication, then automatically supply the client
352 // domain credentials.
353 autoProxyOptions.fAutoLogonIfChallenged = TRUE;
354
355 CString completeUrl = (nServerPort == INTERNET_DEFAULT_HTTPS_PORT ? "htt ps://" : "http://");
356 completeUrl += server;
357 completeUrl += file;
358
359 bResult = ::WinHttpGetProxyForUrl(*hSession, completeUrl, &autoProxyOpti ons, &proxyInfo) ? true : false;
360 if (bResult)
361 {
362 bResult = ::WinHttpSetOption(*hRequest, WINHTTP_OPTION_PROXY, &proxyIn fo, cbProxyInfoSize) ? true : false;
363 if (!bResult)
364 {
365 DEBUG_ERROR_LOG(::GetLastError(), PLUGIN_ERROR_HTTP_REQUEST, PLUGIN_ ERROR_HTTP_REQUEST_SET_OPTION, "HttpRequest::SendHttpRequest - WinHttpSetOption" )
366 }
367 }
368 else
369 {
370 DEBUG_ERROR_LOG(::GetLastError(), PLUGIN_ERROR_HTTP_REQUEST, PLUGIN_ER ROR_HTTP_REQUEST_GET_URL_PROXY, "HttpRequest::SendHttpRequest WinHttpGetProxyFor Url")
371 }
372
373 if (bResult)
374 {
375 bResult = ::WinHttpSendRequest(*hRequest, WINHTTP_NO_ADDITIONAL_HEADER S, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0) ? true : false;
376 if (!bResult)
377 {
378 DEBUG_ERROR_LOG(::GetLastError(), PLUGIN_ERROR_HTTP_REQUEST, PLUGIN_ ERROR_HTTP_REQUEST_SEND_REQUEST, "HttpRequest::SendHttpRequest - WinHttpSendRequ est")
379 }
380 }
381 }
382 else
383 {
384 DEBUG_ERROR_LOG(dwError, PLUGIN_ERROR_HTTP_REQUEST, PLUGIN_ERROR_HTTP_RE QUEST_SEND_REQUEST, "HttpRequest::SendHttpRequest - WinHttpSendRequest")
385 }
386 }
387 }
388 else
389 {
390 DEBUG_ERROR_LOG(::GetLastError(), PLUGIN_ERROR_HTTP_REQUEST, PLUGIN_ERROR_HT TP_REQUEST_OPEN_REQUEST, "HttpRequest::SendHttpRequest - WinHttpOpenRequest")
391 }
392
393 // End the request.
394 if (bResult)
395 {
396 bResult = ::WinHttpReceiveResponse(*hRequest, NULL) ? true : false;
397 if (!bResult)
398 {
399 DEBUG_ERROR_LOG(::GetLastError(), PLUGIN_ERROR_HTTP_REQUEST, PLUGIN_ERROR_ HTTP_REQUEST_RECEIVE_RESPONSE, "HttpRequest::SendHttpRequest - WinHttpReceiveRes ponse")
400 }
401 }
402
403 // Keep checking for data until there is nothing left.
404 if (bResult)
405 {
406 //check the header - if we do not receive an ad-aid tag in the header
407 //then the answer cannot come from our server, maybe it is from an hotspot o r something similar
408 //that demands validation before access to the internet is granted
409 //see http://msdn.microsoft.com/en-us/library/aa384102(VS.85).aspx for docum entation of queryheaders
410 //we look for X-AIDPING: aidonline
411 LPCWSTR headerName = L"X-AIDPING";
412 wchar_t lpOutBuffer[50];
413 DWORD dwSize = 50;
414
415 if (nServerPort != 80 && ::WinHttpQueryHeaders(*hRequest, WINHTTP_QUERY_CUST OM, headerName, lpOutBuffer, &dwSize, WINHTTP_NO_HEADER_INDEX))
416 {
417 if (CStringW(lpOutBuffer,dwSize) != CStringW(L"aidonline"))
418 {
419 // Unknown server - we return error
420 DEBUG_ERROR_LOG(0, PLUGIN_ERROR_HTTP_REQUEST, PLUGIN_ERROR_HTTP_REQUEST_ INVALID_RESPONSE_SERVER, "HttpRequest::SendHttpRequest - Reponse not from correc t server")
421 return false;
422 }
423 }
424 else if (nServerPort != 80)
425 {
426 DEBUG_ERROR_LOG(::GetLastError(), PLUGIN_ERROR_HTTP_REQUEST, PLUGIN_ERROR_ HTTP_REQUEST_QUERY_HEADERS, "HttpRequest::SendHttpRequest - WinHttpQueryHeaders" )
427 }
428
429 do
430 {
431 // Check for available data.
432 dwSize = 0;
433 if (!::WinHttpQueryDataAvailable(*hRequest, &dwSize))
434 {
435 DEBUG_ERROR_LOG(::GetLastError(), PLUGIN_ERROR_HTTP_REQUEST, PLUGIN_ERRO R_HTTP_REQUEST_QUERY_DATA_AVAILABLE, "HttpRequest::SendHttpRequest - WinHttpQuer yDataAvailable")
436 return false;
437 }
438
439 // Allocate space for the buffer.
440 CStringA outBuffer;
441 LPVOID pOutBuffer = outBuffer.GetBufferSetLength(dwSize+1);
442 if (!pOutBuffer)
443 {
444 dwSize = 0;
445 return false;
446 }
447 else
448 {
449 // Read the data.
450 ::ZeroMemory(pOutBuffer, dwSize+1);
451
452 if (!::WinHttpReadData(*hRequest, pOutBuffer, dwSize, &dwDownloaded))
453 {
454 DEBUG_ERROR_LOG(::GetLastError(), PLUGIN_ERROR_HTTP_REQUEST, PLUGIN_ER ROR_HTTP_REQUEST_READ_DATA, "HttpRequest::SendHttpRequest - WinHttpReadData")
455 return false;
456 }
457 else
458 {
459 if (response)
460 {
461 *response += outBuffer;
462 }
463 }
464
465 // Free the memory allocated to the buffer.
466 }
467
468 outBuffer.ReleaseBuffer();
469
470 } while (dwSize > 0);
471 }
472
473 return bResult;
474 }
OLDNEW

Powered by Google App Engine
This is Rietveld