From dd7c38baae8c9a08d3568217d3cad6309add576d Mon Sep 17 00:00:00 2001 From: incrementalist Date: Fri, 8 Dec 2006 20:45:20 +0000 Subject: This patch fixes Airbag issue #44. Summary of this patch: * It adds a new wstring* parameter to the end of both SendCrashReport() and HTTPUpload::SendRequest(), which can be NULL. * If the request isn't successful, the result parameter isn't touched. * It adds HTTPUpload::UTF8ToWide() to allow the response to be returned as a wstring, * It changes the return value of SendRequest (and by extension, SendCrashReport) so that if the size of the response body isn't exactly the same as the value given in the Content-Length header, the return value is false (in addition to the previous semantics). * It also updates symupload.cc to account for the new parameter in SendRequest(). git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@81 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/client/windows/sender/crash_report_sender.cc | 4 +- src/client/windows/sender/crash_report_sender.h | 9 +++- src/common/windows/http_upload.cc | 64 ++++++++++++++++++++++-- src/common/windows/http_upload.h | 18 ++++++- src/tools/windows/symupload/symupload.cc | 2 +- 5 files changed, 86 insertions(+), 11 deletions(-) diff --git a/src/client/windows/sender/crash_report_sender.cc b/src/client/windows/sender/crash_report_sender.cc index 0c48c875..485ffc36 100644 --- a/src/client/windows/sender/crash_report_sender.cc +++ b/src/client/windows/sender/crash_report_sender.cc @@ -38,10 +38,10 @@ namespace google_airbag { // static bool CrashReportSender::SendCrashReport( const wstring &url, const map ¶meters, - const wstring &dump_file_name) { + const wstring &dump_file_name, wstring *report_code) { return HTTPUpload::SendRequest(url, parameters, dump_file_name, - L"upload_file_minidump"); + L"upload_file_minidump", report_code); } } // namespace google_airbag diff --git a/src/client/windows/sender/crash_report_sender.h b/src/client/windows/sender/crash_report_sender.h index a909c466..c44c5e74 100644 --- a/src/client/windows/sender/crash_report_sender.h +++ b/src/client/windows/sender/crash_report_sender.h @@ -56,11 +56,16 @@ class CrashReportSender { // name value pairs, as a multipart POST request to the given URL. // Parameter names must contain only printable ASCII characters, // and may not contain a quote (") character. + // If the report is sent successfully (the return value is true), a + // code uniquely identifying the report will be returned in report_code. // Only HTTP(S) URLs are currently supported. Returns true on success. - // TODO(bryner): we should expose the response to the caller. + // If report_code is non-NULL and the report is sent successfully (that is, + // the return value is true), a code uniquely identifying the report will be + // returned in report_code. (Otherwise, report_code will be unchanged.) static bool SendCrashReport(const wstring &url, const map ¶meters, - const wstring &dump_file_name); + const wstring &dump_file_name, + wstring *report_code); private: // No instances of this class should be created. diff --git a/src/common/windows/http_upload.cc b/src/common/windows/http_upload.cc index 54e7ff85..59e541f0 100644 --- a/src/common/windows/http_upload.cc +++ b/src/common/windows/http_upload.cc @@ -28,8 +28,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -#include -#include // Disable exception handler warnings. #pragma warning( disable : 4530 ) @@ -67,7 +65,8 @@ class HTTPUpload::AutoInternetHandle { bool HTTPUpload::SendRequest(const wstring &url, const map ¶meters, const wstring &upload_file, - const wstring &file_part_name) { + const wstring &file_part_name, + wstring *response_body) { // TODO(bryner): support non-ASCII parameter names if (!CheckParameters(parameters)) { return false; @@ -154,7 +153,43 @@ bool HTTPUpload::SendRequest(const wstring &url, return false; } - return (wcscmp(http_status, L"200") == 0); + bool result = (wcscmp(http_status, L"200") == 0); + + if (result) { + result = ReadResponse(request.get(), response_body); + } + + return result; +} + +// static +bool HTTPUpload::ReadResponse(HINTERNET request, wstring *response) { + wchar_t content_length[32]; + DWORD content_length_size = sizeof(content_length); + if (!HttpQueryInfo(request, HTTP_QUERY_CONTENT_LENGTH, + static_cast(&content_length), &content_length_size, + 0)) { + return false; + } + DWORD claimed_size = wcstol(content_length, NULL, 10); + + char *response_buffer = new char[claimed_size]; + DWORD size_read; + DWORD total_read = 0; + BOOL read_result; + do { + read_result = InternetReadFile(request, response_buffer + total_read, + claimed_size - total_read, &size_read); + total_read += size_read; + } while (read_result && (size_read != 0) && (total_read < claimed_size)); + + bool succeeded = (total_read == claimed_size); + if (succeeded && response) { + *response = UTF8ToWide(string(response_buffer, total_read)); + } + + delete[] response_buffer; + return succeeded; } // static @@ -261,6 +296,27 @@ void HTTPUpload::GetFileContents(const wstring &filename, } } +// static +wstring HTTPUpload::UTF8ToWide(const string &utf8) { + if (utf8.length() == 0) { + return wstring(); + } + + // compute the length of the buffer we'll need + int charcount = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0); + + if (charcount == 0) { + return wstring(); + } + + // convert + wchar_t* buf = new wchar_t[charcount]; + MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, buf, charcount); + wstring result(buf); + delete[] buf; + return result; +} + // static string HTTPUpload::WideToUTF8(const wstring &wide) { if (wide.length() == 0) { diff --git a/src/common/windows/http_upload.h b/src/common/windows/http_upload.h index 4d86eded..a23a0f2b 100644 --- a/src/common/windows/http_upload.h +++ b/src/common/windows/http_upload.h @@ -38,6 +38,9 @@ // Disable exception handler warnings. #pragma warning( disable : 4530 ) +#include +#include + #include #include #include @@ -58,15 +61,23 @@ class HTTPUpload { // Parameter names must contain only printable ASCII characters, // and may not contain a quote (") character. // Only HTTP(S) URLs are currently supported. Returns true on success. - // TODO(bryner): we should expose the response to the caller. + // If the request is successful and response_body is non-NULL, + // the response body will be returned in response_body. static bool SendRequest(const wstring &url, const map ¶meters, const wstring &upload_file, - const wstring &file_part_name); + const wstring &file_part_name, + wstring *response_body); private: class AutoInternetHandle; + // Retrieves the HTTP response. If NULL is passed in for response, + // this merely checks (via the return value) that we were successfully + // able to retrieve exactly as many bytes of content in the response as + // were specified in the Content-Length header. + static bool HTTPUpload::ReadResponse(HINTERNET request, wstring* response); + // Generates a new multipart boundary for a POST request static wstring GenerateMultipartBoundary(); @@ -85,6 +96,9 @@ class HTTPUpload { // Fills the supplied vector with the contents of filename. static void GetFileContents(const wstring &filename, vector *contents); + // Converts a UTF8 string to UTF16. + static wstring UTF8ToWide(const string &utf8); + // Converts a UTF16 string to UTF8. static string WideToUTF8(const wstring &wide); diff --git a/src/tools/windows/symupload/symupload.cc b/src/tools/windows/symupload/symupload.cc index d829aa91..25de747a 100644 --- a/src/tools/windows/symupload/symupload.cc +++ b/src/tools/windows/symupload/symupload.cc @@ -182,7 +182,7 @@ int wmain(int argc, wchar_t *argv[]) { } bool success = HTTPUpload::SendRequest(url, parameters, - symbol_file, L"symbol_file"); + symbol_file, L"symbol_file", NULL); _wunlink(symbol_file.c_str()); if (!success) { -- cgit v1.2.1