Incomplete work to upload avatars.

// FREEBIE
pull/1/head
Matthew Chen 8 years ago
parent f6668d24c1
commit 09e65a674b

@ -10,6 +10,7 @@
#import <SignalServiceKit/OWSMessageSender.h> #import <SignalServiceKit/OWSMessageSender.h>
#import <SignalServiceKit/SecurityUtils.h> #import <SignalServiceKit/SecurityUtils.h>
#import <SignalServiceKit/TSGroupThread.h> #import <SignalServiceKit/TSGroupThread.h>
#import <SignalServiceKit/TSProfileAvatarUploadFormRequest.h>
#import <SignalServiceKit/TSSetProfileRequest.h> #import <SignalServiceKit/TSSetProfileRequest.h>
#import <SignalServiceKit/TSStorageManager.h> #import <SignalServiceKit/TSStorageManager.h>
#import <SignalServiceKit/TSThread.h> #import <SignalServiceKit/TSThread.h>
@ -414,11 +415,164 @@ static const NSInteger kProfileKeyLength = 16;
// TODO: // TODO:
NSString *avatarUrl = @"avatarUrl"; NSString *avatarUrl = @"avatarUrl";
NSData *avatarDigest = [@"avatarDigest" dataUsingEncoding:NSUTF8StringEncoding]; NSData *avatarDigest = [@"avatarDigest" dataUsingEncoding:NSUTF8StringEncoding];
if (YES) {
successBlock(avatarUrl, avatarDigest); // See: https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-UsingHTTPPOST.html
return; TSProfileAvatarUploadFormRequest *formRequest = [TSProfileAvatarUploadFormRequest new];
}
failureBlock(); [self.networkManager makeRequest:formRequest
success:^(NSURLSessionDataTask *task, id formResponseObject) {
if (![formResponseObject isKindOfClass:[NSDictionary class]]) {
OWSProdFail(@"profile_manager_error_avatar_upload_form_invalid_response");
failureBlock();
return;
}
NSDictionary *responseMap = formResponseObject;
DDLogError(@"responseObject: %@", formResponseObject);
// acl = private;
// algorithm = "AWS4-HMAC-SHA256";
// credential =
// "AKIAINTYCHN42UH3LGRA/20170804/us-east-1/s3/aws4_request"; date =
// 20170804T193927Z; key = PtRO3iSkY6twBA; policy =
// eyAiZXhwaXJhdGlvbiI6ICIyMDE3LTA4LTA0VDIwOjA5OjI3LjMwMFoiLAogICJjb25kaXRpb25zIjogWwogICAgeyJidWNrZXQiOiAic2lnbmFsLXByb2ZpbGVzLXN0YWdpbmcifSwKICAgIHsia2V5IjogIlB0Uk8zaVNrWTZ0d0JBIn0sCiAgICB7ImFjbCI6ICJwcml2YXRlIn0sCiAgICBbInN0YXJ0cy13aXRoIiwgIiRDb250ZW50LVR5cGUiLCAiIl0sCgogICAgeyJ4LWFtei1jcmVkZW50aWFsIjogIkFLSUFJTlRZQ0hONDJVSDNMR1JBLzIwMTcwODA0L3VzLWVhc3QtMS9zMy9hd3M0X3JlcXVlc3QifSwKICAgIHsieC1hbXotYWxnb3JpdGhtIjogIkFXUzQtSE1BQy1TSEEyNTYifSwKICAgIHsieC1hbXotZGF0ZSI6ICIyMDE3MDgwNFQxOTM5MjdaIiB9CiAgXQp9;
// signature =
// 3608fdc9af8ca0d13c754c34eb37014c9995b058c2e0166550468de47b00f316;
// url = "profiles-staging.signal.org";
NSString *formUrl = responseMap[@"url"];
if (![formUrl isKindOfClass:[NSString class]] || formUrl.length < 1) {
OWSProdFail(@"profile_manager_error_avatar_upload_form_invalid_url");
failureBlock();
return;
}
NSString *formAcl = responseMap[@"acl"];
if (![formAcl isKindOfClass:[NSString class]] || formAcl.length < 1) {
OWSProdFail(@"profile_manager_error_avatar_upload_form_invalid_acl");
failureBlock();
return;
}
NSString *formKey = responseMap[@"key"];
if (![formKey isKindOfClass:[NSString class]] || formKey.length < 1) {
OWSProdFail(@"profile_manager_error_avatar_upload_form_invalid_key");
failureBlock();
return;
}
NSString *formPolicy = responseMap[@"policy"];
if (![formPolicy isKindOfClass:[NSString class]] || formPolicy.length < 1) {
OWSProdFail(@"profile_manager_error_avatar_upload_form_invalid_policy");
failureBlock();
return;
}
NSString *formAlgorithm = responseMap[@"algorithm"];
if (![formAlgorithm isKindOfClass:[NSString class]] || formAlgorithm.length < 1) {
OWSProdFail(@"profile_manager_error_avatar_upload_form_invalid_algorithm");
failureBlock();
return;
}
NSString *formCredential = responseMap[@"credential"];
if (![formCredential isKindOfClass:[NSString class]] || formCredential.length < 1) {
OWSProdFail(@"profile_manager_error_avatar_upload_form_invalid_credential");
failureBlock();
return;
}
NSString *formDate = responseMap[@"date"];
if (![formDate isKindOfClass:[NSString class]] || formDate.length < 1) {
OWSProdFail(@"profile_manager_error_avatar_upload_form_invalid_date");
failureBlock();
return;
}
NSString *formSignature = responseMap[@"signature"];
if (![formSignature isKindOfClass:[NSString class]] || formSignature.length < 1) {
OWSProdFail(@"profile_manager_error_avatar_upload_form_invalid_signature");
failureBlock();
return;
}
NSDictionary<NSString *, NSString *> *parameters = @{
@"acl" : formAcl,
@"x-amz-algorithm" : formAlgorithm,
@"x-amz-credential" : formCredential,
@"x-amz-date" : formDate,
@"key" : formKey,
@"policy" : formPolicy,
@"x-amz-signature" : formSignature,
};
NSString *filePath = [self.profileAvatarsDirPath stringByAppendingPathComponent:fileName];
NSInputStream *fileInputStream = [[NSInputStream alloc] initWithFileAtPath:filePath];
if (!fileInputStream) {
OWSProdFail(@"profile_manager_error_avatar_upload_invalid_file_stream");
failureBlock();
return;
}
NSError *error;
long long fileSize =
[[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&error][NSFileSize]
longLongValue];
if (error || fileSize <= 0) {
OWSProdFail(@"profile_manager_error_avatar_upload_invalid_file_size");
failureBlock();
return;
}
NSMutableURLRequest *uploadRequest = [[AFHTTPRequestSerializer serializer]
multipartFormRequestWithMethod:@"post"
URLString:[@"https://" stringByAppendingString:formUrl]
parameters:parameters
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
// [formData appendPartWithFormData:<#(nonnull NSData *)#> name:@"acl"];
[formData appendPartWithInputStream:fileInputStream
name:@"file"
fileName:fileName
length:fileSize
mimeType:@"image/jpeg"];
}
error:&error];
if (error || !uploadRequest) {
OWSProdFail(@"profile_manager_error_avatar_upload_invalid_upload_request");
failureBlock();
return;
}
[uploadRequest setValue:@"Content-Type: text/html; charset=UTF-8" forHTTPHeaderField:@"Content-Type"];
// [uploadRequest setAllHTTPHeaderFields:headerDictionary];
// TODO: Should we use a special configuration as we do in TSNetworkManager?
// TODO: How does censorship circumvention fit in?
AFURLSessionManager *manager = [[AFURLSessionManager alloc]
initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
manager.responseSerializer = [AFXMLParserResponseSerializer new];
NSURLSessionUploadTask *uploadTask;
uploadTask = [manager uploadTaskWithStreamedRequest:uploadRequest
progress:^(NSProgress *_Nonnull uploadProgress) {
// This is not called back on the main queue.
// You are responsible for dispatching to the main queue for UI updates
DDLogVerbose(@"%@ Avatar upload progress: %f", self.tag, uploadProgress.fractionCompleted);
}
completionHandler:^(NSURLResponse *_Nonnull response,
id _Nullable uploadResponseObject,
NSError *_Nullable uploadError) {
if (uploadError) {
DDLogError(@"%@ Avatar upload failed: %@", self.tag, uploadError);
failureBlock();
} else {
DDLogVerbose(@"%@ Avatar upload succeeded", self.tag);
successBlock(avatarUrl, avatarDigest);
}
}];
[uploadTask resume];
}
failure:^(NSURLSessionDataTask *task, NSError *error) {
DDLogError(@"%@ Failed to get profile avatar upload form: %@", self.tag, error);
failureBlock();
}];
}); });
} }

Loading…
Cancel
Save