http_upload.cc revision 28c645f3ee1d33c20e6ad7314c1454e8254809f2
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; 868b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner components.dwSchemeLength = sizeof(scheme); 878b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner components.lpszHostName = host; 888b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner components.dwHostNameLength = sizeof(host); 898b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner components.lpszUrlPath = path; 908b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner components.dwUrlPathLength = sizeof(path); 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(), 1408b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner -1, HTTP_ADDREQ_FLAG_ADD); 1418b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 1428b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner string request_body; 143684649a57172532274e2b8b1307af6fa11fdabceted.mielczarek if (!GenerateRequestBody(parameters, upload_file, 144684649a57172532274e2b8b1307af6fa11fdabceted.mielczarek file_part_name, boundary, &request_body)) { 145684649a57172532274e2b8b1307af6fa11fdabceted.mielczarek return false; 146684649a57172532274e2b8b1307af6fa11fdabceted.mielczarek } 1478b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 1485afd60b067a65920ba2e4705ccea71b880cc1607mmentovai if (!HttpSendRequest(request.get(), NULL, 0, 1495afd60b067a65920ba2e4705ccea71b880cc1607mmentovai const_cast<char *>(request_body.data()), 1505afd60b067a65920ba2e4705ccea71b880cc1607mmentovai static_cast<DWORD>(request_body.size()))) { 1515afd60b067a65920ba2e4705ccea71b880cc1607mmentovai return false; 1525afd60b067a65920ba2e4705ccea71b880cc1607mmentovai } 1535afd60b067a65920ba2e4705ccea71b880cc1607mmentovai 1545afd60b067a65920ba2e4705ccea71b880cc1607mmentovai // The server indicates a successful upload with HTTP status 200. 1555afd60b067a65920ba2e4705ccea71b880cc1607mmentovai wchar_t http_status[4]; 1565afd60b067a65920ba2e4705ccea71b880cc1607mmentovai DWORD http_status_size = sizeof(http_status); 1575afd60b067a65920ba2e4705ccea71b880cc1607mmentovai if (!HttpQueryInfo(request.get(), HTTP_QUERY_STATUS_CODE, 1585afd60b067a65920ba2e4705ccea71b880cc1607mmentovai static_cast<LPVOID>(&http_status), &http_status_size, 1595afd60b067a65920ba2e4705ccea71b880cc1607mmentovai 0)) { 1605afd60b067a65920ba2e4705ccea71b880cc1607mmentovai return false; 1615afd60b067a65920ba2e4705ccea71b880cc1607mmentovai } 1625afd60b067a65920ba2e4705ccea71b880cc1607mmentovai 163d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist int http_response = wcstol(http_status, NULL, 10); 164d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist if (response_code) { 165d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist *response_code = http_response; 166d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist } 167d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist 168d4e527b7eea7628e305e6ca93cdcb9796060d65aincrementalist bool result = (http_response == 200); 169dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 170dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist if (result) { 171dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist result = ReadResponse(request.get(), response_body); 172dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist } 173dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 174dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist return result; 175dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist} 176dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 177dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist// static 178dd7c38baae8c9a08d3568217d3cad6309add576dincrementalistbool HTTPUpload::ReadResponse(HINTERNET request, wstring *response) { 1791de8bed899cc08b3453753132d137b8a953a4e8dmmentovai bool has_content_length_header = false; 180dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist wchar_t content_length[32]; 181dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist DWORD content_length_size = sizeof(content_length); 18228c645f3ee1d33c20e6ad7314c1454e8254809f2bryner DWORD claimed_size = 0; 1831de8bed899cc08b3453753132d137b8a953a4e8dmmentovai string response_body; 1841de8bed899cc08b3453753132d137b8a953a4e8dmmentovai 1851de8bed899cc08b3453753132d137b8a953a4e8dmmentovai if (HttpQueryInfo(request, HTTP_QUERY_CONTENT_LENGTH, 1861de8bed899cc08b3453753132d137b8a953a4e8dmmentovai static_cast<LPVOID>(&content_length), 1871de8bed899cc08b3453753132d137b8a953a4e8dmmentovai &content_length_size, 0)) { 1881de8bed899cc08b3453753132d137b8a953a4e8dmmentovai has_content_length_header = true; 1891de8bed899cc08b3453753132d137b8a953a4e8dmmentovai claimed_size = wcstol(content_length, NULL, 10); 1901de8bed899cc08b3453753132d137b8a953a4e8dmmentovai response_body.reserve(claimed_size); 191dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist } 192dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 1931de8bed899cc08b3453753132d137b8a953a4e8dmmentovai 1941de8bed899cc08b3453753132d137b8a953a4e8dmmentovai DWORD bytes_available; 195dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist DWORD total_read = 0; 1961de8bed899cc08b3453753132d137b8a953a4e8dmmentovai bool return_code; 1971de8bed899cc08b3453753132d137b8a953a4e8dmmentovai 1981de8bed899cc08b3453753132d137b8a953a4e8dmmentovai while ((return_code = InternetQueryDataAvailable(request, &bytes_available, 1991de8bed899cc08b3453753132d137b8a953a4e8dmmentovai 0, 0) != 0) && 2001de8bed899cc08b3453753132d137b8a953a4e8dmmentovai bytes_available > 0) { 2011de8bed899cc08b3453753132d137b8a953a4e8dmmentovai vector<char> response_buffer(bytes_available); 2021de8bed899cc08b3453753132d137b8a953a4e8dmmentovai DWORD size_read; 2031de8bed899cc08b3453753132d137b8a953a4e8dmmentovai 2041de8bed899cc08b3453753132d137b8a953a4e8dmmentovai if ((return_code = InternetReadFile(request, &response_buffer[0], 2051de8bed899cc08b3453753132d137b8a953a4e8dmmentovai bytes_available, &size_read) != 0) && 2061de8bed899cc08b3453753132d137b8a953a4e8dmmentovai size_read > 0) { 2071de8bed899cc08b3453753132d137b8a953a4e8dmmentovai total_read += size_read; 2081de8bed899cc08b3453753132d137b8a953a4e8dmmentovai response_body.append(&response_buffer[0], size_read); 2091de8bed899cc08b3453753132d137b8a953a4e8dmmentovai } else { 2101de8bed899cc08b3453753132d137b8a953a4e8dmmentovai break; 2111de8bed899cc08b3453753132d137b8a953a4e8dmmentovai } 2121de8bed899cc08b3453753132d137b8a953a4e8dmmentovai } 2131de8bed899cc08b3453753132d137b8a953a4e8dmmentovai 2141de8bed899cc08b3453753132d137b8a953a4e8dmmentovai bool succeeded = return_code && (!has_content_length_header || 2151de8bed899cc08b3453753132d137b8a953a4e8dmmentovai (total_read == claimed_size)); 216dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist if (succeeded && response) { 2171de8bed899cc08b3453753132d137b8a953a4e8dmmentovai *response = UTF8ToWide(response_body); 218dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist } 219dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 220dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist return succeeded; 2218b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner} 2228b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2238b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// static 2248b1645d8cdb34035c0b132fe8b574bc5ee48fb62brynerwstring HTTPUpload::GenerateMultipartBoundary() { 2258b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner // The boundary has 27 '-' characters followed by 16 hex digits 2268b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner static const wchar_t kBoundaryPrefix[] = L"---------------------------"; 2278b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner static const int kBoundaryLength = 27 + 16 + 1; 2288b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2298b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner // Generate some random numbers to fill out the boundary 2308b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner int r0 = rand(); 2318b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner int r1 = rand(); 2328b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2338b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner wchar_t temp[kBoundaryLength]; 234aec44489da7da17b5babd9343850257558741fa2mmentovai swprintf(temp, kBoundaryLength, L"%s%08X%08X", kBoundaryPrefix, r0, r1); 23530fc9ce1c0e671d7a4234ea70f7ed3906c627659mmentovai 23630fc9ce1c0e671d7a4234ea70f7ed3906c627659mmentovai // remove when VC++7.1 is no longer supported 23730fc9ce1c0e671d7a4234ea70f7ed3906c627659mmentovai temp[kBoundaryLength - 1] = L'\0'; 23830fc9ce1c0e671d7a4234ea70f7ed3906c627659mmentovai 2398b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return wstring(temp); 2408b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner} 2418b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2428b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// static 2438b1645d8cdb34035c0b132fe8b574bc5ee48fb62brynerwstring HTTPUpload::GenerateRequestHeader(const wstring &boundary) { 2448b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner wstring header = L"Content-Type: multipart/form-data; boundary="; 2458b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner header += boundary; 2468b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return header; 2478b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner} 2488b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2498b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// static 2508b1645d8cdb34035c0b132fe8b574bc5ee48fb62brynerbool HTTPUpload::GenerateRequestBody(const map<wstring, wstring> ¶meters, 2518b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner const wstring &upload_file, 2528b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner const wstring &file_part_name, 2538b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner const wstring &boundary, 2548b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner string *request_body) { 2558b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner vector<char> contents; 2568b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner GetFileContents(upload_file, &contents); 2578b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (contents.empty()) { 2588b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; 2598b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 2608b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2618b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner string boundary_str = WideToUTF8(boundary); 2628b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (boundary_str.empty()) { 2638b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; 2648b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 2658b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2668b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->clear(); 2678b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2688b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner // Append each of the parameter pairs as a form-data part 2698b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner for (map<wstring, wstring>::const_iterator pos = parameters.begin(); 2708b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner pos != parameters.end(); ++pos) { 2718b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->append("--" + boundary_str + "\r\n"); 2728b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->append("Content-Disposition: form-data; name=\"" + 2738b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner WideToUTF8(pos->first) + "\"\r\n\r\n" + 2748b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner WideToUTF8(pos->second) + "\r\n"); 2758b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 2768b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2778b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner // Now append the upload file as a binary (octet-stream) part 2788b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner string filename_utf8 = WideToUTF8(upload_file); 2798b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (filename_utf8.empty()) { 2808b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; 2818b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 2828b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2838b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner string file_part_name_utf8 = WideToUTF8(file_part_name); 2848b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (file_part_name_utf8.empty()) { 2858b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; 2868b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 2878b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 2888b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->append("--" + boundary_str + "\r\n"); 2898b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->append("Content-Disposition: form-data; " 2908b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner "name=\"" + file_part_name_utf8 + "\"; " 2918b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner "filename=\"" + filename_utf8 + "\"\r\n"); 2928b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->append("Content-Type: application/octet-stream\r\n"); 2938b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->append("\r\n"); 2948b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 295c297c50f83344a35712c69563f75a70a3e3182e1bryner if (!contents.empty()) { 296c297c50f83344a35712c69563f75a70a3e3182e1bryner request_body->append(&(contents[0]), contents.size()); 297c297c50f83344a35712c69563f75a70a3e3182e1bryner } 2988b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->append("\r\n"); 2998b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner request_body->append("--" + boundary_str + "--\r\n"); 3008b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return true; 3018b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner} 3028b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 3038b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// static 3048b1645d8cdb34035c0b132fe8b574bc5ee48fb62brynervoid HTTPUpload::GetFileContents(const wstring &filename, 3058b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner vector<char> *contents) { 30673cd14b4af906e77f3d8b019962fb9979ff12620mmentovai // The "open" method on pre-MSVC8 ifstream implementations doesn't accept a 30773cd14b4af906e77f3d8b019962fb9979ff12620mmentovai // wchar_t* filename, so use _wfopen directly in that case. For VC8 and 30873cd14b4af906e77f3d8b019962fb9979ff12620mmentovai // later, _wfopen has been deprecated in favor of _wfopen_s, which does 30973cd14b4af906e77f3d8b019962fb9979ff12620mmentovai // not exist in earlier versions, so let the ifstream open the file itself. 31073cd14b4af906e77f3d8b019962fb9979ff12620mmentovai#if _MSC_VER >= 1400 // MSVC 2005/8 3118b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner ifstream file; 3128b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner file.open(filename.c_str(), ios::binary); 31373cd14b4af906e77f3d8b019962fb9979ff12620mmentovai#else // _MSC_VER >= 1400 31473cd14b4af906e77f3d8b019962fb9979ff12620mmentovai ifstream file(_wfopen(filename.c_str(), L"rb")); 31573cd14b4af906e77f3d8b019962fb9979ff12620mmentovai#endif // _MSC_VER >= 1400 3168b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (file.is_open()) { 3178b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner file.seekg(0, ios::end); 3188b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner int length = file.tellg(); 3198b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner contents->resize(length); 320c297c50f83344a35712c69563f75a70a3e3182e1bryner if (length != 0) { 321c297c50f83344a35712c69563f75a70a3e3182e1bryner file.seekg(0, ios::beg); 322c297c50f83344a35712c69563f75a70a3e3182e1bryner file.read(&((*contents)[0]), length); 323c297c50f83344a35712c69563f75a70a3e3182e1bryner } 3248b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner file.close(); 3258b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } else { 3268b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner contents->clear(); 3278b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 3288b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner} 3298b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 3308b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// static 331dd7c38baae8c9a08d3568217d3cad6309add576dincrementalistwstring HTTPUpload::UTF8ToWide(const string &utf8) { 332dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist if (utf8.length() == 0) { 333dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist return wstring(); 334dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist } 335dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 336dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist // compute the length of the buffer we'll need 337dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist int charcount = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0); 338dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 339dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist if (charcount == 0) { 340dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist return wstring(); 341dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist } 342dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 343dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist // convert 344dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist wchar_t* buf = new wchar_t[charcount]; 345dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, buf, charcount); 346dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist wstring result(buf); 347dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist delete[] buf; 348dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist return result; 349dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist} 350dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist 351dd7c38baae8c9a08d3568217d3cad6309add576dincrementalist// static 3528b1645d8cdb34035c0b132fe8b574bc5ee48fb62brynerstring HTTPUpload::WideToUTF8(const wstring &wide) { 3538b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (wide.length() == 0) { 3548b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return string(); 3558b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 3568b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 3578b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner // compute the length of the buffer we'll need 3588b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner int charcount = WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1, 3598b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner NULL, 0, NULL, NULL); 3608b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (charcount == 0) { 3618b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return string(); 3628b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 3638b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 3648b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner // convert 3658b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner char *buf = new char[charcount]; 3668b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1, buf, charcount, 3678b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner NULL, NULL); 3688b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 3698b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner string result(buf); 3708b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner delete[] buf; 3718b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return result; 3728b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner} 3738b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 3748b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner// static 3758b1645d8cdb34035c0b132fe8b574bc5ee48fb62brynerbool HTTPUpload::CheckParameters(const map<wstring, wstring> ¶meters) { 3768b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner for (map<wstring, wstring>::const_iterator pos = parameters.begin(); 3778b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner pos != parameters.end(); ++pos) { 3788b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner const wstring &str = pos->first; 3798b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (str.size() == 0) { 3808b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; // disallow empty parameter names 3818b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 3828b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner for (unsigned int i = 0; i < str.size(); ++i) { 3838b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner wchar_t c = str[i]; 3848b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner if (c < 32 || c == '"' || c > 127) { 3858b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return false; 3868b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 3878b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 3888b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner } 3898b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner return true; 3908b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner} 3918b1645d8cdb34035c0b132fe8b574bc5ee48fb62bryner 392e5dc60822e5938fea2ae892ccddb906641ba174emmentovai} // namespace google_breakpad 393