Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(559)

Side by Side Diff: obsolete/breakpad/common/windows/http_upload.cc

Issue 10928195: First round of dead file removal (Closed) Base URL: https://github.com/samclegg/nativeclient-sdk.git@master
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2006, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 #include <assert.h>
31
32 // Disable exception handler warnings.
33 #pragma warning( disable : 4530 )
34
35 #include <fstream>
36
37 #include "common/windows/string_utils-inl.h"
38
39 #include "common/windows/http_upload.h"
40
41 namespace google_breakpad {
42
43 using std::ifstream;
44 using std::ios;
45
46 static const wchar_t kUserAgent[] = L"Breakpad/1.0 (Windows)";
47
48 // Helper class which closes an internet handle when it goes away
49 class HTTPUpload::AutoInternetHandle {
50 public:
51 explicit AutoInternetHandle(HINTERNET handle) : handle_(handle) {}
52 ~AutoInternetHandle() {
53 if (handle_) {
54 InternetCloseHandle(handle_);
55 }
56 }
57
58 HINTERNET get() { return handle_; }
59
60 private:
61 HINTERNET handle_;
62 };
63
64 // static
65 bool HTTPUpload::SendRequest(const wstring &url,
66 const map<wstring, wstring> &parameters,
67 const wstring &upload_file,
68 const wstring &file_part_name,
69 int *timeout,
70 wstring *response_body,
71 int *response_code) {
72 if (response_code) {
73 *response_code = 0;
74 }
75
76 // TODO(bryner): support non-ASCII parameter names
77 if (!CheckParameters(parameters)) {
78 return false;
79 }
80
81 // Break up the URL and make sure we can handle it
82 wchar_t scheme[16], host[256], path[256];
83 URL_COMPONENTS components;
84 memset(&components, 0, sizeof(components));
85 components.dwStructSize = sizeof(components);
86 components.lpszScheme = scheme;
87 components.dwSchemeLength = sizeof(scheme) / sizeof(scheme[0]);
88 components.lpszHostName = host;
89 components.dwHostNameLength = sizeof(host) / sizeof(host[0]);
90 components.lpszUrlPath = path;
91 components.dwUrlPathLength = sizeof(path) / sizeof(path[0]);
92 if (!InternetCrackUrl(url.c_str(), static_cast<DWORD>(url.size()),
93 0, &components)) {
94 return false;
95 }
96 bool secure = false;
97 if (wcscmp(scheme, L"https") == 0) {
98 secure = true;
99 } else if (wcscmp(scheme, L"http") != 0) {
100 return false;
101 }
102
103 AutoInternetHandle internet(InternetOpen(kUserAgent,
104 INTERNET_OPEN_TYPE_PRECONFIG,
105 NULL, // proxy name
106 NULL, // proxy bypass
107 0)); // flags
108 if (!internet.get()) {
109 return false;
110 }
111
112 AutoInternetHandle connection(InternetConnect(internet.get(),
113 host,
114 components.nPort,
115 NULL, // user name
116 NULL, // password
117 INTERNET_SERVICE_HTTP,
118 0, // flags
119 NULL)); // context
120 if (!connection.get()) {
121 return false;
122 }
123
124 DWORD http_open_flags = secure ? INTERNET_FLAG_SECURE : 0;
125 AutoInternetHandle request(HttpOpenRequest(connection.get(),
126 L"POST",
127 path,
128 NULL, // version
129 NULL, // referer
130 NULL, // agent type
131 http_open_flags,
132 NULL)); // context
133 if (!request.get()) {
134 return false;
135 }
136
137 wstring boundary = GenerateMultipartBoundary();
138 wstring content_type_header = GenerateRequestHeader(boundary);
139 HttpAddRequestHeaders(request.get(),
140 content_type_header.c_str(),
141 static_cast<DWORD>(-1),
142 HTTP_ADDREQ_FLAG_ADD);
143
144 string request_body;
145 if (!GenerateRequestBody(parameters, upload_file,
146 file_part_name, boundary, &request_body)) {
147 return false;
148 }
149
150 if (timeout) {
151 if (!InternetSetOption(request.get(),
152 INTERNET_OPTION_SEND_TIMEOUT,
153 timeout,
154 sizeof(timeout))) {
155 fwprintf(stderr, L"Could not unset send timeout, continuing...\n");
156 }
157
158 if (!InternetSetOption(request.get(),
159 INTERNET_OPTION_RECEIVE_TIMEOUT,
160 timeout,
161 sizeof(timeout))) {
162 fwprintf(stderr, L"Could not unset receive timeout, continuing...\n");
163 }
164 }
165
166 if (!HttpSendRequest(request.get(), NULL, 0,
167 const_cast<char *>(request_body.data()),
168 static_cast<DWORD>(request_body.size()))) {
169 return false;
170 }
171
172 // The server indicates a successful upload with HTTP status 200.
173 wchar_t http_status[4];
174 DWORD http_status_size = sizeof(http_status);
175 if (!HttpQueryInfo(request.get(), HTTP_QUERY_STATUS_CODE,
176 static_cast<LPVOID>(&http_status), &http_status_size,
177 0)) {
178 return false;
179 }
180
181 int http_response = wcstol(http_status, NULL, 10);
182 if (response_code) {
183 *response_code = http_response;
184 }
185
186 bool result = (http_response == 200);
187
188 if (result) {
189 result = ReadResponse(request.get(), response_body);
190 }
191
192 return result;
193 }
194
195 // static
196 bool HTTPUpload::ReadResponse(HINTERNET request, wstring *response) {
197 bool has_content_length_header = false;
198 wchar_t content_length[32];
199 DWORD content_length_size = sizeof(content_length);
200 DWORD claimed_size = 0;
201 string response_body;
202
203 if (HttpQueryInfo(request, HTTP_QUERY_CONTENT_LENGTH,
204 static_cast<LPVOID>(&content_length),
205 &content_length_size, 0)) {
206 has_content_length_header = true;
207 claimed_size = wcstol(content_length, NULL, 10);
208 response_body.reserve(claimed_size);
209 }
210
211
212 DWORD bytes_available;
213 DWORD total_read = 0;
214 BOOL return_code;
215
216 while (((return_code = InternetQueryDataAvailable(request, &bytes_available,
217 0, 0)) != 0) && bytes_available > 0) {
218
219 vector<char> response_buffer(bytes_available);
220 DWORD size_read;
221
222 return_code = InternetReadFile(request,
223 &response_buffer[0],
224 bytes_available, &size_read);
225
226 if (return_code && size_read > 0) {
227 total_read += size_read;
228 response_body.append(&response_buffer[0], size_read);
229 } else {
230 break;
231 }
232 }
233
234 bool succeeded = return_code && (!has_content_length_header ||
235 (total_read == claimed_size));
236 if (succeeded && response) {
237 *response = UTF8ToWide(response_body);
238 }
239
240 return succeeded;
241 }
242
243 // static
244 wstring HTTPUpload::GenerateMultipartBoundary() {
245 // The boundary has 27 '-' characters followed by 16 hex digits
246 static const wchar_t kBoundaryPrefix[] = L"---------------------------";
247 static const int kBoundaryLength = 27 + 16 + 1;
248
249 // Generate some random numbers to fill out the boundary
250 int r0 = rand();
251 int r1 = rand();
252
253 wchar_t temp[kBoundaryLength];
254 swprintf(temp, kBoundaryLength, L"%s%08X%08X", kBoundaryPrefix, r0, r1);
255
256 // remove when VC++7.1 is no longer supported
257 temp[kBoundaryLength - 1] = L'\0';
258
259 return wstring(temp);
260 }
261
262 // static
263 wstring HTTPUpload::GenerateRequestHeader(const wstring &boundary) {
264 wstring header = L"Content-Type: multipart/form-data; boundary=";
265 header += boundary;
266 return header;
267 }
268
269 // static
270 bool HTTPUpload::GenerateRequestBody(const map<wstring, wstring> &parameters,
271 const wstring &upload_file,
272 const wstring &file_part_name,
273 const wstring &boundary,
274 string *request_body) {
275 vector<char> contents;
276 GetFileContents(upload_file, &contents);
277 if (contents.empty()) {
278 return false;
279 }
280
281 string boundary_str = WideToUTF8(boundary);
282 if (boundary_str.empty()) {
283 return false;
284 }
285
286 request_body->clear();
287
288 // Append each of the parameter pairs as a form-data part
289 for (map<wstring, wstring>::const_iterator pos = parameters.begin();
290 pos != parameters.end(); ++pos) {
291 request_body->append("--" + boundary_str + "\r\n");
292 request_body->append("Content-Disposition: form-data; name=\"" +
293 WideToUTF8(pos->first) + "\"\r\n\r\n" +
294 WideToUTF8(pos->second) + "\r\n");
295 }
296
297 // Now append the upload file as a binary (octet-stream) part
298 string filename_utf8 = WideToUTF8(upload_file);
299 if (filename_utf8.empty()) {
300 return false;
301 }
302
303 string file_part_name_utf8 = WideToUTF8(file_part_name);
304 if (file_part_name_utf8.empty()) {
305 return false;
306 }
307
308 request_body->append("--" + boundary_str + "\r\n");
309 request_body->append("Content-Disposition: form-data; "
310 "name=\"" + file_part_name_utf8 + "\"; "
311 "filename=\"" + filename_utf8 + "\"\r\n");
312 request_body->append("Content-Type: application/octet-stream\r\n");
313 request_body->append("\r\n");
314
315 if (!contents.empty()) {
316 request_body->append(&(contents[0]), contents.size());
317 }
318 request_body->append("\r\n");
319 request_body->append("--" + boundary_str + "--\r\n");
320 return true;
321 }
322
323 // static
324 void HTTPUpload::GetFileContents(const wstring &filename,
325 vector<char> *contents) {
326 // The "open" method on pre-MSVC8 ifstream implementations doesn't accept a
327 // wchar_t* filename, so use _wfopen directly in that case. For VC8 and
328 // later, _wfopen has been deprecated in favor of _wfopen_s, which does
329 // not exist in earlier versions, so let the ifstream open the file itself.
330 #if _MSC_VER >= 1400 // MSVC 2005/8
331 ifstream file;
332 file.open(filename.c_str(), ios::binary);
333 #else // _MSC_VER >= 1400
334 ifstream file(_wfopen(filename.c_str(), L"rb"));
335 #endif // _MSC_VER >= 1400
336 if (file.is_open()) {
337 file.seekg(0, ios::end);
338 std::streamoff length = file.tellg();
339 contents->resize(length);
340 if (length != 0) {
341 file.seekg(0, ios::beg);
342 file.read(&((*contents)[0]), length);
343 }
344 file.close();
345 } else {
346 contents->clear();
347 }
348 }
349
350 // static
351 wstring HTTPUpload::UTF8ToWide(const string &utf8) {
352 if (utf8.length() == 0) {
353 return wstring();
354 }
355
356 // compute the length of the buffer we'll need
357 int charcount = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0);
358
359 if (charcount == 0) {
360 return wstring();
361 }
362
363 // convert
364 wchar_t* buf = new wchar_t[charcount];
365 MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, buf, charcount);
366 wstring result(buf);
367 delete[] buf;
368 return result;
369 }
370
371 // static
372 string HTTPUpload::WideToUTF8(const wstring &wide) {
373 if (wide.length() == 0) {
374 return string();
375 }
376
377 // compute the length of the buffer we'll need
378 int charcount = WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1,
379 NULL, 0, NULL, NULL);
380 if (charcount == 0) {
381 return string();
382 }
383
384 // convert
385 char *buf = new char[charcount];
386 WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1, buf, charcount,
387 NULL, NULL);
388
389 string result(buf);
390 delete[] buf;
391 return result;
392 }
393
394 // static
395 bool HTTPUpload::CheckParameters(const map<wstring, wstring> &parameters) {
396 for (map<wstring, wstring>::const_iterator pos = parameters.begin();
397 pos != parameters.end(); ++pos) {
398 const wstring &str = pos->first;
399 if (str.size() == 0) {
400 return false; // disallow empty parameter names
401 }
402 for (unsigned int i = 0; i < str.size(); ++i) {
403 wchar_t c = str[i];
404 if (c < 32 || c == '"' || c > 127) {
405 return false;
406 }
407 }
408 }
409 return true;
410 }
411
412 } // namespace google_breakpad
OLDNEW
« no previous file with comments | « obsolete/breakpad/common/windows/http_upload.h ('k') | obsolete/breakpad/common/windows/pdb_source_line_writer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698