http_upload.cc revision bbd9b472916ce10b16f59d4e56c9ed7959f9d95e
18b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// Copyright (c) 2006, Google Inc. 28b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// All rights reserved. 38b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// 48b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// Redistribution and use in source and binary forms, with or without 58b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// modification, are permitted provided that the following conditions are 68b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// met: 78b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// 88b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// * Redistributions of source code must retain the above copyright 98b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// notice, this list of conditions and the following disclaimer. 108b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// * Redistributions in binary form must reproduce the above 118b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// copyright notice, this list of conditions and the following disclaimer 128b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// in the documentation and/or other materials provided with the 138b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// distribution. 148b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// * Neither the name of Google Inc. nor the names of its 158b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// contributors may be used to endorse or promote products derived from 168b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// this software without specific prior written permission. 178b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// 188b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 198b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 208b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 218b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 228b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 238b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 248b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 258b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 268b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 278b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 288b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 298b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 308b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner#include <assert.h> 318b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 3212a5245bfe93d4a0ccb692afefc4ecf1435d97f4mmentovai// Disable exception handler warnings. 3312a5245bfe93d4a0ccb692afefc4ecf1435d97f4mmentovai#pragma warning( disable : 4530 ) 3412a5245bfe93d4a0ccb692afefc4ecf1435d97f4mmentovai 358b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner#include <fstream> 368b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 3773cd14b4af906e77f3d8b019962fb9979ff12620mmentovai#include "common/windows/string_utils-inl.h" 3873cd14b4af906e77f3d8b019962fb9979ff12620mmentovai 398b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner#include "common/windows/http_upload.h" 408b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 41e5dc60822e5938fea2ae892ccddb906641ba174emmentovainamespace google_breakpad { 428b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 438b1645d8cdb34035c0b132fe8b574bc5ee48fb62brynerusing std::ifstream; 448b1645d8cdb34035c0b132fe8b574bc5ee48fb62brynerusing std::ios; 458b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 46e5dc60822e5938fea2ae892ccddb906641ba174emmentovaistatic const wchar_t kUserAgent[] = L"Breakpad/1.0 (Windows)"; 478b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 488b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// Helper class which closes an internet handle when it goes away 498b1645d8cdb34035c0b132fe8b574bc5ee48fb62brynerclass HTTPUpload::AutoInternetHandle { 508b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner public: 518b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner explicit AutoInternetHandle(HINTERNET handle) : handle_(handle) {} 528b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner ~AutoInternetHandle() { 538b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (handle_) { 548b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner InternetCloseHandle(handle_); 558b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 568b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 578b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 588b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner HINTERNET get() { return handle_; } 598b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 608b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner private: 618b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner HINTERNET handle_; 628b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner}; 638b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 648b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// static 658b1645d8cdb34035c0b132fe8b574bc5ee48fb62brynerbool HTTPUpload::SendRequest(const wstring &url, 668b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner const map<wstring, wstring> ¶meters, 678b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner const wstring &upload_file, 68dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist const wstring &file_part_name, 69d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist wstring *response_body, 70d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist int *response_code) { 71d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist if (response_code) { 72d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist *response_code = 0; 73d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist } 74d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist 758b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner // TODO(bryner): support non-ASCII parameter names 768b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (!CheckParameters(parameters)) { 778b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; 788b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 798b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 808b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner // Break up the URL and make sure we can handle it 818b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner wchar_t scheme[16], host[256], path[256]; 828b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner URL_COMPONENTS components; 838b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner memset(&components, 0, sizeof(components)); 848b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner components.dwStructSize = sizeof(components); 858b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner components.lpszScheme = scheme; 86bbd9b472916ce10b16f59d4e56c9ed7959f9d95emmentovai components.dwSchemeLength = sizeof(scheme) / sizeof(scheme[0]); 878b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner components.lpszHostName = host; 88bbd9b472916ce10b16f59d4e56c9ed7959f9d95emmentovai components.dwHostNameLength = sizeof(host) / sizeof(host[0]); 898b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner components.lpszUrlPath = path; 90bbd9b472916ce10b16f59d4e56c9ed7959f9d95emmentovai components.dwUrlPathLength = sizeof(path) / sizeof(path[0]); 918b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (!InternetCrackUrl(url.c_str(), static_cast<DWORD>(url.size()), 928b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 0, &components)) { 938b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; 948b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 955afd60b067a65920ba2e4705ccea71b880cc1607mmentovai bool secure = false; 965afd60b067a65920ba2e4705ccea71b880cc1607mmentovai if (wcscmp(scheme, L"https") == 0) { 975afd60b067a65920ba2e4705ccea71b880cc1607mmentovai secure = true; 985afd60b067a65920ba2e4705ccea71b880cc1607mmentovai } else if (wcscmp(scheme, L"http") != 0) { 998b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; 1008b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 1018b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 1028b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner AutoInternetHandle internet(InternetOpen(kUserAgent, 1035afd60b067a65920ba2e4705ccea71b880cc1607mmentovai INTERNET_OPEN_TYPE_PRECONFIG, 1048b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner NULL, // proxy name 1058b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner NULL, // proxy bypass 1068b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 0)); // flags 1078b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (!internet.get()) { 1088b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; 1098b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 1108b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 1118b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner AutoInternetHandle connection(InternetConnect(internet.get(), 1128b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner host, 1138b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner components.nPort, 1148b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner NULL, // user name 1158b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner NULL, // password 1168b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner INTERNET_SERVICE_HTTP, 1178b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 0, // flags 1188b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner NULL)); // context 1198b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (!connection.get()) { 1208b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; 1218b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 1228b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 1235afd60b067a65920ba2e4705ccea71b880cc1607mmentovai DWORD http_open_flags = secure ? INTERNET_FLAG_SECURE : 0; 1248b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner AutoInternetHandle request(HttpOpenRequest(connection.get(), 1258b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner L"POST", 1268b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner path, 1278b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner NULL, // version 1288b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner NULL, // referer 1298b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner NULL, // agent type 1305afd60b067a65920ba2e4705ccea71b880cc1607mmentovai http_open_flags, 1318b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner NULL)); // context 1328b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (!request.get()) { 1338b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; 1348b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 1358b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 1368b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner wstring boundary = GenerateMultipartBoundary(); 1378b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner wstring content_type_header = GenerateRequestHeader(boundary); 1388b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner HttpAddRequestHeaders(request.get(), 1398b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner content_type_header.c_str(), 140f2fa084fd229b60cc3350bed66c4b7d95b10d61ammentovai static_cast<DWORD>(-1), 141f2fa084fd229b60cc3350bed66c4b7d95b10d61ammentovai HTTP_ADDREQ_FLAG_ADD); 1428b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 1438b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner string request_body; 144684649a57172532274e2b8b1307af6fa11fdabceted.mielczarek if (!GenerateRequestBody(parameters, upload_file, 145684649a57172532274e2b8b1307af6fa11fdabceted.mielczarek file_part_name, boundary, &request_body)) { 146684649a57172532274e2b8b1307af6fa11fdabceted.mielczarek return false; 147684649a57172532274e2b8b1307af6fa11fdabceted.mielczarek } 1488b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 1495afd60b067a65920ba2e4705ccea71b880cc1607mmentovai if (!HttpSendRequest(request.get(), NULL, 0, 1505afd60b067a65920ba2e4705ccea71b880cc1607mmentovai const_cast<char *>(request_body.data()), 1515afd60b067a65920ba2e4705ccea71b880cc1607mmentovai static_cast<DWORD>(request_body.size()))) { 1525afd60b067a65920ba2e4705ccea71b880cc1607mmentovai return false; 1535afd60b067a65920ba2e4705ccea71b880cc1607mmentovai } 1545afd60b067a65920ba2e4705ccea71b880cc1607mmentovai 1555afd60b067a65920ba2e4705ccea71b880cc1607mmentovai // The server indicates a successful upload with HTTP status 200. 1565afd60b067a65920ba2e4705ccea71b880cc1607mmentovai wchar_t http_status[4]; 1575afd60b067a65920ba2e4705ccea71b880cc1607mmentovai DWORD http_status_size = sizeof(http_status); 1585afd60b067a65920ba2e4705ccea71b880cc1607mmentovai if (!HttpQueryInfo(request.get(), HTTP_QUERY_STATUS_CODE, 1595afd60b067a65920ba2e4705ccea71b880cc1607mmentovai static_cast<LPVOID>(&http_status), &http_status_size, 1605afd60b067a65920ba2e4705ccea71b880cc1607mmentovai 0)) { 1615afd60b067a65920ba2e4705ccea71b880cc1607mmentovai return false; 1625afd60b067a65920ba2e4705ccea71b880cc1607mmentovai } 1635afd60b067a65920ba2e4705ccea71b880cc1607mmentovai 164d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist int http_response = wcstol(http_status, NULL, 10); 165d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist if (response_code) { 166d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist *response_code = http_response; 167d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist } 168d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist 169d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist bool result = (http_response == 200); 170dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 171dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist if (result) { 172dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist result = ReadResponse(request.get(), response_body); 173dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist } 174dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 175dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist return result; 176dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist} 177dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 178dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist// static 179dd7c38baae8c9a08d3568217d3cad6309add576dincrementalistbool HTTPUpload::ReadResponse(HINTERNET request, wstring *response) { 1801de8bed899cc08b3453753132d137b8a953a4e8dmmentovai bool has_content_length_header = false; 181dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist wchar_t content_length[32]; 182dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist DWORD content_length_size = sizeof(content_length); 18328c645f3ee1d33c20e6ad7314c1454e8254809f2bryner DWORD claimed_size = 0; 1841de8bed899cc08b3453753132d137b8a953a4e8dmmentovai string response_body; 1851de8bed899cc08b3453753132d137b8a953a4e8dmmentovai 1861de8bed899cc08b3453753132d137b8a953a4e8dmmentovai if (HttpQueryInfo(request, HTTP_QUERY_CONTENT_LENGTH, 1871de8bed899cc08b3453753132d137b8a953a4e8dmmentovai static_cast<LPVOID>(&content_length), 1881de8bed899cc08b3453753132d137b8a953a4e8dmmentovai &content_length_size, 0)) { 1891de8bed899cc08b3453753132d137b8a953a4e8dmmentovai has_content_length_header = true; 1901de8bed899cc08b3453753132d137b8a953a4e8dmmentovai claimed_size = wcstol(content_length, NULL, 10); 1911de8bed899cc08b3453753132d137b8a953a4e8dmmentovai response_body.reserve(claimed_size); 192dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist } 193dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 1941de8bed899cc08b3453753132d137b8a953a4e8dmmentovai 1951de8bed899cc08b3453753132d137b8a953a4e8dmmentovai DWORD bytes_available; 196dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist DWORD total_read = 0; 1971de8bed899cc08b3453753132d137b8a953a4e8dmmentovai bool return_code; 1981de8bed899cc08b3453753132d137b8a953a4e8dmmentovai 1991de8bed899cc08b3453753132d137b8a953a4e8dmmentovai while ((return_code = InternetQueryDataAvailable(request, &bytes_available, 2001de8bed899cc08b3453753132d137b8a953a4e8dmmentovai 0, 0) != 0) && 2011de8bed899cc08b3453753132d137b8a953a4e8dmmentovai bytes_available > 0) { 2021de8bed899cc08b3453753132d137b8a953a4e8dmmentovai vector<char> response_buffer(bytes_available); 2031de8bed899cc08b3453753132d137b8a953a4e8dmmentovai DWORD size_read; 2041de8bed899cc08b3453753132d137b8a953a4e8dmmentovai 2051de8bed899cc08b3453753132d137b8a953a4e8dmmentovai if ((return_code = InternetReadFile(request, &response_buffer[0], 2061de8bed899cc08b3453753132d137b8a953a4e8dmmentovai bytes_available, &size_read) != 0) && 2071de8bed899cc08b3453753132d137b8a953a4e8dmmentovai size_read > 0) { 2081de8bed899cc08b3453753132d137b8a953a4e8dmmentovai total_read += size_read; 2091de8bed899cc08b3453753132d137b8a953a4e8dmmentovai response_body.append(&response_buffer[0], size_read); 2101de8bed899cc08b3453753132d137b8a953a4e8dmmentovai } else { 2111de8bed899cc08b3453753132d137b8a953a4e8dmmentovai break; 2121de8bed899cc08b3453753132d137b8a953a4e8dmmentovai } 2131de8bed899cc08b3453753132d137b8a953a4e8dmmentovai } 2141de8bed899cc08b3453753132d137b8a953a4e8dmmentovai 2151de8bed899cc08b3453753132d137b8a953a4e8dmmentovai bool succeeded = return_code && (!has_content_length_header || 2161de8bed899cc08b3453753132d137b8a953a4e8dmmentovai (total_read == claimed_size)); 217dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist if (succeeded && response) { 2181de8bed899cc08b3453753132d137b8a953a4e8dmmentovai *response = UTF8ToWide(response_body); 219dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist } 220dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 221dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist return succeeded; 2228b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner} 2238b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2248b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// static 2258b1645d8cdb34035c0b132fe8b574bc5ee48fb62brynerwstring HTTPUpload::GenerateMultipartBoundary() { 2268b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner // The boundary has 27 '-' characters followed by 16 hex digits 2278b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner static const wchar_t kBoundaryPrefix[] = L"---------------------------"; 2288b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner static const int kBoundaryLength = 27 + 16 + 1; 2298b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2308b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner // Generate some random numbers to fill out the boundary 2318b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner int r0 = rand(); 2328b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner int r1 = rand(); 2338b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2348b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner wchar_t temp[kBoundaryLength]; 235aec44489da7da17b5babd9343850257558741fa2mmentovai swprintf(temp, kBoundaryLength, L"%s%08X%08X", kBoundaryPrefix, r0, r1); 23630fc9ce1c0e671d7a4234ea70f7ed3906c627659mmentovai 23730fc9ce1c0e671d7a4234ea70f7ed3906c627659mmentovai // remove when VC++7.1 is no longer supported 23830fc9ce1c0e671d7a4234ea70f7ed3906c627659mmentovai temp[kBoundaryLength - 1] = L'\0'; 23930fc9ce1c0e671d7a4234ea70f7ed3906c627659mmentovai 2408b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return wstring(temp); 2418b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner} 2428b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2438b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// static 2448b1645d8cdb34035c0b132fe8b574bc5ee48fb62brynerwstring HTTPUpload::GenerateRequestHeader(const wstring &boundary) { 2458b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner wstring header = L"Content-Type: multipart/form-data; boundary="; 2468b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner header += boundary; 2478b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return header; 2488b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner} 2498b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2508b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// static 2518b1645d8cdb34035c0b132fe8b574bc5ee48fb62brynerbool HTTPUpload::GenerateRequestBody(const map<wstring, wstring> ¶meters, 2528b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner const wstring &upload_file, 2538b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner const wstring &file_part_name, 2548b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner const wstring &boundary, 2558b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner string *request_body) { 2568b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner vector<char> contents; 2578b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner GetFileContents(upload_file, &contents); 2588b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (contents.empty()) { 2598b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; 2608b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 2618b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2628b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner string boundary_str = WideToUTF8(boundary); 2638b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (boundary_str.empty()) { 2648b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; 2658b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 2668b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2678b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->clear(); 2688b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2698b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner // Append each of the parameter pairs as a form-data part 2708b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner for (map<wstring, wstring>::const_iterator pos = parameters.begin(); 2718b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner pos != parameters.end(); ++pos) { 2728b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->append("--" + boundary_str + "\r\n"); 2738b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->append("Content-Disposition: form-data; name=\"" + 2748b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner WideToUTF8(pos->first) + "\"\r\n\r\n" + 2758b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner WideToUTF8(pos->second) + "\r\n"); 2768b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 2778b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2788b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner // Now append the upload file as a binary (octet-stream) part 2798b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner string filename_utf8 = WideToUTF8(upload_file); 2808b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (filename_utf8.empty()) { 2818b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; 2828b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 2838b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2848b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner string file_part_name_utf8 = WideToUTF8(file_part_name); 2858b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (file_part_name_utf8.empty()) { 2868b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; 2878b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 2888b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2898b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->append("--" + boundary_str + "\r\n"); 2908b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->append("Content-Disposition: form-data; " 2918b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner "name=\"" + file_part_name_utf8 + "\"; " 2928b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner "filename=\"" + filename_utf8 + "\"\r\n"); 2938b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->append("Content-Type: application/octet-stream\r\n"); 2948b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->append("\r\n"); 2958b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 296c297c50f83344a35712c69563f75a70a3e3182e1bryner if (!contents.empty()) { 297c297c50f83344a35712c69563f75a70a3e3182e1bryner request_body->append(&(contents[0]), contents.size()); 298c297c50f83344a35712c69563f75a70a3e3182e1bryner } 2998b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->append("\r\n"); 3008b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->append("--" + boundary_str + "--\r\n"); 3018b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return true; 3028b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner} 3038b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 3048b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// static 3058b1645d8cdb34035c0b132fe8b574bc5ee48fb62brynervoid HTTPUpload::GetFileContents(const wstring &filename, 3068b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner vector<char> *contents) { 30773cd14b4af906e77f3d8b019962fb9979ff12620mmentovai // The "open" method on pre-MSVC8 ifstream implementations doesn't accept a 30873cd14b4af906e77f3d8b019962fb9979ff12620mmentovai // wchar_t* filename, so use _wfopen directly in that case. For VC8 and 30973cd14b4af906e77f3d8b019962fb9979ff12620mmentovai // later, _wfopen has been deprecated in favor of _wfopen_s, which does 31073cd14b4af906e77f3d8b019962fb9979ff12620mmentovai // not exist in earlier versions, so let the ifstream open the file itself. 31173cd14b4af906e77f3d8b019962fb9979ff12620mmentovai#if _MSC_VER >= 1400 // MSVC 2005/8 3128b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner ifstream file; 3138b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner file.open(filename.c_str(), ios::binary); 31473cd14b4af906e77f3d8b019962fb9979ff12620mmentovai#else // _MSC_VER >= 1400 31573cd14b4af906e77f3d8b019962fb9979ff12620mmentovai ifstream file(_wfopen(filename.c_str(), L"rb")); 31673cd14b4af906e77f3d8b019962fb9979ff12620mmentovai#endif // _MSC_VER >= 1400 3178b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (file.is_open()) { 3188b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner file.seekg(0, ios::end); 3198b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner int length = file.tellg(); 3208b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner contents->resize(length); 321c297c50f83344a35712c69563f75a70a3e3182e1bryner if (length != 0) { 322c297c50f83344a35712c69563f75a70a3e3182e1bryner file.seekg(0, ios::beg); 323c297c50f83344a35712c69563f75a70a3e3182e1bryner file.read(&((*contents)[0]), length); 324c297c50f83344a35712c69563f75a70a3e3182e1bryner } 3258b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner file.close(); 3268b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } else { 3278b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner contents->clear(); 3288b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 3298b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner} 3308b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 3318b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// static 332dd7c38baae8c9a08d3568217d3cad6309add576dincrementalistwstring HTTPUpload::UTF8ToWide(const string &utf8) { 333dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist if (utf8.length() == 0) { 334dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist return wstring(); 335dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist } 336dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 337dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist // compute the length of the buffer we'll need 338dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist int charcount = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0); 339dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 340dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist if (charcount == 0) { 341dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist return wstring(); 342dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist } 343dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 344dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist // convert 345dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist wchar_t* buf = new wchar_t[charcount]; 346dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, buf, charcount); 347dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist wstring result(buf); 348dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist delete[] buf; 349dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist return result; 350dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist} 351dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 352dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist// static 3538b1645d8cdb34035c0b132fe8b574bc5ee48fb62brynerstring HTTPUpload::WideToUTF8(const wstring &wide) { 3548b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (wide.length() == 0) { 3558b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return string(); 3568b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 3578b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 3588b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner // compute the length of the buffer we'll need 3598b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner int charcount = WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1, 3608b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner NULL, 0, NULL, NULL); 3618b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (charcount == 0) { 3628b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return string(); 3638b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 3648b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 3658b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner // convert 3668b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner char *buf = new char[charcount]; 3678b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1, buf, charcount, 3688b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner NULL, NULL); 3698b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 3708b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner string result(buf); 3718b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner delete[] buf; 3728b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return result; 3738b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner} 3748b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 3758b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// static 3768b1645d8cdb34035c0b132fe8b574bc5ee48fb62brynerbool HTTPUpload::CheckParameters(const map<wstring, wstring> ¶meters) { 3778b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner for (map<wstring, wstring>::const_iterator pos = parameters.begin(); 3788b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner pos != parameters.end(); ++pos) { 3798b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner const wstring &str = pos->first; 3808b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (str.size() == 0) { 3818b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; // disallow empty parameter names 3828b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 3838b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner for (unsigned int i = 0; i < str.size(); ++i) { 3848b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner wchar_t c = str[i]; 3858b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (c < 32 || c == '"' || c > 127) { 3868b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; 3878b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 3888b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 3898b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 3908b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return true; 3918b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner} 3928b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 393e5dc60822e5938fea2ae892ccddb906641ba174emmentovai} // namespace google_breakpad 394