Source code

Revision control

Copy as Markdown

Other Tools

diff --git a/src/common/linux/http_upload.cc b/src/common/linux/http_upload.cc
index 702526af..0a1019dd 100644
--- a/src/common/linux/http_upload.cc
+++ b/src/common/linux/http_upload.cc
@@ -55,7 +55,7 @@ static const char kUserAgent[] = "Breakpad/1.0 (Linux)";
// static
bool HTTPUpload::SendRequest(const string &url,
- const map<string, string> &parameters,
+ const string &parameters,
const map<string, string> &files,
const string &proxy,
const string &proxy_user_pwd,
@@ -66,9 +66,6 @@ bool HTTPUpload::SendRequest(const string &url,
if (response_code != NULL)
*response_code = 0;
- if (!CheckParameters(parameters))
- return false;
-
// We may have been linked statically; if curl_easy_init is in the
// current binary, no need to search for a dynamic version.
void* curl_lib = dlopen(NULL, RTLD_NOW);
@@ -133,14 +130,14 @@ bool HTTPUpload::SendRequest(const string &url,
// Add form data.
CURLFORMcode (*curl_formadd)(struct curl_httppost **, struct curl_httppost **, ...);
*(void**) (&curl_formadd) = dlsym(curl_lib, "curl_formadd");
- map<string, string>::const_iterator iter = parameters.begin();
- for (; iter != parameters.end(); ++iter)
- (*curl_formadd)(&formpost, &lastptr,
- CURLFORM_COPYNAME, iter->first.c_str(),
- CURLFORM_COPYCONTENTS, iter->second.c_str(),
- CURLFORM_END);
+ (*curl_formadd)(&formpost, &lastptr, CURLFORM_COPYNAME, "extra",
+ CURLFORM_BUFFER, "extra.json", CURLFORM_BUFFERPTR,
+ parameters.c_str(), CURLFORM_BUFFERLENGTH,
+ parameters.length(), CURLFORM_CONTENTTYPE, "application/json",
+ CURLFORM_END);
// Add form files.
+ map<string, string>::const_iterator iter = files.begin();
for (iter = files.begin(); iter != files.end(); ++iter) {
(*curl_formadd)(&formpost, &lastptr,
CURLFORM_COPYNAME, iter->first.c_str(),
@@ -210,21 +207,4 @@ bool HTTPUpload::CheckCurlLib(void* curl_lib) {
dlsym(curl_lib, "curl_easy_setopt");
}
-// static
-bool HTTPUpload::CheckParameters(const map<string, string> &parameters) {
- for (map<string, string>::const_iterator pos = parameters.begin();
- pos != parameters.end(); ++pos) {
- const string &str = pos->first;
- if (str.size() == 0)
- return false; // disallow empty parameter names
- for (unsigned int i = 0; i < str.size(); ++i) {
- int c = str[i];
- if (c < 32 || c == '"' || c > 127) {
- return false;
- }
- }
- }
- return true;
-}
-
} // namespace google_breakpad
diff --git a/src/common/linux/http_upload.h b/src/common/linux/http_upload.h
index bc1d5d57..95dedebc 100644
--- a/src/common/linux/http_upload.h
+++ b/src/common/linux/http_upload.h
@@ -29,7 +29,7 @@
// HTTPUpload provides a "nice" API to send a multipart HTTP(S) POST
// request using libcurl. It currently supports requests that contain
-// a set of string parameters (key/value pairs), and a file to upload.
+// parameters encoded in a JSON string, and a file to upload.
#ifndef COMMON_LINUX_HTTP_UPLOAD_H__
#define COMMON_LINUX_HTTP_UPLOAD_H__
@@ -49,8 +49,7 @@ class HTTPUpload {
// request to the given URL.
// Each key in |files| is the name of the file part of the request
// (i.e. it corresponds to the name= attribute on an <input type="file">.
- // Parameter names must contain only printable ASCII characters,
- // and may not contain a quote (") character.
+ // Parameters are specified as a JSON-encoded string in |parameters|.
// Only HTTP(S) URLs are currently supported. Returns true on success.
// If the request is successful and response_body is non-NULL,
// the response body will be returned in response_body.
@@ -59,7 +58,7 @@ class HTTPUpload {
// If the send fails, a description of the error will be
// returned in error_description.
static bool SendRequest(const string &url,
- const map<string, string> &parameters,
+ const string &parameters,
const map<string, string> &files,
const string &proxy,
const string &proxy_user_pwd,
@@ -69,11 +68,6 @@ class HTTPUpload {
string *error_description);
private:
- // Checks that the given list of parameters has only printable
- // ASCII characters in the parameter name, and does not contain
- // any quote (") characters. Returns true if so.
- static bool CheckParameters(const map<string, string> &parameters);
-
// Checks the curl_lib parameter points to a valid curl lib.
static bool CheckCurlLib(void* curl_lib);
diff --git a/src/common/mac/HTTPMultipartUpload.h b/src/common/mac/HTTPMultipartUpload.h
index 42e8fed3..0cea733e 100644
--- a/src/common/mac/HTTPMultipartUpload.h
+++ b/src/common/mac/HTTPMultipartUpload.h
@@ -37,7 +37,7 @@
@interface HTTPMultipartUpload : NSObject {
@protected
NSURL *url_; // The destination URL (STRONG)
- NSDictionary *parameters_; // The key/value pairs for sending data (STRONG)
+ NSMutableString *parameters_; // The JSON payload for sending data (STRONG)
NSMutableDictionary *files_; // Dictionary of name/file-path (STRONG)
NSString *boundary_; // The boundary string (STRONG)
NSHTTPURLResponse *response_; // The response from the send (STRONG)
@@ -47,8 +47,8 @@
- (NSURL *)URL;
-- (void)setParameters:(NSDictionary *)parameters;
-- (NSDictionary *)parameters;
+- (void)setParameters:(NSMutableString *)parameters;
+- (NSMutableString *)parameters;
- (void)addFileAtPath:(NSString *)path name:(NSString *)name;
- (void)addFileContents:(NSData *)data name:(NSString *)name;
diff --git a/src/common/mac/HTTPMultipartUpload.m b/src/common/mac/HTTPMultipartUpload.m
index a3677f25..d2480493 100644
--- a/src/common/mac/HTTPMultipartUpload.m
+++ b/src/common/mac/HTTPMultipartUpload.m
@@ -93,7 +93,7 @@ static NSData *SendSynchronousNSURLRequest(NSURLRequest *req,
- (NSString *)multipartBoundary;
// Each of the following methods will append the starting multipart boundary,
// but not the ending one.
-- (NSData *)formDataForKey:(NSString *)key value:(NSString *)value;
+- (NSData *)formDataForJSON:(NSString *)json;
- (NSData *)formDataForFileContents:(NSData *)contents name:(NSString *)name;
- (NSData *)formDataForFile:(NSString *)file name:(NSString *)name;
@end
@@ -110,13 +110,16 @@ static NSData *SendSynchronousNSURLRequest(NSURLRequest *req,
}
//=============================================================================
-- (NSData *)formDataForKey:(NSString *)key value:(NSString *)value {
- NSString *escaped = PercentEncodeNSString(key);
- NSString *fmt =
- @"--%@\r\nContent-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n";
- NSString *form = [NSString stringWithFormat:fmt, boundary_, escaped, value];
+- (NSData *)formDataForJSON:(NSString *)json {
+ NSMutableData *data = [NSMutableData data];
+ NSString *fmt = @"--%@\r\nContent-Disposition: form-data; name=\"extra\"; "
+ "filename=\"extra.json\"\r\nContent-Type: application/json\r\n\r\n";
+ NSString *form = [NSString stringWithFormat:fmt, boundary_];
+
+ [data appendData:[form dataUsingEncoding:NSUTF8StringEncoding]];
+ [data appendData:[json dataUsingEncoding:NSUTF8StringEncoding]];
- return [form dataUsingEncoding:NSUTF8StringEncoding];
+ return data;
}
//=============================================================================
@@ -171,15 +174,15 @@ static NSData *SendSynchronousNSURLRequest(NSURLRequest *req,
}
//=============================================================================
-- (void)setParameters:(NSDictionary *)parameters {
+- (void)setParameters:(NSMutableString *)parameters {
if (parameters != parameters_) {
[parameters_ release];
- parameters_ = [parameters copy];
+ parameters_ = [parameters mutableCopy];
}
}
//=============================================================================
-- (NSDictionary *)parameters {
+- (NSMutableString *)parameters {
return parameters_;
}
@@ -210,16 +213,8 @@ static NSData *SendSynchronousNSURLRequest(NSURLRequest *req,
[req setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",
boundary_] forHTTPHeaderField:@"Content-type"];
- // Add any parameters to the message
- NSArray *parameterKeys = [parameters_ allKeys];
- NSString *key;
-
- NSInteger count = [parameterKeys count];
- for (NSInteger i = 0; i < count; ++i) {
- key = [parameterKeys objectAtIndex:i];
- [postBody appendData:[self formDataForKey:key
- value:[parameters_ objectForKey:key]]];
- }
+ // Add JSON parameters to the message
+ [postBody appendData:[self formDataForJSON:parameters_]];
// Add any files to the message
NSArray *fileNames = [files_ allKeys];
diff --git a/src/common/windows/http_upload.cc b/src/common/windows/http_upload.cc
index b0cc9078..5df17e1a 100644
--- a/src/common/windows/http_upload.cc
+++ b/src/common/windows/http_upload.cc
@@ -141,23 +141,6 @@ namespace {
return rv;
}
- bool CheckParameters(const map<wstring, wstring> &parameters) {
- for (map<wstring, wstring>::const_iterator pos = parameters.begin();
- pos != parameters.end(); ++pos) {
- const wstring &str = pos->first;
- if (str.size() == 0) {
- return false; // disallow empty parameter names
- }
- for (unsigned int i = 0; i < str.size(); ++i) {
- wchar_t c = str[i];
- if (c < 32 || c == '"' || c > 127) {
- return false;
- }
- }
- }
- return true;
- }
-
// Converts a UTF16 string to UTF8.
string WideToUTF8(const wstring &wide) {
return WideToMBCP(wide, CP_UTF8);
@@ -390,7 +373,7 @@ namespace {
return true;
}
- bool GenerateRequestBody(const map<wstring, wstring> &parameters,
+ bool GenerateRequestBody(const string &parameters,
const map<wstring, wstring> &files,
const wstring &boundary,
string *request_body) {
@@ -401,14 +384,19 @@ namespace {
request_body->clear();
- // Append each of the parameter pairs as a form-data part
- for (map<wstring, wstring>::const_iterator pos = parameters.begin();
- pos != parameters.end(); ++pos) {
- request_body->append("--" + boundary_str + "\r\n");
- request_body->append("Content-Disposition: form-data; name=\"" +
- WideToUTF8(pos->first) + "\"\r\n\r\n" +
- WideToUTF8(pos->second) + "\r\n");
+ // Append the extra data as a single JSON form entry
+ request_body->append("--" + boundary_str + "\r\n");
+ request_body->append(
+ "Content-Disposition: form-data; "
+ "name=\"extra\"; "
+ "filename=\"extra.json\"\r\n");
+ request_body->append("Content-Type: application/json\r\n");
+ request_body->append("\r\n");
+
+ if (!parameters.empty()) {
+ request_body->append(parameters);
}
+ request_body->append("\r\n");
// Now append each upload file as a binary (octet-stream) part
for (map<wstring, wstring>::const_iterator pos = files.begin();
@@ -463,16 +451,11 @@ namespace google_breakpad {
bool HTTPUpload::SendMultipartPostRequest(
const wstring& url,
- const map<wstring, wstring>& parameters,
+ const string& parameters,
const map<wstring, wstring>& files,
int* timeout_ms,
wstring* response_body,
int* response_code) {
- // TODO(bryner): support non-ASCII parameter names
- if (!CheckParameters(parameters)) {
- return false;
- }
-
wstring boundary = GenerateMultipartBoundary();
wstring content_type_header = GenerateMultipartPostRequestHeader(boundary);
diff --git a/src/common/windows/http_upload.h b/src/common/windows/http_upload.h
index 57e526e3..1e47f582 100644
--- a/src/common/windows/http_upload.h
+++ b/src/common/windows/http_upload.h
@@ -29,7 +29,7 @@
// HTTPUpload provides a "nice" API to send a multipart HTTP(S) POST
// request using wininet. It currently supports requests that contain
-// a set of string parameters (key/value pairs), and a file to upload.
+// parameters encoded in a JSON string, and a file to upload.
#ifndef COMMON_WINDOWS_HTTP_UPLOAD_H_
#define COMMON_WINDOWS_HTTP_UPLOAD_H_
@@ -45,9 +45,9 @@
namespace google_breakpad {
+using std::map;
using std::string;
using std::wstring;
-using std::map;
class HTTPUpload {
public:
@@ -81,8 +81,7 @@ class HTTPUpload {
// request to the given URL.
// Each key in |files| is the name of the file part of the request
// (i.e. it corresponds to the name= attribute on an <input type="file">.
- // Parameter names must contain only printable ASCII characters,
- // and may not contain a quote (") character.
+ // Parameters are specified as a JSON-encoded string in |parameters|.
// Only HTTP(S) URLs are currently supported. Returns true on success.
// If the request is successful and response_body is non-NULL,
// the response body will be returned in response_body.
@@ -90,7 +89,7 @@ class HTTPUpload {
// received (or 0 if the request failed before getting an HTTP response).
static bool SendMultipartPostRequest(
const wstring& url,
- const map<wstring, wstring>& parameters,
+ const string& parameters,
const map<wstring, wstring>& files,
int *timeout_ms,
wstring *response_body,