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:
parent
428a01e8de
commit
114336881a
15 changed files with 1229 additions and 154 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
42
src/tools/mac/symupload/HTTPGetRequest.h
Normal file
42
src/tools/mac/symupload/HTTPGetRequest.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) 2019, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "HTTPRequest.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Represents a HTTP GET request
|
||||
*/
|
||||
@interface HTTPGetRequest : HTTPRequest
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
39
src/tools/mac/symupload/HTTPGetRequest.m
Normal file
39
src/tools/mac/symupload/HTTPGetRequest.m
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Copyright (c) 2019, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#import "HTTPGetRequest.h"
|
||||
|
||||
@implementation HTTPGetRequest
|
||||
|
||||
//=============================================================================
|
||||
- (NSString*)HTTPMethod {
|
||||
return @"GET";
|
||||
}
|
||||
|
||||
@end
|
51
src/tools/mac/symupload/HTTPPutRequest.h
Normal file
51
src/tools/mac/symupload/HTTPPutRequest.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
// Copyright (c) 2019, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "HTTPRequest.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Represents an HTTP PUT request.
|
||||
*/
|
||||
@interface HTTPPutRequest : HTTPRequest {
|
||||
@protected
|
||||
NSString* file_;
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the path of the file that will be sent in the PUT request.
|
||||
*/
|
||||
- (void)setFile:(NSString*)file;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
62
src/tools/mac/symupload/HTTPPutRequest.m
Normal file
62
src/tools/mac/symupload/HTTPPutRequest.m
Normal file
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) 2019, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#import "HTTPPutRequest.h"
|
||||
|
||||
@implementation HTTPPutRequest
|
||||
|
||||
//=============================================================================
|
||||
- (void)dealloc {
|
||||
[file_ release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (void)setFile:(NSString *)file {
|
||||
file_ = [file copy];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (NSString*)HTTPMethod {
|
||||
return @"PUT";
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (NSData*)bodyData {
|
||||
NSMutableData *postBody = [NSMutableData data];
|
||||
|
||||
[HTTPRequest appendFileToBodyData:postBody
|
||||
withName:@"symbol_file"
|
||||
withFileOrData:file_];
|
||||
|
||||
return postBody;
|
||||
}
|
||||
|
||||
@end
|
73
src/tools/mac/symupload/HTTPRequest.h
Normal file
73
src/tools/mac/symupload/HTTPRequest.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
// Copyright (c) 2019, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
/**
|
||||
Represents a single HTTP request. Sending the request is synchronous.
|
||||
Once the send is complete, the response will be set.
|
||||
|
||||
This is a base interface that specific HTTP requests derive from.
|
||||
It is not intended to be instantiated directly.
|
||||
*/
|
||||
@interface HTTPRequest : NSObject {
|
||||
@protected
|
||||
NSURL *URL_; // The destination URL (STRONG)
|
||||
NSHTTPURLResponse *response_; // The response from the send (STRONG)
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes the HTTPRequest and sets its URL.
|
||||
*/
|
||||
- (id)initWithURL:(NSURL *)URL;
|
||||
|
||||
- (NSURL *)URL;
|
||||
|
||||
- (NSHTTPURLResponse*) response;
|
||||
|
||||
- (NSString*)HTTPMethod; // Internal, don't call outside class hierarchy.
|
||||
|
||||
- (NSString*)contentType; // Internal, don't call outside class hierarchy.
|
||||
|
||||
- (NSData*)bodyData; // Internal, don't call outside class hierarchy.
|
||||
|
||||
- (NSData *)send:(NSError **)error;
|
||||
|
||||
/**
|
||||
Appends a file to the HTTP request, either by filename or by file content
|
||||
(in the form of NSData).
|
||||
*/
|
||||
+ (void)appendFileToBodyData:(NSMutableData *)data
|
||||
withName:(NSString*)name
|
||||
withFileOrData:(id)fileOrData;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
214
src/tools/mac/symupload/HTTPRequest.m
Normal file
214
src/tools/mac/symupload/HTTPRequest.m
Normal file
|
@ -0,0 +1,214 @@
|
|||
// Copyright (c) 2019, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#import "HTTPRequest.h"
|
||||
|
||||
#import "util.h"
|
||||
|
||||
// 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 **outResponse,
|
||||
NSError **outError) {
|
||||
#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 waitSemaphone = dispatch_semaphore_create(0);
|
||||
NSURLSessionConfiguration* config = [NSURLSessionConfiguration
|
||||
defaultSessionConfiguration];
|
||||
[config setTimeoutIntervalForRequest:240.0];
|
||||
NSURLSession* session = [NSURLSession sessionWithConfiguration:config];
|
||||
[[session
|
||||
dataTaskWithRequest:req
|
||||
completionHandler:^(NSData *data,
|
||||
NSURLResponse *resp,
|
||||
NSError *err) {
|
||||
if (outError)
|
||||
error = [err retain];
|
||||
if (outResponse)
|
||||
response = [resp retain];
|
||||
if (err == nil)
|
||||
result = [data retain];
|
||||
dispatch_semaphore_signal(waitSemaphone);
|
||||
}] resume];
|
||||
dispatch_semaphore_wait(waitSemaphone, DISPATCH_TIME_FOREVER);
|
||||
dispatch_release(waitSemaphone);
|
||||
if (outError)
|
||||
*outError = [error autorelease];
|
||||
if (outResponse)
|
||||
*outResponse = [response autorelease];
|
||||
return [result autorelease];
|
||||
#else
|
||||
return [NSURLConnection sendSynchronousRequest:req
|
||||
returningResponse:outResponse
|
||||
error:outError];
|
||||
#endif
|
||||
}
|
||||
|
||||
@implementation HTTPRequest
|
||||
|
||||
//=============================================================================
|
||||
- (id)initWithURL:(NSURL *)URL {
|
||||
if ((self = [super init])) {
|
||||
URL_ = [URL copy];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (void)dealloc {
|
||||
[URL_ release];
|
||||
[response_ release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (NSURL *)URL {
|
||||
return URL_;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (NSHTTPURLResponse *)response {
|
||||
return response_;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (NSString*)HTTPMethod {
|
||||
@throw [NSException exceptionWithName:NSInternalInconsistencyException
|
||||
reason:[NSString stringWithFormat:@"You must"
|
||||
"override %@ in a subclass",
|
||||
NSStringFromSelector(_cmd)]
|
||||
userInfo:nil];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (NSString*)contentType {
|
||||
return nil;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (NSData*)bodyData {
|
||||
return nil;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (NSData *)send:(NSError **)withError {
|
||||
NSMutableURLRequest *req =
|
||||
[[NSMutableURLRequest alloc]
|
||||
initWithURL:URL_
|
||||
cachePolicy:NSURLRequestUseProtocolCachePolicy
|
||||
timeoutInterval:60.0];
|
||||
|
||||
NSString* contentType = [self contentType];
|
||||
if ([contentType length] > 0) {
|
||||
[req setValue:contentType forHTTPHeaderField:@"Content-type"];
|
||||
}
|
||||
|
||||
NSData* bodyData = [self bodyData];
|
||||
if ([bodyData length] > 0) {
|
||||
[req setHTTPBody:bodyData];
|
||||
}
|
||||
|
||||
[req setHTTPMethod:[self HTTPMethod]];
|
||||
|
||||
[response_ release];
|
||||
response_ = nil;
|
||||
|
||||
NSData *data = nil;
|
||||
if ([[req URL] isFileURL]) {
|
||||
[[req HTTPBody] writeToURL:[req URL] options:0 error:withError];
|
||||
} else {
|
||||
NSURLResponse *response = nil;
|
||||
data = SendSynchronousNSURLRequest(req, &response, withError);
|
||||
response_ = (NSHTTPURLResponse *)[response retain];
|
||||
}
|
||||
[req release];
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
+ (NSData *)formDataForFileContents:(NSData *)contents
|
||||
withName:(NSString *)name {
|
||||
NSMutableData *data = [NSMutableData data];
|
||||
NSString *escaped = PercentEncodeNSString(name);
|
||||
NSString *fmt = @"Content-Disposition: form-data; name=\"%@\"; "
|
||||
"filename=\"minidump.dmp\"\r\nContent-Type: "
|
||||
"application/octet-stream\r\n\r\n";
|
||||
NSString *pre = [NSString stringWithFormat:fmt, escaped];
|
||||
|
||||
[data appendData:[pre dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[data appendData:contents];
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
+ (NSData *)formDataForFile:(NSString *)file withName:(NSString *)name {
|
||||
NSData *contents = [NSData dataWithContentsOfFile:file];
|
||||
|
||||
return [HTTPRequest formDataForFileContents:contents withName:name];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
+ (NSData *)formDataForKey:(NSString *)key value:(NSString *)value {
|
||||
NSString *escaped = PercentEncodeNSString(key);
|
||||
NSString *fmt =
|
||||
@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n";
|
||||
NSString *form = [NSString stringWithFormat:fmt, escaped, value];
|
||||
|
||||
return [form dataUsingEncoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
+ (void)appendFileToBodyData:(NSMutableData *)data
|
||||
withName:(NSString*)name
|
||||
withFileOrData:(id)fileOrData {
|
||||
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 withName:name];
|
||||
else
|
||||
fileData = [HTTPRequest formDataForFile:fileOrData withName:name];
|
||||
|
||||
[data appendData:fileData];
|
||||
}
|
||||
|
||||
@end
|
57
src/tools/mac/symupload/HTTPSimplePostRequest.h
Normal file
57
src/tools/mac/symupload/HTTPSimplePostRequest.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Copyright (c) 2019, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "HTTPRequest.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Represents a simple (non-multipart) HTTP POST request.
|
||||
*/
|
||||
@interface HTTPSimplePostRequest : HTTPRequest {
|
||||
@protected
|
||||
NSString* contentType_;
|
||||
NSString* body_;
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the content type of the POST request.
|
||||
*/
|
||||
- (void)setContentType:(NSString*)contentType;
|
||||
|
||||
/**
|
||||
Sets the contents of the POST request's body.
|
||||
*/
|
||||
- (void)setBody:(NSString*)body;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
69
src/tools/mac/symupload/HTTPSimplePostRequest.m
Normal file
69
src/tools/mac/symupload/HTTPSimplePostRequest.m
Normal file
|
@ -0,0 +1,69 @@
|
|||
// Copyright (c) 2019, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#import "HTTPSimplePostRequest.h"
|
||||
|
||||
@implementation HTTPSimplePostRequest
|
||||
|
||||
//=============================================================================
|
||||
- (void)dealloc {
|
||||
[contentType_ release];
|
||||
[body_ release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (void)setContentType:(NSString *)contentType {
|
||||
contentType_ = [contentType copy];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (void)setBody:(NSString *)body {
|
||||
body_ = [body copy];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (NSString*)HTTPMethod {
|
||||
return @"POST";
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (NSString*)contentType {
|
||||
return contentType_;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (NSData*)bodyData {
|
||||
NSMutableData* data = [NSMutableData data];
|
||||
[data appendData:[body_ dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
return data;
|
||||
}
|
||||
|
||||
@end
|
100
src/tools/mac/symupload/SymbolCollectorClient.h
Normal file
100
src/tools/mac/symupload/SymbolCollectorClient.h
Normal file
|
@ -0,0 +1,100 @@
|
|||
// Copyright (c) 2019, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Represents a response from a sym-upload-v2 server to a CreateUploadURL call.
|
||||
*/
|
||||
@interface UploadURLResponse : NSObject {
|
||||
@protected
|
||||
NSString* uploadURL_;
|
||||
NSString* uploadKey_;
|
||||
}
|
||||
|
||||
- (id)initWithUploadURL:(NSString*)uploadURL
|
||||
withUploadKey:(NSString*)uploadKey;
|
||||
|
||||
- (NSString*)uploadURL;
|
||||
- (NSString*)uploadKey;
|
||||
@end
|
||||
|
||||
/**
|
||||
Possible return statuses from a sym-upload-v2 server to a CompleteUpload call.
|
||||
*/
|
||||
typedef NS_ENUM(NSInteger, CompleteUploadResult) {
|
||||
CompleteUploadResultOk,
|
||||
CompleteUploadResultDuplicateData,
|
||||
CompleteUploadResultError
|
||||
};
|
||||
|
||||
/**
|
||||
Possible return statuses from a sym-upload-v2 server to a CheckSymbolStatus
|
||||
call.
|
||||
*/
|
||||
typedef NS_ENUM(NSInteger, SymbolStatus) {
|
||||
SymbolStatusFound,
|
||||
SymbolStatusMissing,
|
||||
SymbolStatusUnknown
|
||||
};
|
||||
|
||||
/**
|
||||
Interface to help a client interact with a sym-upload-v2 server, over HTTP.
|
||||
For details of the API and protocol, see :/docs/sym_upload_v2_protocol.md.
|
||||
*/
|
||||
@interface SymbolCollectorClient : NSObject;
|
||||
|
||||
/**
|
||||
Call the CheckSymbolstatus API on the server.
|
||||
*/
|
||||
+ (SymbolStatus)CheckSymbolStatus:(NSString*)APIURL
|
||||
withAPIKey:(NSString*)APIKey
|
||||
withDebugFile:(NSString*)debugFile
|
||||
withDebugID:(NSString*)debugID;
|
||||
|
||||
/**
|
||||
Call the CreateUploadURL API on the server.
|
||||
*/
|
||||
+ (UploadURLResponse*)CreateUploadURL:(NSString*)APIURL
|
||||
withAPIKey:(NSString*)APIKey;
|
||||
|
||||
/**
|
||||
Call the CompleteUpload API on the server.
|
||||
*/
|
||||
+ (CompleteUploadResult)CompleteUpload:(NSString*)APIURL
|
||||
withAPIKey:(NSString*)APIKey
|
||||
withUploadKey:(NSString*)uploadKey
|
||||
withDebugFile:(NSString*)debugFile
|
||||
withDebugID:(NSString*)debugID;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
247
src/tools/mac/symupload/SymbolCollectorClient.m
Normal file
247
src/tools/mac/symupload/SymbolCollectorClient.m
Normal file
|
@ -0,0 +1,247 @@
|
|||
// Copyright (c) 2019, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#import "SymbolCollectorClient.h"
|
||||
|
||||
#import "HTTPGetRequest.h"
|
||||
#import "HTTPSimplePostRequest.h"
|
||||
|
||||
@implementation UploadURLResponse
|
||||
|
||||
//=============================================================================
|
||||
- (id)initWithUploadURL:(NSString *)uploadURL
|
||||
withUploadKey:(NSString *)uploadKey {
|
||||
if (self = [super init]) {
|
||||
uploadURL_ = [uploadURL copy];
|
||||
uploadKey_ = [uploadKey copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (void)dealloc {
|
||||
[uploadURL_ release];
|
||||
[uploadKey_ release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (NSString*)uploadURL {
|
||||
return uploadURL_;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
- (NSString*)uploadKey {
|
||||
return uploadKey_;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation SymbolCollectorClient
|
||||
|
||||
//=============================================================================
|
||||
+ (SymbolStatus)CheckSymbolStatus:(NSString *)APIURL
|
||||
withAPIKey:(NSString *)APIKey
|
||||
withDebugFile:(NSString *)debugFile
|
||||
withDebugID:(NSString *)debugID {
|
||||
NSURL* URL = [NSURL URLWithString:[NSString stringWithFormat:
|
||||
@"%@/v1/symbols/%@/%@:checkStatus"
|
||||
@"?key=%@",
|
||||
APIURL,
|
||||
debugFile,
|
||||
debugID,
|
||||
APIKey]];
|
||||
|
||||
HTTPGetRequest* getRequest = [[HTTPGetRequest alloc] initWithURL:URL];
|
||||
NSError *error = nil;
|
||||
NSData *data = [getRequest send:&error];
|
||||
NSString *result = [[NSString alloc] initWithData:data
|
||||
encoding:NSUTF8StringEncoding];
|
||||
int responseCode = [[getRequest response] statusCode];
|
||||
[getRequest release];
|
||||
|
||||
if (error || responseCode != 200) {
|
||||
fprintf(stdout, "Failed to check symbol status.\n");
|
||||
fprintf(stdout, "Response code: %d\n", responseCode);
|
||||
fprintf(stdout, "Response:\n");
|
||||
fprintf(stdout, "%s\n", [result UTF8String]);
|
||||
return SymbolStatusUnknown;
|
||||
}
|
||||
|
||||
error = nil;
|
||||
NSRegularExpression* statusRegex = [NSRegularExpression
|
||||
regularExpressionWithPattern:
|
||||
@"\"status\": \"([^\"]+)\""
|
||||
options:0
|
||||
error:&error];
|
||||
NSArray* matches = [statusRegex
|
||||
matchesInString:result
|
||||
options:0
|
||||
range: NSMakeRange(0, [result length])];
|
||||
if ([matches count] != 1) {
|
||||
fprintf(stdout, "Failed to parse check symbol status response.");
|
||||
fprintf(stdout, "Response:\n");
|
||||
fprintf(stdout, "%s\n", [result UTF8String]);
|
||||
return SymbolStatusUnknown;
|
||||
}
|
||||
|
||||
NSString* status = [result substringWithRange:[matches[0] rangeAtIndex:1]];
|
||||
[result release];
|
||||
|
||||
return [status isEqualToString:@"FOUND"] ?
|
||||
SymbolStatusFound :
|
||||
SymbolStatusMissing;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
+ (UploadURLResponse *)CreateUploadURL:(NSString *)APIURL
|
||||
withAPIKey:(NSString *)APIKey {
|
||||
NSURL* URL = [NSURL URLWithString:[NSString stringWithFormat:
|
||||
@"%@/v1/uploads:create?key=%@",
|
||||
APIURL,
|
||||
APIKey]];
|
||||
|
||||
HTTPSimplePostRequest* postRequest = [[HTTPSimplePostRequest alloc]
|
||||
initWithURL:URL];
|
||||
NSError *error = nil;
|
||||
NSData* data = [postRequest send:&error];
|
||||
NSString *result = [[NSString alloc] initWithData:data
|
||||
encoding:NSUTF8StringEncoding];
|
||||
int responseCode = [[postRequest response] statusCode];
|
||||
[postRequest release];
|
||||
|
||||
if (error || responseCode != 200) {
|
||||
fprintf(stdout, "Failed to create upload URL.\n");
|
||||
fprintf(stdout, "Response code: %d\n", responseCode);
|
||||
fprintf(stdout, "Response:\n");
|
||||
fprintf(stdout, "%s\n", [result UTF8String]);
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Note camel-case rather than underscores.
|
||||
NSRegularExpression* uploadURLRegex = [NSRegularExpression
|
||||
regularExpressionWithPattern:
|
||||
@"\"uploadUrl\": \"([^\"]+)\""
|
||||
options:0
|
||||
error:&error];
|
||||
NSRegularExpression* uploadKeyRegex = [NSRegularExpression
|
||||
regularExpressionWithPattern:
|
||||
@"\"uploadKey\": \"([^\"]+)\""
|
||||
options:0
|
||||
error:&error];
|
||||
|
||||
NSArray* uploadURLMatches = [uploadURLRegex
|
||||
matchesInString:result
|
||||
options:0
|
||||
range: NSMakeRange(0, [result length])];
|
||||
NSArray* uploadKeyMatches = [uploadKeyRegex
|
||||
matchesInString:result
|
||||
options:0
|
||||
range: NSMakeRange(0, [result length])];
|
||||
if ([uploadURLMatches count] != 1 || [uploadKeyMatches count] != 1) {
|
||||
fprintf(stdout, "Failed to parse create url response.");
|
||||
fprintf(stdout, "Response:\n");
|
||||
fprintf(stdout, "%s\n", [result UTF8String]);
|
||||
return nil;
|
||||
}
|
||||
NSString* uploadURL = [result
|
||||
substringWithRange:[uploadURLMatches[0]
|
||||
rangeAtIndex:1]];
|
||||
NSString* uploadKey = [result
|
||||
substringWithRange:[uploadKeyMatches[0]
|
||||
rangeAtIndex:1]];
|
||||
|
||||
return [[UploadURLResponse alloc] initWithUploadURL:uploadURL
|
||||
withUploadKey:uploadKey];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
+ (CompleteUploadResult)CompleteUpload:(NSString *)APIURL
|
||||
withAPIKey:(NSString *)APIKey
|
||||
withUploadKey:(NSString *)uploadKey
|
||||
withDebugFile:(NSString *)debugFile
|
||||
withDebugID:(NSString *)debugID {
|
||||
NSURL* URL = [NSURL URLWithString:[NSString stringWithFormat:
|
||||
@"%@/v1/uploads/%@:complete?key=%@",
|
||||
APIURL,
|
||||
uploadKey,
|
||||
APIKey]];
|
||||
NSString* body = [NSString stringWithFormat:
|
||||
@"{ symbol_id: { debug_file: \"%@\", debug_id: \"%@\" } }",
|
||||
debugFile,
|
||||
debugID];
|
||||
|
||||
HTTPSimplePostRequest* postRequest = [[HTTPSimplePostRequest alloc]
|
||||
initWithURL:URL];
|
||||
[postRequest setBody:body];
|
||||
[postRequest setContentType:@"application/json"];
|
||||
|
||||
NSError *error = nil;
|
||||
NSData* data = [postRequest send:&error];
|
||||
NSString *result = [[NSString alloc] initWithData:data
|
||||
encoding:NSUTF8StringEncoding];
|
||||
int responseCode = [[postRequest response] statusCode];
|
||||
[postRequest release];
|
||||
|
||||
if (error || responseCode != 200) {
|
||||
fprintf(stdout, "Failed to complete upload URL.\n");
|
||||
fprintf(stdout, "Response code: %d\n", responseCode);
|
||||
fprintf(stdout, "Response:\n");
|
||||
fprintf(stdout, "%s\n", [result UTF8String]);
|
||||
return CompleteUploadResultError;
|
||||
}
|
||||
|
||||
// Note camel-case rather than underscores.
|
||||
NSRegularExpression* completeResultRegex = [NSRegularExpression
|
||||
regularExpressionWithPattern:
|
||||
@"\"result\": \"([^\"]+)\""
|
||||
options:0
|
||||
error:&error];
|
||||
|
||||
NSArray* completeResultMatches = [completeResultRegex
|
||||
matchesInString:result
|
||||
options:0
|
||||
range: NSMakeRange(0, [result length])];
|
||||
|
||||
if ([completeResultMatches count] != 1) {
|
||||
fprintf(stdout, "Failed to parse complete upload response.");
|
||||
fprintf(stdout, "Response:\n");
|
||||
fprintf(stdout, "%s\n", [result UTF8String]);
|
||||
return nil;
|
||||
}
|
||||
NSString* completeResult = [result
|
||||
substringWithRange:[completeResultMatches[0]
|
||||
rangeAtIndex:1]];
|
||||
[result release];
|
||||
|
||||
return ([completeResult isEqualToString:@"DUPLICATE_DATA"]) ?
|
||||
CompleteUploadResultDuplicateData :
|
||||
CompleteUploadResultOk;
|
||||
}
|
||||
@end
|
|
@ -43,11 +43,22 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
#include "HTTPMultipartUpload.h"
|
||||
#include "HTTPPutRequest.h"
|
||||
#include "SymbolCollectorClient.h"
|
||||
|
||||
typedef enum {
|
||||
SymUploadProtocolV1,
|
||||
SymUploadProtocolV2
|
||||
} SymUploadProtocol;
|
||||
|
||||
typedef struct {
|
||||
NSString *symbolsPath;
|
||||
NSString *uploadURLStr;
|
||||
SymUploadProtocol symUploadProtocol;
|
||||
NSString* apiKey;
|
||||
BOOL force;
|
||||
BOOL success;
|
||||
} Options;
|
||||
|
||||
|
@ -84,15 +95,12 @@ static NSArray *ModuleDataForSymbolFile(NSString *file) {
|
|||
}
|
||||
|
||||
//=============================================================================
|
||||
static void Start(Options *options) {
|
||||
static void StartSymUploadProtocolV1(Options* options,
|
||||
NSArray* moduleParts,
|
||||
NSString* compactedID) {
|
||||
NSURL *url = [NSURL URLWithString:options->uploadURLStr];
|
||||
HTTPMultipartUpload *ul = [[HTTPMultipartUpload alloc] initWithURL:url];
|
||||
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
|
||||
NSArray *moduleParts = ModuleDataForSymbolFile(options->symbolsPath);
|
||||
NSMutableString *compactedID =
|
||||
[NSMutableString stringWithString:[moduleParts objectAtIndex:3]];
|
||||
[compactedID replaceOccurrencesOfString:@"-" withString:@"" options:0
|
||||
range:NSMakeRange(0, [compactedID length])];
|
||||
|
||||
// Add parameters
|
||||
[parameters setObject:compactedID forKey:@"debug_identifier"];
|
||||
|
@ -135,13 +143,106 @@ static void Start(Options *options) {
|
|||
options->success = !error && status==200;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
static void StartSymUploadProtocolV2(Options* options,
|
||||
NSString* debugFile,
|
||||
NSString* debugID) {
|
||||
if (!options->force) {
|
||||
SymbolStatus symbolStatus = [SymbolCollectorClient
|
||||
CheckSymbolStatus:options->uploadURLStr
|
||||
withAPIKey:options->apiKey
|
||||
withDebugFile:debugFile
|
||||
withDebugID:debugID];
|
||||
if (symbolStatus == SymbolStatusFound) {
|
||||
fprintf(stdout, "Symbol file already exists, upload aborted."
|
||||
" Use \"-f\" to overwrite.\n");
|
||||
options->success = YES;
|
||||
return;
|
||||
} else if (symbolStatus == SymbolStatusUnknown) {
|
||||
fprintf(stdout, "Failed to get check for existing symbol.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
UploadURLResponse* URLResponse = [SymbolCollectorClient
|
||||
CreateUploadURL:options->uploadURLStr
|
||||
withAPIKey:options->apiKey];
|
||||
if (URLResponse == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSURL* uploadURL = [NSURL URLWithString:[URLResponse uploadURL]];
|
||||
HTTPPutRequest* putRequest = [[HTTPPutRequest alloc]
|
||||
initWithURL:uploadURL];
|
||||
[putRequest setFile:options->symbolsPath];
|
||||
|
||||
NSError *error = nil;
|
||||
NSData* data = [putRequest send:&error];
|
||||
NSString *result = [[NSString alloc] initWithData:data
|
||||
encoding:NSUTF8StringEncoding];
|
||||
int responseCode = [[putRequest response] statusCode];
|
||||
[putRequest release];
|
||||
|
||||
if (error || responseCode != 200) {
|
||||
fprintf(stdout, "Failed to upload symbol file.\n");
|
||||
fprintf(stdout, "Response code: %d\n", responseCode);
|
||||
fprintf(stdout, "Response:\n");
|
||||
fprintf(stdout, "%s\n", [result UTF8String]);
|
||||
return;
|
||||
}
|
||||
|
||||
CompleteUploadResult completeUploadResult = [SymbolCollectorClient
|
||||
CompleteUpload:options->uploadURLStr
|
||||
withAPIKey:options->apiKey
|
||||
withUploadKey:[URLResponse uploadKey]
|
||||
withDebugFile:debugFile
|
||||
withDebugID:debugID];
|
||||
[URLResponse release];
|
||||
if (completeUploadResult == CompleteUploadResultError) {
|
||||
fprintf(stdout, "Failed to complete upload.\n");
|
||||
return;
|
||||
} else if (completeUploadResult == CompleteUploadResultDuplicateData) {
|
||||
fprintf(stdout, "Uploaded file checksum matched existing file checksum,"
|
||||
" no change necessary.\n");
|
||||
} else {
|
||||
fprintf(stdout, "Successfully sent the symbol file.\n");
|
||||
}
|
||||
options->success = YES;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
static void Start(Options *options) {
|
||||
NSArray *moduleParts = ModuleDataForSymbolFile(options->symbolsPath);
|
||||
NSMutableString *compactedID =
|
||||
[NSMutableString stringWithString:[moduleParts objectAtIndex:3]];
|
||||
[compactedID replaceOccurrencesOfString:@"-" withString:@"" options:0
|
||||
range:NSMakeRange(0, [compactedID length])];
|
||||
|
||||
if (options->symUploadProtocol == SymUploadProtocolV1) {
|
||||
StartSymUploadProtocolV1(options, moduleParts, compactedID);
|
||||
} else if (options->symUploadProtocol == SymUploadProtocolV2) {
|
||||
StartSymUploadProtocolV2(options,
|
||||
[moduleParts objectAtIndex:4],
|
||||
compactedID);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
static void
|
||||
Usage(int argc, const char *argv[]) {
|
||||
fprintf(stderr, "Submit symbol information.\n");
|
||||
fprintf(stderr, "Usage: %s <symbols> <upload-URL>\n", argv[0]);
|
||||
fprintf(stderr, "<symbols> should be created by using the dump_syms tool.\n");
|
||||
fprintf(stderr, "<upload-URL> is the destination for the upload\n");
|
||||
fprintf(stderr, "Usage: %s [options] <symbol-file> <upload-URL>\n", argv[0]);
|
||||
fprintf(stderr, "<symbol-file> should be created by using the dump_syms "
|
||||
"tool.\n");
|
||||
fprintf(stderr, "<upload-URL> is the destination for the upload.\n");
|
||||
fprintf(stderr, "Options:\n");
|
||||
fprintf(stderr, "\t-p <protocol>: protocol to use for upload, accepts "
|
||||
"[\"sym-upload-v1\", \"sym-upload-v2\"]. Default is "
|
||||
"\"sym-upload-v1\".\n");
|
||||
fprintf(stderr, "\t-k <api-key>: secret for authentication with upload "
|
||||
"server. [Only in sym-upload-v2 protocol mode]\n");
|
||||
fprintf(stderr, "\t-f: Overwrite symbol file on server if already present. "
|
||||
"[Only in sym-upload-v2 protocol mode]\n");
|
||||
fprintf(stderr, "\t-h: Usage\n");
|
||||
fprintf(stderr, "\t-?: Usage\n");
|
||||
}
|
||||
|
@ -149,11 +250,33 @@ Usage(int argc, const char *argv[]) {
|
|||
//=============================================================================
|
||||
static void
|
||||
SetupOptions(int argc, const char *argv[], Options *options) {
|
||||
// Set default value of symUploadProtocol.
|
||||
options->symUploadProtocol = SymUploadProtocolV1;
|
||||
|
||||
extern int optind;
|
||||
char ch;
|
||||
|
||||
while ((ch = getopt(argc, (char * const *)argv, "h?")) != -1) {
|
||||
while ((ch = getopt(argc, (char * const *)argv, "p:k:hf?")) != -1) {
|
||||
switch (ch) {
|
||||
case 'p':
|
||||
if (strcmp(optarg, "sym-upload-v2") == 0) {
|
||||
options->symUploadProtocol = SymUploadProtocolV2;
|
||||
break;
|
||||
} else if (strcmp(optarg, "sym-upload-v1") == 0) {
|
||||
// This is already the default but leave in case that changes.
|
||||
options->symUploadProtocol = SymUploadProtocolV1;
|
||||
break;
|
||||
}
|
||||
Usage(argc, argv);
|
||||
exit(0);
|
||||
break;
|
||||
case 'k':
|
||||
options->apiKey = [NSString stringWithCString:optarg
|
||||
encoding:NSASCIIStringEncoding];
|
||||
break;
|
||||
case 'f':
|
||||
options->force = YES;
|
||||
break;
|
||||
default:
|
||||
Usage(argc, argv);
|
||||
exit(0);
|
||||
|
|
|
@ -7,6 +7,11 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
5B6060BD222716FC0015F0A0 /* HTTPRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B6060BC222716FC0015F0A0 /* HTTPRequest.m */; };
|
||||
5B6060C02227201B0015F0A0 /* HTTPPutRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B6060BF2227201B0015F0A0 /* HTTPPutRequest.m */; };
|
||||
5B6060C7222735E50015F0A0 /* HTTPGetRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B6060C6222735E50015F0A0 /* HTTPGetRequest.m */; };
|
||||
5B6060CA2227374E0015F0A0 /* HTTPSimplePostRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B6060C92227374E0015F0A0 /* HTTPSimplePostRequest.m */; };
|
||||
5B6060D022273BDA0015F0A0 /* SymbolCollectorClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B6060CF22273BDA0015F0A0 /* SymbolCollectorClient.m */; };
|
||||
8B31022C11F0CEBD00FCF3E4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
|
||||
8DD76F9A0486AA7600D96B5E /* symupload.m in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* symupload.m */; settings = {ATTRIBUTES = (); }; };
|
||||
8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
|
||||
|
@ -30,14 +35,25 @@
|
|||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
08FB7796FE84155DC02AAC07 /* symupload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = symupload.m; sourceTree = "<group>"; };
|
||||
08FB7796FE84155DC02AAC07 /* symupload.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = symupload.m; sourceTree = "<group>"; tabWidth = 2; };
|
||||
08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
5B6060BB222716FC0015F0A0 /* HTTPRequest.h */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = HTTPRequest.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
5B6060BC222716FC0015F0A0 /* HTTPRequest.m */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = HTTPRequest.m; sourceTree = "<group>"; tabWidth = 2; };
|
||||
5B6060BE2227201B0015F0A0 /* HTTPPutRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTTPPutRequest.h; sourceTree = "<group>"; };
|
||||
5B6060BF2227201B0015F0A0 /* HTTPPutRequest.m */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = HTTPPutRequest.m; sourceTree = "<group>"; tabWidth = 2; };
|
||||
5B6060C22227303A0015F0A0 /* util.h */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = util.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
5B6060C5222735E50015F0A0 /* HTTPGetRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTTPGetRequest.h; sourceTree = "<group>"; };
|
||||
5B6060C6222735E50015F0A0 /* HTTPGetRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HTTPGetRequest.m; sourceTree = "<group>"; };
|
||||
5B6060C82227374E0015F0A0 /* HTTPSimplePostRequest.h */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = HTTPSimplePostRequest.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
5B6060C92227374E0015F0A0 /* HTTPSimplePostRequest.m */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = HTTPSimplePostRequest.m; sourceTree = "<group>"; tabWidth = 2; };
|
||||
5B6060CE22273BDA0015F0A0 /* SymbolCollectorClient.h */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = SymbolCollectorClient.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
5B6060CF22273BDA0015F0A0 /* SymbolCollectorClient.m */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = SymbolCollectorClient.m; sourceTree = "<group>"; tabWidth = 2; };
|
||||
8B31022B11F0CE6900FCF3E4 /* Breakpad.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Breakpad.xcconfig; path = ../../../common/mac/Breakpad.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||
8B3102B611F0D5CE00FCF3E4 /* BreakpadDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadDebug.xcconfig; path = ../../../common/mac/BreakpadDebug.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||
8B3102B711F0D5CE00FCF3E4 /* BreakpadRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadRelease.xcconfig; path = ../../../common/mac/BreakpadRelease.xcconfig; sourceTree = SOURCE_ROOT; };
|
||||
8DD76FA10486AA7600D96B5E /* symupload */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = symupload; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9BD833680B03E4080055103E /* HTTPMultipartUpload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTTPMultipartUpload.h; path = ../../../common/mac/HTTPMultipartUpload.h; sourceTree = "<group>"; };
|
||||
9BD833690B03E4080055103E /* HTTPMultipartUpload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HTTPMultipartUpload.m; path = ../../../common/mac/HTTPMultipartUpload.m; sourceTree = "<group>"; };
|
||||
9BD833680B03E4080055103E /* HTTPMultipartUpload.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = HTTPMultipartUpload.h; path = ../../../common/mac/HTTPMultipartUpload.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
9BD833690B03E4080055103E /* HTTPMultipartUpload.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; name = HTTPMultipartUpload.m; path = ../../../common/mac/HTTPMultipartUpload.m; sourceTree = "<group>"; tabWidth = 2; };
|
||||
9BD835FB0B0544950055103E /* minidump_upload */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = minidump_upload; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9BD836000B0544BA0055103E /* minidump_upload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = minidump_upload.m; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
@ -65,6 +81,17 @@
|
|||
08FB7794FE84155DC02AAC07 /* symupload */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5B6060CE22273BDA0015F0A0 /* SymbolCollectorClient.h */,
|
||||
5B6060CF22273BDA0015F0A0 /* SymbolCollectorClient.m */,
|
||||
5B6060C82227374E0015F0A0 /* HTTPSimplePostRequest.h */,
|
||||
5B6060C92227374E0015F0A0 /* HTTPSimplePostRequest.m */,
|
||||
5B6060C5222735E50015F0A0 /* HTTPGetRequest.h */,
|
||||
5B6060C6222735E50015F0A0 /* HTTPGetRequest.m */,
|
||||
5B6060C22227303A0015F0A0 /* util.h */,
|
||||
5B6060BE2227201B0015F0A0 /* HTTPPutRequest.h */,
|
||||
5B6060BF2227201B0015F0A0 /* HTTPPutRequest.m */,
|
||||
5B6060BB222716FC0015F0A0 /* HTTPRequest.h */,
|
||||
5B6060BC222716FC0015F0A0 /* HTTPRequest.m */,
|
||||
8B31022B11F0CE6900FCF3E4 /* Breakpad.xcconfig */,
|
||||
8B3102B611F0D5CE00FCF3E4 /* BreakpadDebug.xcconfig */,
|
||||
8B3102B711F0D5CE00FCF3E4 /* BreakpadRelease.xcconfig */,
|
||||
|
@ -137,9 +164,15 @@
|
|||
/* Begin PBXProject section */
|
||||
08FB7793FE84155DC02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
};
|
||||
buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "symupload" */;
|
||||
compatibilityVersion = "Xcode 3.1";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 08FB7794FE84155DC02AAC07 /* symupload */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
|
@ -156,6 +189,11 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8DD76F9A0486AA7600D96B5E /* symupload.m in Sources */,
|
||||
5B6060CA2227374E0015F0A0 /* HTTPSimplePostRequest.m in Sources */,
|
||||
5B6060D022273BDA0015F0A0 /* SymbolCollectorClient.m in Sources */,
|
||||
5B6060C7222735E50015F0A0 /* HTTPGetRequest.m in Sources */,
|
||||
5B6060C02227201B0015F0A0 /* HTTPPutRequest.m in Sources */,
|
||||
5B6060BD222716FC0015F0A0 /* HTTPRequest.m in Sources */,
|
||||
9BD8336B0B03E4080055103E /* HTTPMultipartUpload.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
52
src/tools/mac/symupload/util.h
Normal file
52
src/tools/mac/symupload/util.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
// Copyright (c) 2019, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef util_h
|
||||
#define util_h
|
||||
|
||||
#import <Foundation/Foundation.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
|
||||
}
|
||||
|
||||
#endif /* util_h */
|
Loading…
Reference in a new issue