parent
83d01eed76
commit
823927685d
|
@ -10,7 +10,7 @@
|
|||
#import <SignalServiceKit/OWSMessageSender.h>
|
||||
#import <SignalServiceKit/SecurityUtils.h>
|
||||
#import <SignalServiceKit/TSGroupThread.h>
|
||||
#import <SignalServiceKit/TSStorageManager.h>
|
||||
#import <SignalServiceKit/TSSetProfileRequest.h>
|
||||
#import <SignalServiceKit/TSStorageManager.h>
|
||||
#import <SignalServiceKit/TSThread.h>
|
||||
#import <SignalServiceKit/TSYapDatabaseObject.h>
|
||||
|
@ -423,17 +423,20 @@ static const NSInteger kProfileKeyLength = 16;
|
|||
OWSAssert(failureBlock);
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
// TODO: Do we need to use NSDataBase64EncodingOptions?
|
||||
NSString *_Nullable localProfileNameBase64 = [[self encryptProfileString:localProfileName] base64EncodedString];
|
||||
NSString *_Nullable avatarUrlBase64 = [[avatarUrl dataUsingEncoding:NSUTF8StringEncoding] base64EncodedString];
|
||||
NSString *_Nullable avatarDigestBase64 = [avatarDigest base64EncodedString];
|
||||
NSData *_Nullable profileNameEncrypted = [self encryptProfileString:localProfileName];
|
||||
|
||||
// TODO:
|
||||
if (YES) {
|
||||
successBlock();
|
||||
return;
|
||||
}
|
||||
failureBlock();
|
||||
TSSetProfileRequest *request = [[TSSetProfileRequest alloc] initWithProfileName:profileNameEncrypted
|
||||
avatarUrl:avatarUrl
|
||||
avatarDigest:avatarDigest];
|
||||
|
||||
[self.networkManager makeRequest:request
|
||||
success:^(NSURLSessionDataTask *task, id responseObject) {
|
||||
successBlock();
|
||||
}
|
||||
failure:^(NSURLSessionDataTask *task, NSError *error) {
|
||||
DDLogError(@"%@ Failed to update profile with error: %@", self.tag, error);
|
||||
failureBlock();
|
||||
}];
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -669,46 +672,51 @@ static const NSInteger kProfileKeyLength = 16;
|
|||
- (void)updateProfileForRecipientId:(NSString *)recipientId
|
||||
profileNameEncrypted:(NSData *_Nullable)profileNameEncrypted
|
||||
avatarUrlData:(NSData *_Nullable)avatarUrlData
|
||||
avatarDigest:(NSData *_Nullable)avatarDigest
|
||||
avatarDigest:(NSData *_Nullable)avatarDigestParam
|
||||
{
|
||||
OWSAssert(recipientId.length > 0);
|
||||
|
||||
UserProfile *userProfile = [self getOrBuildUserProfileForRecipientId:recipientId];
|
||||
if (!userProfile.profileKey) {
|
||||
return;
|
||||
}
|
||||
// Ensure decryption, etc. off main thread.
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
|
||||
NSString *_Nullable profileName =
|
||||
[self decryptProfileString:profileNameEncrypted profileKey:userProfile.profileKey];
|
||||
NSString *_Nullable avatarUrl
|
||||
= (avatarUrlData ? [[NSString alloc] initWithData:avatarUrlData encoding:NSUTF8StringEncoding] : nil);
|
||||
|
||||
if (!avatarUrl || !avatarDigest) {
|
||||
// If either avatar url or digest is missing, skip both.
|
||||
avatarUrl = nil;
|
||||
avatarDigest = nil;
|
||||
}
|
||||
|
||||
BOOL isAvatarSame = ([self isNullableStringEqual:userProfile.avatarUrl toString:avatarUrl] &&
|
||||
[self isNullableDataEqual:userProfile.avatarDigest toData:avatarDigest]);
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
userProfile.profileName = profileName;
|
||||
userProfile.avatarUrl = avatarUrl;
|
||||
userProfile.avatarDigest = avatarDigest;
|
||||
|
||||
if (!isAvatarSame) {
|
||||
// Evacuate avatar image cache.
|
||||
[self.otherUsersProfileAvatarImageCache removeObjectForKey:recipientId];
|
||||
|
||||
if (avatarUrl) {
|
||||
[self downloadProfileAvatarWithUrl:avatarUrl recipientId:recipientId];
|
||||
}
|
||||
UserProfile *userProfile = [self getOrBuildUserProfileForRecipientId:recipientId];
|
||||
if (!userProfile.profileKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
userProfile.lastUpdateDate = [NSDate new];
|
||||
NSString *_Nullable profileName =
|
||||
[self decryptProfileString:profileNameEncrypted profileKey:userProfile.profileKey];
|
||||
NSString *_Nullable avatarUrl
|
||||
= (avatarUrlData ? [[NSString alloc] initWithData:avatarUrlData encoding:NSUTF8StringEncoding] : nil);
|
||||
NSData *_Nullable avatarDigest = avatarDigestParam;
|
||||
|
||||
[self saveUserProfile:userProfile];
|
||||
if (!avatarUrl || !avatarDigest) {
|
||||
// If either avatar url or digest is missing, skip both.
|
||||
avatarUrl = nil;
|
||||
avatarDigest = nil;
|
||||
}
|
||||
|
||||
BOOL isAvatarSame = ([self isNullableStringEqual:userProfile.avatarUrl toString:avatarUrl] &&
|
||||
[self isNullableDataEqual:userProfile.avatarDigest toData:avatarDigest]);
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
userProfile.profileName = profileName;
|
||||
userProfile.avatarUrl = avatarUrl;
|
||||
userProfile.avatarDigest = avatarDigest;
|
||||
|
||||
if (!isAvatarSame) {
|
||||
// Evacuate avatar image cache.
|
||||
[self.otherUsersProfileAvatarImageCache removeObjectForKey:recipientId];
|
||||
|
||||
if (avatarUrl) {
|
||||
[self downloadProfileAvatarWithUrl:avatarUrl recipientId:recipientId];
|
||||
}
|
||||
}
|
||||
|
||||
userProfile.lastUpdateDate = [NSDate new];
|
||||
|
||||
[self saveUserProfile:userProfile];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -213,13 +213,15 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
{
|
||||
__weak ProfileViewController *weakSelf = self;
|
||||
[OWSProfileManager.sharedManager updateLocalProfileName:self.nameTextField.text
|
||||
avatarImage:self.avatar
|
||||
success:^{
|
||||
[weakSelf.navigationController popViewControllerAnimated:YES];
|
||||
}
|
||||
failure:^{
|
||||
// TODO: Handle failure.
|
||||
}];
|
||||
avatarImage:self.avatar
|
||||
success:^{
|
||||
[weakSelf.navigationController popViewControllerAnimated:YES];
|
||||
}
|
||||
failure:^{
|
||||
[OWSAlerts showAlertWithTitle:NSLocalizedString(@"ALERT_ERROR_TITLE", @"")
|
||||
message:NSLocalizedString(@"PROFILE_VIEW_ERROR_UPDATE_FAILED",
|
||||
@"Error message shown when a profile update fails.")];
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - UITextFieldDelegate
|
||||
|
|
|
@ -1069,6 +1069,9 @@
|
|||
/* Label for action that clear's the user's profile avatar */
|
||||
"PROFILE_VIEW_CLEAR_AVATAR" = "Clear Avatar";
|
||||
|
||||
/* Error message shown when a profile update fails. */
|
||||
"PROFILE_VIEW_ERROR_UPDATE_FAILED" = "Profile update failed.";
|
||||
|
||||
/* Default text for the profile name field of the profile view. */
|
||||
"PROFILE_VIEW_NAME_DEFAULT_TEXT" = "Enter your name.";
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
* Normally this is private, but we need to embed this
|
||||
* data structure within our own.
|
||||
*/
|
||||
- (OWSSignalServiceProtosDataMessage *)buildDataMessage:(NSString *)recipientId;
|
||||
- (OWSSignalServiceProtosDataMessage *)buildDataMessage:(NSString *_Nullable)recipientId;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -455,10 +455,9 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
|
|||
return builder;
|
||||
}
|
||||
|
||||
- (OWSSignalServiceProtosDataMessage *)buildDataMessage:(NSString *)recipientId
|
||||
- (OWSSignalServiceProtosDataMessage *)buildDataMessage:(NSString *_Nullable)recipientId
|
||||
{
|
||||
OWSAssert(self.thread);
|
||||
OWSAssert(recipientId.length > 0);
|
||||
|
||||
OWSSignalServiceProtosDataMessageBuilder *builder = [self dataMessageBuilder];
|
||||
[builder addLocalProfileKeyIfNecessary:self.thread recipientId:recipientId];
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TSRequest.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface TSSetProfileRequest : TSRequest
|
||||
|
||||
- (nullable instancetype)initWithProfileName:(NSData *_Nullable)profileNameEncrypted
|
||||
avatarUrl:(NSString *_Nullable)avatarUrl
|
||||
avatarDigest:(NSData *_Nullable)avatarDigest;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TSSetProfileRequest.h"
|
||||
#import "NSData+Base64.h"
|
||||
#import "TSConstants.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation TSSetProfileRequest
|
||||
|
||||
- (nullable instancetype)initWithProfileName:(NSData *_Nullable)profileNameEncrypted
|
||||
avatarUrl:(NSString *_Nullable)avatarUrl
|
||||
avatarDigest:(NSData *_Nullable)avatarDigest
|
||||
{
|
||||
|
||||
self = [super initWithURL:[NSURL URLWithString:textSecureSetProfileAPI]];
|
||||
|
||||
self.HTTPMethod = @"PUT";
|
||||
|
||||
if (profileNameEncrypted.length > 0) {
|
||||
self.parameters[@"name"] = [profileNameEncrypted base64EncodedString];
|
||||
}
|
||||
if (avatarUrl.length > 0) {
|
||||
self.parameters[@"avatar"] = [[avatarUrl dataUsingEncoding:NSUTF8StringEncoding] base64EncodedString];
|
||||
}
|
||||
if (avatarDigest.length > 0) {
|
||||
self.parameters[@"avatarDigest"] = [avatarDigest base64EncodedString];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -16,7 +16,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
@interface OWSSignalServiceProtosDataMessageBuilder (OWS)
|
||||
|
||||
- (void)addLocalProfileKeyIfNecessary:(TSThread *)thread recipientId:(NSString *)recipientId;
|
||||
- (void)addLocalProfileKeyIfNecessary:(TSThread *)thread recipientId:(NSString *_Nullable)recipientId;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -12,11 +12,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
@implementation PBGeneratedMessageBuilder (OWS)
|
||||
|
||||
- (BOOL)shouldMessageHaveLocalProfileKey:(TSThread *)thread recipientId:(NSString *)recipientId
|
||||
// recipient:(SignalRecipient *)recipient
|
||||
- (BOOL)shouldMessageHaveLocalProfileKey:(TSThread *)thread recipientId:(NSString *_Nullable)recipientId
|
||||
{
|
||||
OWSAssert(thread);
|
||||
OWSAssert(recipientId.length > 0);
|
||||
|
||||
id<ProfileManagerProtocol> profileManager = [TextSecureKitEnv sharedEnv].profileManager;
|
||||
|
||||
|
@ -25,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
//
|
||||
// For Group threads, we want to include the profile key IFF the
|
||||
// recipient OR the group is in the whitelist.
|
||||
if ([profileManager isUserInProfileWhitelist:recipientId]) {
|
||||
if (recipientId.length > 0 && [profileManager isUserInProfileWhitelist:recipientId]) {
|
||||
return YES;
|
||||
} else if ([profileManager isThreadInProfileWhitelist:thread]) {
|
||||
return YES;
|
||||
|
@ -46,10 +44,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
@implementation OWSSignalServiceProtosDataMessageBuilder (OWS)
|
||||
|
||||
- (void)addLocalProfileKeyIfNecessary:(TSThread *)thread recipientId:(NSString *)recipientId
|
||||
- (void)addLocalProfileKeyIfNecessary:(TSThread *)thread recipientId:(NSString *_Nullable)recipientId
|
||||
{
|
||||
OWSAssert(thread);
|
||||
OWSAssert(recipientId.length > 0);
|
||||
|
||||
if ([self shouldMessageHaveLocalProfileKey:thread recipientId:recipientId]) {
|
||||
[self setProfileKey:self.localProfileKey];
|
||||
|
|
|
@ -41,6 +41,7 @@ typedef enum { kSMSVerification, kPhoneNumberVerification } VerificationTranspor
|
|||
#define textSecureDeviceProvisioningAPIFormat @"v1/provisioning/%@"
|
||||
#define textSecureDevicesAPIFormat @"v1/devices/%@"
|
||||
#define textSecureProfileAPIFormat @"v1/profile/%@"
|
||||
#define textSecureSetProfileAPI @"v1/profile"
|
||||
|
||||
#pragma mark Push RegistrationSpecific Constants
|
||||
typedef NS_ENUM(NSInteger, TSPushRegistrationError) {
|
||||
|
|
Loading…
Reference in New Issue