Mercurial > trustbridge
comparison ui/downloader_win.cpp @ 11:7e2f14c7aba2
Split up downloader component and further implement it
author | Andre Heinecke <aheinecke@intevation.de> |
---|---|
date | Fri, 14 Feb 2014 11:20:15 +0000 |
parents | |
children | 95e1b6edf2fc |
comparison
equal
deleted
inserted
replaced
10:fe39d93f1261 | 11:7e2f14c7aba2 |
---|---|
1 /** | |
2 * @file downloader_win.cpp | |
3 * @brief Downloader implementation for Windows | |
4 * | |
5 * We use Windows API here instead of Qt because we want to avoid | |
6 * QtNetworks SSL stack which is based on OpenSSL and so | |
7 * we might be incompatible with GPL code. Also using the | |
8 * native API means that the security of the SSL implementation | |
9 * is tied to the security of the system. | |
10 * | |
11 */ | |
12 #include "downloader.h" | |
13 #ifdef Q_OS_WIN | |
14 #ifndef MYVERSION | |
15 #define MYVERSION "1" | |
16 #endif | |
17 | |
18 #include <windows.h> | |
19 #include <winhttp.h> | |
20 | |
21 #include <QDebug> | |
22 | |
23 #define DEBUG if (1) qDebug() << __PRETTY_FUNCTION__ | |
24 | |
25 const QString getLastErrorMsg() { | |
26 LPWSTR bufPtr = NULL; | |
27 DWORD err = GetLastError(); | |
28 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | | |
29 FORMAT_MESSAGE_FROM_SYSTEM | | |
30 FORMAT_MESSAGE_IGNORE_INSERTS, | |
31 NULL, err, 0, (LPWSTR)&bufPtr, 0, NULL); | |
32 const QString result = | |
33 (bufPtr) ? QString::fromUtf16((const ushort*)bufPtr).trimmed() : | |
34 QString("Unknown Error %1").arg(err); | |
35 LocalFree(bufPtr); | |
36 return result; | |
37 } | |
38 | |
39 /** @brief open a session with appropiate proxy settings | |
40 * | |
41 * @param[inout] *pHSession pointer to a HInternet structure | |
42 * | |
43 * On error call getLastError to get extended error information. | |
44 * | |
45 * @returns True on success, false on error. | |
46 */ | |
47 | |
48 | |
49 bool openSession(HINTERNET *pHSession) | |
50 { | |
51 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig; | |
52 | |
53 DEBUG; | |
54 if (!pHSession) { | |
55 SetLastError(ERROR_INVALID_PARAMETER); | |
56 return false; | |
57 } | |
58 | |
59 qDebug() << "2"; | |
60 memset(&proxyConfig, 0, sizeof (WINHTTP_CURRENT_USER_IE_PROXY_CONFIG)); | |
61 | |
62 if (WinHttpGetIEProxyConfigForCurrentUser(&proxyConfig)) { | |
63 if (proxyConfig.fAutoDetect) { | |
64 // TODO Handle this | |
65 qDebug() << "Autodetect is set"; | |
66 } | |
67 | |
68 if (proxyConfig.lpszProxy || proxyConfig.lpszProxyBypass) { | |
69 DEBUG << "Using proxies."; | |
70 } | |
71 | |
72 if (proxyConfig.lpszProxy) { | |
73 *pHSession = WinHttpOpen(L"M13 "MYVERSION, | |
74 WINHTTP_ACCESS_TYPE_NAMED_PROXY, | |
75 proxyConfig.lpszProxy, | |
76 proxyConfig.lpszProxyBypass, 0); | |
77 } | |
78 } | |
79 | |
80 if (!*pHSession) { | |
81 DEBUG << "No IE Proxy falling back to default proxy"; | |
82 *pHSession = WinHttpOpen(L"M13 "MYVERSION, | |
83 WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, | |
84 WINHTTP_NO_PROXY_NAME, | |
85 WINHTTP_NO_PROXY_BYPASS, 0); | |
86 } | |
87 // Cleanup | |
88 if (proxyConfig.lpszAutoConfigUrl) { | |
89 GlobalFree(proxyConfig.lpszAutoConfigUrl); | |
90 } | |
91 | |
92 if (proxyConfig.lpszProxy) { | |
93 GlobalFree(proxyConfig.lpszProxy); | |
94 } | |
95 | |
96 if (proxyConfig.lpszProxyBypass) { | |
97 GlobalFree(proxyConfig.lpszProxyBypass); | |
98 } | |
99 return *pHSession; | |
100 } | |
101 | |
102 | |
103 /** @brief initialize a connection in the session | |
104 * | |
105 * @param[in] HSession the session to work in. | |
106 * @param[inout] *pHConnect pointer to the connection. | |
107 * @param[in] url pointer to the URL in wchar representation. | |
108 * | |
109 * On error call getLastError to get extended error information. | |
110 * | |
111 * @returns True on success, false on error. | |
112 */ | |
113 bool initializeConnection(HINTERNET hSession, HINTERNET *pHConnect, | |
114 LPCWSTR url) | |
115 { | |
116 DEBUG; | |
117 if (!hSession || !pHConnect) { | |
118 SetLastError(ERROR_INVALID_PARAMETER); | |
119 return false; | |
120 } | |
121 // Initialize connection. No request is done here. | |
122 *pHConnect = WinHttpConnect(hSession, url, | |
123 INTERNET_DEFAULT_HTTPS_PORT, 0); | |
124 | |
125 return *pHConnect; | |
126 } | |
127 | |
128 /** @brief Create a request | |
129 * | |
130 * @param[in] HSession the session to work in. | |
131 * @param[in] HConnect the connection to use. | |
132 * @param[inout] *pHRequest pointer to the request structure to be filled. | |
133 * @param[in] requestType the HTTP request to be made default is GET | |
134 * @param[in] resource pointer to the resource to request in wchar | |
135 * representation. | |
136 * | |
137 * On error call getLastError to get extended error information. | |
138 * This function still does not do any networking but only initializes | |
139 * it. | |
140 * | |
141 * @returns True on success, false on error. | |
142 */ | |
143 | |
144 bool createRequest(HINTERNET hSession, HINTERNET hConnect, | |
145 HINTERNET *pHRequest, LPCWSTR requestType, LPCWSTR resource) | |
146 { | |
147 DEBUG; | |
148 if (!hSession || !hConnect || !pHRequest) { | |
149 SetLastError(ERROR_INVALID_PARAMETER); | |
150 return false; | |
151 } | |
152 | |
153 *pHRequest = WinHttpOpenRequest(hConnect, requestType, resource, | |
154 NULL, WINHTTP_NO_REFERER, | |
155 WINHTTP_DEFAULT_ACCEPT_TYPES, | |
156 WINHTTP_FLAG_SECURE); | |
157 return *pHRequest; | |
158 } | |
159 | |
160 void Downloader::run() { | |
161 BOOL bResults = FALSE; | |
162 HINTERNET hSession = NULL, | |
163 hConnect = NULL, | |
164 hRequest = NULL; | |
165 | |
166 SYSTEMTIME lastModified; | |
167 DWORD sizeOfSystemtime = sizeof (SYSTEMTIME); | |
168 | |
169 memset(&lastModified, 0, sizeof (SYSTEMTIME)); | |
170 | |
171 if (!openSession(&hSession)) { | |
172 DEBUG << "Failed to open session: " << getLastErrorMsg(); | |
173 return; | |
174 } | |
175 | |
176 if (!initializeConnection(hSession, &hConnect, L"www.intevation.de")) { | |
177 DEBUG << "Failed to initialize connection: " << getLastErrorMsg(); | |
178 goto cleanup; | |
179 } | |
180 | |
181 if (!createRequest(hSession, hConnect, &hRequest, L"GET", L"/")) { | |
182 DEBUG << "Failed to create the request: " << getLastErrorMsg(); | |
183 goto cleanup; | |
184 } | |
185 | |
186 if (hRequest) { | |
187 DEBUG << "Doing Request"; | |
188 bResults = WinHttpSendRequest(hRequest, | |
189 WINHTTP_NO_ADDITIONAL_HEADERS, | |
190 0, WINHTTP_NO_REQUEST_DATA, 0, | |
191 0, 0); | |
192 } else { | |
193 DEBUG << "Error: " << GetLastError(); | |
194 } | |
195 | |
196 | |
197 if (bResults) { | |
198 DEBUG << "Recieving Response"; | |
199 bResults = WinHttpReceiveResponse(hRequest, NULL); | |
200 } else { | |
201 DEBUG << "Error: " << GetLastError(); | |
202 } | |
203 | |
204 if (bResults) { | |
205 DEBUG << "Querying Headers"; | |
206 bResults = WinHttpQueryHeaders(hRequest, | |
207 WINHTTP_QUERY_LAST_MODIFIED | | |
208 WINHTTP_QUERY_FLAG_SYSTEMTIME, | |
209 NULL, | |
210 &lastModified, | |
211 &sizeOfSystemtime, | |
212 WINHTTP_NO_HEADER_INDEX); | |
213 } else { | |
214 DWORD errCode = GetLastError(); | |
215 switch (errCode) { | |
216 case ERROR_WINHTTP_HEADER_NOT_FOUND: | |
217 DEBUG << "Header not found"; | |
218 break; | |
219 case ERROR_WINHTTP_INCORRECT_HANDLE_STATE: | |
220 DEBUG << "Incorrect handle state"; | |
221 break; | |
222 case ERROR_WINHTTP_INCORRECT_HANDLE_TYPE: | |
223 DEBUG << "Incorrect handle type"; | |
224 break; | |
225 case ERROR_WINHTTP_INTERNAL_ERROR: | |
226 DEBUG << "Internal error"; | |
227 break; | |
228 case ERROR_NOT_ENOUGH_MEMORY: | |
229 DEBUG << "OOM"; | |
230 break; | |
231 default: | |
232 DEBUG << "Error: " << getLastErrorMsg(); | |
233 } | |
234 } | |
235 | |
236 DEBUG << "Last modified year: " << lastModified.wYear; | |
237 | |
238 | |
239 if (!bResults) { | |
240 // Report any errors. | |
241 DEBUG << "Error" << GetLastError(); | |
242 emit error(tr("Unknown Problem when connecting"), Unknown); | |
243 } | |
244 cleanup: | |
245 if (hRequest) { | |
246 WinHttpCloseHandle(hRequest); | |
247 } | |
248 | |
249 if (hConnect) { | |
250 WinHttpCloseHandle(hConnect); | |
251 | |
252 } | |
253 | |
254 if (hSession) { | |
255 WinHttpCloseHandle(hSession); | |
256 } | |
257 return; | |
258 } | |
259 #endif |