| 
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -1056,9 +1056,11 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        NSString *_Nullable avatarUrlPathAtStart = userProfile.avatarUrlPath;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (userProfile.avatarUrlPath.length < 1) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if (userProfile.profileKey.keyData.length < 1 || userProfile.avatarUrlPath.length < 1) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        OWSAES256Key *profileKeyAtStart = userProfile.profileKey;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        NSString *fileName = [self generateAvatarFilename];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        NSString *filePath = [OWSUserProfile profileAvatarFilepathWithFilename:fileName];
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -1077,7 +1079,6 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        NSString *tempDirectory = OWSTemporaryDirectory();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        NSString *tempFilePath = [tempDirectory stringByAppendingPathComponent:fileName];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        NSString *profilePictureURL = userProfile.avatarUrlPath;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        NSError *serializationError;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        NSMutableURLRequest *request =
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -1091,9 +1092,8 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        NSURLSession* session = [NSURLSession sharedSession];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        NSURLSessionTask* downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            @synchronized(self.currentAvatarDownloads)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                [self.currentAvatarDownloads removeObject:userProfile.recipientId];
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -1105,32 +1105,68 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            NSFileManager *fileManager = [NSFileManager defaultManager];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            NSURL *fileURL = [NSURL fileURLWithPath:filePath];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            NSURL *tempFileUrl = [NSURL fileURLWithPath:tempFilePath];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            NSError *moveError;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if (![fileManager moveItemAtURL:location toURL:fileURL error:&moveError]) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if (![fileManager moveItemAtURL:location toURL:tempFileUrl error:&moveError]) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                OWSLogError(@"MoveItemAtURL for avatar failed: %@", moveError);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            NSData *_Nullable encryptedData = (error ? nil : [NSData dataWithContentsOfFile:tempFilePath]);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            NSData *_Nullable decryptedData = [self decryptProfileData:encryptedData profileKey:profileKeyAtStart];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            UIImage *_Nullable image = nil;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if (decryptedData) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                BOOL success = [decryptedData writeToFile:filePath atomically:YES];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if (success) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    image = [UIImage imageWithContentsOfFile:filePath];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            OWSUserProfile *latestUserProfile = [OWSUserProfile getOrBuildUserProfileForRecipientId:userProfile.recipientId dbConnection:self.dbConnection];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if (latestUserProfile.profileKey.keyData.length < 1
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                || ![latestUserProfile.profileKey isEqual:userProfile.profileKey]) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                OWSLogWarn(@"Ignoring avatar download for obsolete user profile.");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            } else if (![avatarUrlPathAtStart isEqualToString:latestUserProfile.avatarUrlPath]) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                OWSLogInfo(@"avatar url has changed during download");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if (latestUserProfile.avatarUrlPath.length > 0) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    [self downloadAvatarForUserProfile:latestUserProfile];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            } else if (error) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if ([response isKindOfClass:NSHTTPURLResponse.class]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    && ((NSHTTPURLResponse *)response).statusCode == 403) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    OWSLogInfo(@"no avatar for: %@", userProfile.recipientId);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    OWSLogError(@"avatar download for %@ failed with error: %@", userProfile.recipientId, error);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            } else if (!encryptedData) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                OWSLogError(@"avatar encrypted data for %@ could not be read.", userProfile.recipientId);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            } else if (!decryptedData) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                OWSLogError(@"avatar data for %@ could not be decrypted.", userProfile.recipientId);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            } else if (!image) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                OWSLogError(@"avatar image for %@ could not be loaded with error: %@", userProfile.recipientId, error);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                [self updateProfileAvatarCache:image filename:fileName];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            UIImage *image = [UIImage imageWithContentsOfFile:[fileURL path]];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if (image) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                dispatch_async(dispatch_get_main_queue(), ^{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                [latestUserProfile updateWithAvatarFileName:fileName dbConnection:self.dbConnection completion:^{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    [[NSNotificationCenter defaultCenter]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        postNotificationNameAsync:OWSContactsManagerSignalAccountsDidChangeNotification
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        object:nil];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    [self updateProfileAvatarCache:image filename:fileName];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    OWSUserProfile *latestUserProfile =
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        [OWSUserProfile getOrBuildUserProfileForRecipientId:userProfile.recipientId
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                                               dbConnection:self.dbConnection];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // If we're updating the profile that corresponds to our local number,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // update the local profile as well.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if (userProfile.address.isLocalAddress) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                OWSUserProfile *localUserProfile = self.localUserProfile;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                OWSAssertDebug(localUserProfile);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    [latestUserProfile updateWithAvatarFileName:fileName dbConnection:self.dbConnection completion:^{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        [[NSNotificationCenter defaultCenter]
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            postNotificationNameAsync:OWSContactsManagerSignalAccountsDidChangeNotification
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                            object:nil];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    }];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                });
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                [localUserProfile updateWithAvatarFileName:fileName dbConnection:self.dbConnection completion:nil];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                [self updateProfileAvatarCache:image filename:fileName];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            OWSAssertDebug(backgroundTask);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            backgroundTask = nil;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        [downloadTask resume];
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |