blob: 5926d2ad2c80119b55fb8b07679e780b2bc61bcb [file] [log] [blame]
// Copyright (c) 2020, 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)checkSymbolStatusOnServer:(NSString*)APIURL
withAPIKey:(NSString*)APIKey
withDebugFile:(NSString*)debugFile
withDebugID:(NSString*)debugID {
// Note that forward-slash is listed as a character to escape here, for
// completeness, however it is illegal in a debugFile input.
NSMutableCharacterSet* allowedDebugFileCharacters = [NSMutableCharacterSet
characterSetWithCharactersInString:@" \"\\/#%:?@|^`{}<>[]&=;"];
[allowedDebugFileCharacters
formUnionWithCharacterSet:[NSCharacterSet controlCharacterSet]];
[allowedDebugFileCharacters invert];
NSString* escapedDebugFile =
[debugFile stringByAddingPercentEncodingWithAllowedCharacters:
allowedDebugFileCharacters];
NSURL* URL = [NSURL
URLWithString:[NSString
stringWithFormat:@"%@/v1/symbols/%@/%@:checkStatus"
@"?key=%@",
APIURL, escapedDebugFile, 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*)createUploadURLOnServer:(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)completeUploadOnServer:(NSString*)APIURL
withAPIKey:(NSString*)APIKey
withUploadKey:(NSString*)uploadKey
withDebugFile:(NSString*)debugFile
withDebugID:(NSString*)debugID
withType:(NSString*)type {
NSURL* URL = [NSURL
URLWithString:[NSString
stringWithFormat:@"%@/v1/uploads/%@:complete?key=%@",
APIURL, uploadKey, APIKey]];
NSDictionary* symbolIdDictionary =
[NSDictionary dictionaryWithObjectsAndKeys:debugFile, @"debug_file",
debugID, @"debug_id", nil];
NSDictionary* jsonDictionary = [NSDictionary
dictionaryWithObjectsAndKeys:symbolIdDictionary, @"symbol_id", type,
@"symbol_upload_type", nil];
NSError* error = nil;
NSData* jsonData =
[NSJSONSerialization dataWithJSONObject:jsonDictionary
options:NSJSONWritingPrettyPrinted
error:&error];
if (jsonData == nil) {
fprintf(stdout, "Error: %s\n", [[error localizedDescription] UTF8String]);
fprintf(stdout,
"Failed to complete upload. Could not write JSON payload.\n");
return CompleteUploadResultError;
}
NSString* body = [[NSString alloc] initWithData:jsonData
encoding:NSUTF8StringEncoding];
HTTPSimplePostRequest* postRequest =
[[HTTPSimplePostRequest alloc] initWithURL:URL];
[postRequest setBody:body];
[postRequest setContentType:@"application/json"];
NSData* data = [postRequest send:&error];
if (data == nil) {
fprintf(stdout, "Error: %s\n", [[error localizedDescription] UTF8String]);
fprintf(stdout, "Failed to complete upload URL.\n");
return CompleteUploadResultError;
}
NSString* result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
int responseCode = [[postRequest response] statusCode];
[postRequest release];
if (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 CompleteUploadResultError;
}
NSString* completeResult =
[result substringWithRange:[completeResultMatches[0] rangeAtIndex:1]];
[result release];
return ([completeResult isEqualToString:@"DUPLICATE_DATA"])
? CompleteUploadResultDuplicateData
: CompleteUploadResultOk;
}
@end