Port new symbol API to symupload on Mac.

- See documentation in Linux implementation commit: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/1422400.

Change-Id: If3ff256e63f2db3ac9c0be78cfc17754d532cb88
Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/1497653
Reviewed-by: Ivan Penkov <ivanpe@chromium.org>
This commit is contained in:
Nelson Billing
2020-07-22 14:44:06 -07:00
parent 428a01e8de
commit 114336881a
15 changed files with 1229 additions and 154 deletions

View File

@@ -27,35 +27,39 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// HTTPMultipartUpload: A multipart/form-data HTTP uploader.
// Each parameter pair is sent as a boundary
// Each file is sent with a name field in addition to the filename and data
// The data will be sent synchronously.
#import <Foundation/Foundation.h>
@interface HTTPMultipartUpload : NSObject {
#import "HTTPRequest.h"
/**
Represents a multipart/form-data HTTP upload (POST request).
Each parameter pair is sent as a boundary.
Each file is sent with a name field in addition to the filename and data.
*/
@interface HTTPMultipartUpload : HTTPRequest {
@protected
NSURL *url_; // The destination URL (STRONG)
NSDictionary *parameters_; // The key/value pairs 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)
}
- (id)initWithURL:(NSURL *)url;
- (NSURL *)URL;
/**
Sets the parameters that will be sent in the multipart POST request.
*/
- (void)setParameters:(NSDictionary *)parameters;
- (NSDictionary *)parameters;
/**
Adds a file to be uploaded in the multipart POST request, by its file path.
*/
- (void)addFileAtPath:(NSString *)path name:(NSString *)name;
/**
Adds a file to be uploaded in the multipart POST request, by its name and
contents.
*/
- (void)addFileContents:(NSData *)data name:(NSString *)name;
- (NSDictionary *)files;
// Set the data and return the response
- (NSData *)send:(NSError **)error;
- (NSHTTPURLResponse *)response;
@end

View File

@@ -28,67 +28,10 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import "HTTPMultipartUpload.h"
#import "GTMDefines.h"
#import "util.h"
// As -[NSString stringByAddingPercentEscapesUsingEncoding:] has been
// deprecated with iOS 9.0 / OS X 10.11 SDKs, this function re-implements it
// using -[NSString stringByAddingPercentEncodingWithAllowedCharacters:] when
// using those SDKs.
static NSString *PercentEncodeNSString(NSString *key) {
#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && defined(__IPHONE_9_0) && \
__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_9_0) || \
(defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
defined(MAC_OS_X_VERSION_10_11) && \
MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11)
return [key stringByAddingPercentEncodingWithAllowedCharacters:
[NSCharacterSet URLQueryAllowedCharacterSet]];
#else
return [key stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
#endif
}
// As -[NSURLConnection sendSynchronousRequest:returningResponse:error:] has
// been deprecated with iOS 9.0 / OS X 10.11 SDKs, this function re-implements
// it using -[NSURLSession dataTaskWithRequest:completionHandler:] which is
// available on iOS 7+.
static NSData *SendSynchronousNSURLRequest(NSURLRequest *req,
NSURLResponse **out_response,
NSError **out_error) {
#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && defined(__IPHONE_7_0) && \
__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0) || \
(defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
defined(MAC_OS_X_VERSION_10_11) && \
MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11)
__block NSData* result = nil;
__block NSError* error = nil;
__block NSURLResponse* response = nil;
dispatch_semaphore_t wait_semaphone = dispatch_semaphore_create(0);
[[[NSURLSession sharedSession]
dataTaskWithRequest:req
completionHandler:^(NSData *data,
NSURLResponse *resp,
NSError *err) {
if (out_error)
error = [err retain];
if (out_response)
response = [resp retain];
if (err == nil)
result = [data retain];
dispatch_semaphore_signal(wait_semaphone);
}] resume];
dispatch_semaphore_wait(wait_semaphone, DISPATCH_TIME_FOREVER);
dispatch_release(wait_semaphone);
if (out_error)
*out_error = [error autorelease];
if (out_response)
*out_response = [response autorelease];
return [result autorelease];
#else
return [NSURLConnection sendSynchronousRequest:req
returningResponse:out_response
error:out_error];
#endif
}
@interface HTTPMultipartUpload(PrivateMethods)
- (NSString *)multipartBoundary;
// Each of the following methods will append the starting multipart boundary,
@@ -111,33 +54,24 @@ static NSData *SendSynchronousNSURLRequest(NSURLRequest *req,
//=============================================================================
- (NSData *)formDataForKey:(NSString *)key value:(NSString *)value {
NSMutableData* data = [NSMutableData data];
[self appendBoundaryData:data];
NSString *escaped = PercentEncodeNSString(key);
NSString *fmt =
@"--%@\r\nContent-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n";
@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n";
NSString *form = [NSString stringWithFormat:fmt, boundary_, escaped, value];
return [form dataUsingEncoding:NSUTF8StringEncoding];
}
//=============================================================================
- (NSData *)formDataForFileContents:(NSData *)contents name:(NSString *)name {
NSMutableData *data = [NSMutableData data];
NSString *escaped = PercentEncodeNSString(name);
NSString *fmt = @"--%@\r\nContent-Disposition: form-data; name=\"%@\"; "
"filename=\"minidump.dmp\"\r\nContent-Type: application/octet-stream\r\n\r\n";
NSString *pre = [NSString stringWithFormat:fmt, boundary_, escaped];
[data appendData:[pre dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:contents];
[data appendData:[form dataUsingEncoding:NSUTF8StringEncoding]];
return data;
}
//=============================================================================
- (NSData *)formDataForFile:(NSString *)file name:(NSString *)name {
NSData *contents = [NSData dataWithContentsOfFile:file];
- (void)appendBoundaryData: (NSMutableData*)data {
NSString *fmt = @"--%@\r\n";
NSString *pre = [NSString stringWithFormat:fmt, boundary_];
return [self formDataForFileContents:contents name:name];
[data appendData:[pre dataUsingEncoding:NSUTF8StringEncoding]];
}
//=============================================================================
@@ -145,8 +79,7 @@ static NSData *SendSynchronousNSURLRequest(NSURLRequest *req,
#pragma mark || Public ||
//=============================================================================
- (id)initWithURL:(NSURL *)url {
if ((self = [super init])) {
url_ = [url copy];
if ((self = [super initWithURL:url])) {
boundary_ = [[self multipartBoundary] retain];
files_ = [[NSMutableDictionary alloc] init];
}
@@ -156,20 +89,13 @@ static NSData *SendSynchronousNSURLRequest(NSURLRequest *req,
//=============================================================================
- (void)dealloc {
[url_ release];
[parameters_ release];
[files_ release];
[boundary_ release];
[response_ release];
[super dealloc];
}
//=============================================================================
- (NSURL *)URL {
return url_;
}
//=============================================================================
- (void)setParameters:(NSDictionary *)parameters {
if (parameters != parameters_) {
@@ -199,17 +125,20 @@ static NSData *SendSynchronousNSURLRequest(NSURLRequest *req,
}
//=============================================================================
- (NSData *)send:(NSError **)error {
NSMutableURLRequest *req =
[[NSMutableURLRequest alloc]
initWithURL:url_ cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
- (NSString*)HTTPMethod {
return @"POST";
}
//=============================================================================
- (NSString*)contentType {
return [NSString stringWithFormat:@"multipart/form-data; boundary=%@",
boundary_];
}
//=============================================================================
- (NSData*)bodyData {
NSMutableData *postBody = [NSMutableData data];
[req setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",
boundary_] forHTTPHeaderField:@"Content-type"];
// Add any parameters to the message
NSArray *parameterKeys = [parameters_ allKeys];
NSString *key;
@@ -224,44 +153,19 @@ static NSData *SendSynchronousNSURLRequest(NSURLRequest *req,
// Add any files to the message
NSArray *fileNames = [files_ allKeys];
for (NSString *name in fileNames) {
// First append boundary
[self appendBoundaryData:postBody];
// Then the formdata
id fileOrData = [files_ objectForKey:name];
NSData *fileData;
// The object can be either the path to a file (NSString) or the contents
// of the file (NSData).
if ([fileOrData isKindOfClass:[NSData class]])
fileData = [self formDataForFileContents:fileOrData name:name];
else
fileData = [self formDataForFile:fileOrData name:name];
[postBody appendData:fileData];
[HTTPRequest appendFileToBodyData:postBody
withName:name
withFileOrData:fileOrData];
}
NSString *epilogue = [NSString stringWithFormat:@"\r\n--%@--\r\n", boundary_];
[postBody appendData:[epilogue dataUsingEncoding:NSUTF8StringEncoding]];
[req setHTTPBody:postBody];
[req setHTTPMethod:@"POST"];
[response_ release];
response_ = nil;
NSData *data = nil;
if ([[req URL] isFileURL]) {
[[req HTTPBody] writeToURL:[req URL] options:0 error:error];
} else {
NSURLResponse *response = nil;
data = SendSynchronousNSURLRequest(req, &response, error);
response_ = (NSHTTPURLResponse *)[response retain];
}
[req release];
return data;
}
//=============================================================================
- (NSHTTPURLResponse *)response {
return response_;
return postBody;
}
@end