Attachments: Sending and receiving

This commit is contained in:
Frederic Jacobs 2014-12-22 00:40:15 +01:00
parent 9683451ed9
commit 8334adb4d9
24 changed files with 352 additions and 138 deletions

View file

@ -288,6 +288,9 @@
B6019E971A2492AB001118DF /* NSDate+millisecondTimeStamp.mm in Sources */ = {isa = PBXBuildFile; fileRef = B6019E961A2492AB001118DF /* NSDate+millisecondTimeStamp.mm */; };
B60C16651988999D00E97A6C /* VersionMigrations.m in Sources */ = {isa = PBXBuildFile; fileRef = B60C16641988999D00E97A6C /* VersionMigrations.m */; };
B60EDE041A05A01700D73516 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B60EDE031A05A01700D73516 /* AudioToolbox.framework */; };
B60FB9A71A46F099006A5A66 /* TSAllocAttachmentRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B60FB9A61A46F099006A5A66 /* TSAllocAttachmentRequest.m */; };
B60FB9AD1A46F831006A5A66 /* UIImage+contentTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = B60FB9AC1A46F831006A5A66 /* UIImage+contentTypes.m */; };
B60FB9B01A4711D4006A5A66 /* TSAttachmentEncryptionResult.m in Sources */ = {isa = PBXBuildFile; fileRef = B60FB9AF1A4711D4006A5A66 /* TSAttachmentEncryptionResult.m */; };
B62D53F71A23CCAD009AAF82 /* TSMessageAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = B62D53F61A23CCAD009AAF82 /* TSMessageAdapter.m */; };
B633C5801A1D190B0059AC12 /* archive@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C4FE1A1D190B0059AC12 /* archive@2x.png */; };
B633C5831A1D190B0059AC12 /* backspace.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C5011A1D190B0059AC12 /* backspace.png */; };
@ -336,10 +339,10 @@
B63AF5CD1A1F757900D01AAD /* TSRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5B91A1F757900D01AAD /* TSRequest.m */; };
B63AF5CE1A1F757900D01AAD /* TSAttachmentRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5BB1A1F757900D01AAD /* TSAttachmentRequest.m */; };
B63AF5D01A1F757900D01AAD /* TSSubmitMessageRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5BF1A1F757900D01AAD /* TSSubmitMessageRequest.m */; };
B63AF5D11A1F757900D01AAD /* TSUploadAttachment.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5C11A1F757900D01AAD /* TSUploadAttachment.m */; };
B63AF5D21A1F757900D01AAD /* TSNetworkManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5C31A1F757900D01AAD /* TSNetworkManager.m */; };
B63AF5D31A1F757900D01AAD /* TSSocketManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5C61A1F757900D01AAD /* TSSocketManager.m */; };
B63AF5D81A1F889500D01AAD /* SubProtocol.pb.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5D71A1F889500D01AAD /* SubProtocol.pb.m */; settings = {COMPILER_FLAGS = "-w"; }; };
B640C4771A477B0F005C7C8A /* TSAttachementsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B640C4761A477B0F005C7C8A /* TSAttachementsTest.m */; };
B6416FB8199A0478003C5699 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = B6416F57199A0478003C5699 /* Localizable.strings */; };
B65EDA1219E1BE6400AAA7CB /* RPAPICall.m in Sources */ = {isa = PBXBuildFile; fileRef = B65EDA1119E1BE6400AAA7CB /* RPAPICall.m */; };
B66DBF4A19D5BBC8006EA940 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B66DBF4919D5BBC8006EA940 /* Images.xcassets */; };
@ -884,6 +887,12 @@
B60C16631988999D00E97A6C /* VersionMigrations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VersionMigrations.h; sourceTree = "<group>"; };
B60C16641988999D00E97A6C /* VersionMigrations.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VersionMigrations.m; sourceTree = "<group>"; };
B60EDE031A05A01700D73516 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
B60FB9A51A46F099006A5A66 /* TSAllocAttachmentRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSAllocAttachmentRequest.h; sourceTree = "<group>"; };
B60FB9A61A46F099006A5A66 /* TSAllocAttachmentRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAllocAttachmentRequest.m; sourceTree = "<group>"; };
B60FB9AB1A46F831006A5A66 /* UIImage+contentTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+contentTypes.h"; sourceTree = "<group>"; };
B60FB9AC1A46F831006A5A66 /* UIImage+contentTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+contentTypes.m"; sourceTree = "<group>"; };
B60FB9AE1A4711D4006A5A66 /* TSAttachmentEncryptionResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSAttachmentEncryptionResult.h; sourceTree = "<group>"; };
B60FB9AF1A4711D4006A5A66 /* TSAttachmentEncryptionResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachmentEncryptionResult.m; sourceTree = "<group>"; };
B62D53F51A23CCAD009AAF82 /* TSMessageAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSMessageAdapter.h; sourceTree = "<group>"; };
B62D53F61A23CCAD009AAF82 /* TSMessageAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSMessageAdapter.m; sourceTree = "<group>"; };
B633C4FE1A1D190B0059AC12 /* archive@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "archive@2x.png"; sourceTree = "<group>"; };
@ -949,14 +958,13 @@
B63AF5BB1A1F757900D01AAD /* TSAttachmentRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachmentRequest.m; sourceTree = "<group>"; };
B63AF5BE1A1F757900D01AAD /* TSSubmitMessageRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSSubmitMessageRequest.h; sourceTree = "<group>"; };
B63AF5BF1A1F757900D01AAD /* TSSubmitMessageRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSSubmitMessageRequest.m; sourceTree = "<group>"; };
B63AF5C01A1F757900D01AAD /* TSUploadAttachment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSUploadAttachment.h; sourceTree = "<group>"; };
B63AF5C11A1F757900D01AAD /* TSUploadAttachment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSUploadAttachment.m; sourceTree = "<group>"; };
B63AF5C21A1F757900D01AAD /* TSNetworkManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSNetworkManager.h; sourceTree = "<group>"; };
B63AF5C31A1F757900D01AAD /* TSNetworkManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSNetworkManager.m; sourceTree = "<group>"; };
B63AF5C51A1F757900D01AAD /* TSSocketManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSSocketManager.h; sourceTree = "<group>"; };
B63AF5C61A1F757900D01AAD /* TSSocketManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSSocketManager.m; sourceTree = "<group>"; };
B63AF5D61A1F889500D01AAD /* SubProtocol.pb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubProtocol.pb.h; sourceTree = "<group>"; };
B63AF5D71A1F889500D01AAD /* SubProtocol.pb.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SubProtocol.pb.m; sourceTree = "<group>"; };
B640C4761A477B0F005C7C8A /* TSAttachementsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachementsTest.m; sourceTree = "<group>"; };
B6416F58199A0478003C5699 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Localizable.strings; sourceTree = "<group>"; };
B657DDC91911A40500F45B0C /* Signal.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Signal.entitlements; sourceTree = "<group>"; };
B65EDA1019E1BE6400AAA7CB /* RPAPICall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RPAPICall.h; sourceTree = "<group>"; };
@ -2221,6 +2229,8 @@
B63AF5AB1A1F757900D01AAD /* Requests */ = {
isa = PBXGroup;
children = (
B60FB9A51A46F099006A5A66 /* TSAllocAttachmentRequest.h */,
B60FB9A61A46F099006A5A66 /* TSAllocAttachmentRequest.m */,
B63AF5AC1A1F757900D01AAD /* TSContactsIntersectionRequest.h */,
B63AF5AD1A1F757900D01AAD /* TSContactsIntersectionRequest.m */,
B63AF5AE1A1F757900D01AAD /* TSUnregisterAccountRequest.h */,
@ -2239,8 +2249,6 @@
B63AF5BB1A1F757900D01AAD /* TSAttachmentRequest.m */,
B63AF5BE1A1F757900D01AAD /* TSSubmitMessageRequest.h */,
B63AF5BF1A1F757900D01AAD /* TSSubmitMessageRequest.m */,
B63AF5C01A1F757900D01AAD /* TSUploadAttachment.h */,
B63AF5C11A1F757900D01AAD /* TSUploadAttachment.m */,
);
path = Requests;
sourceTree = "<group>";
@ -2292,6 +2300,7 @@
B6B095E11A1D25C5008BFAA6 /* TSStorageIdentityKeyStoreTests.m */,
B6B095E21A1D25C5008BFAA6 /* TSStoragePreKeyStoreTests.m */,
B6B095E31A1D25C5008BFAA6 /* TSStorageSignedPreKeyStore.m */,
B640C4761A477B0F005C7C8A /* TSAttachementsTest.m */,
);
path = textsecure;
sourceTree = "<group>";
@ -2367,14 +2376,14 @@
B6B096101A1D25ED008BFAA6 /* TSInteraction.m */,
B6B096111A1D25ED008BFAA6 /* TSMessage.h */,
B6B096121A1D25ED008BFAA6 /* TSMessage.m */,
B6B50AA91A4192C500F8F607 /* TSMessagesManager+attachments.h */,
B6B50AAA1A4192C500F8F607 /* TSMessagesManager+attachments.m */,
B63885CB1A26772D00A226A6 /* TSMessagesManager+callRecorder.h */,
B63885CC1A26772D00A226A6 /* TSMessagesManager+callRecorder.m */,
B6B096131A1D25ED008BFAA6 /* TSMessagesManager+sendMessages.h */,
B6B096141A1D25ED008BFAA6 /* TSMessagesManager+sendMessages.m */,
B6B096151A1D25ED008BFAA6 /* TSMessagesManager.h */,
B6B096161A1D25ED008BFAA6 /* TSMessagesManager.m */,
B6B50AA91A4192C500F8F607 /* TSMessagesManager+attachments.h */,
B6B50AAA1A4192C500F8F607 /* TSMessagesManager+attachments.m */,
B6B096171A1D25ED008BFAA6 /* TSOutgoingMessage.h */,
B6B096181A1D25ED008BFAA6 /* TSOutgoingMessage.m */,
B6B096191A1D25ED008BFAA6 /* TSServerMessage.h */,
@ -2445,6 +2454,10 @@
B6B096601A1D25ED008BFAA6 /* NSURLSessionDataTask+StatusCode.m */,
B6019E951A2492AB001118DF /* NSDate+millisecondTimeStamp.h */,
B6019E961A2492AB001118DF /* NSDate+millisecondTimeStamp.mm */,
B60FB9AB1A46F831006A5A66 /* UIImage+contentTypes.h */,
B60FB9AC1A46F831006A5A66 /* UIImage+contentTypes.m */,
B60FB9AE1A4711D4006A5A66 /* TSAttachmentEncryptionResult.h */,
B60FB9AF1A4711D4006A5A66 /* TSAttachmentEncryptionResult.m */,
);
path = Util;
sourceTree = "<group>";
@ -3082,6 +3095,7 @@
buildActionMask = 2147483647;
files = (
76EB063E18170B33006006FC /* Operation.m in Sources */,
B60FB9AD1A46F831006A5A66 /* UIImage+contentTypes.m in Sources */,
76EB05F618170B33006006FC /* CallConnectUtil.m in Sources */,
76EB061218170B33006006FC /* LoggingUtil.m in Sources */,
A56977921A351BC400173BF2 /* PresentIdentityQRCodeViewController.m in Sources */,
@ -3225,6 +3239,7 @@
FC31962A1A067D8F0094C78E /* MessageComposeTableViewController.m in Sources */,
E16E5BEE18AAC40200B7C403 /* EC25KeyAgreementParticipant.m in Sources */,
76EB057418170B33006006FC /* RecentCallManager.m in Sources */,
B60FB9A71A46F099006A5A66 /* TSAllocAttachmentRequest.m in Sources */,
76EB061C18170B33006006FC /* ArrayUtil.m in Sources */,
76EB05C418170B33006006FC /* HandshakePacket.m in Sources */,
76EB05AA18170B33006006FC /* SequenceCounter.m in Sources */,
@ -3235,13 +3250,13 @@
B6B096881A1D25ED008BFAA6 /* TSStorageManager+keyFromIntLong.m in Sources */,
B6B50AAB1A4192C500F8F607 /* TSMessagesManager+attachments.m in Sources */,
76EB059018170B33006006FC /* IgnoredPacketFailure.m in Sources */,
B60FB9B01A4711D4006A5A66 /* TSAttachmentEncryptionResult.m in Sources */,
765052AF182AC9B5008313E1 /* DialerButtonView.m in Sources */,
76EB05D418170B33006006FC /* ZrtpManager.m in Sources */,
B63AF5CD1A1F757900D01AAD /* TSRequest.m in Sources */,
76EB058E18170B33006006FC /* HostNameEndPoint.m in Sources */,
E19167A418A9687800B7A468 /* DH3KKeyAgreementParticipant.m in Sources */,
E16E5BF018AAC40200B7C403 /* EvpKeyAgreement.m in Sources */,
B63AF5D11A1F757900D01AAD /* TSUploadAttachment.m in Sources */,
FCFD25821A154B3800F4C644 /* CodeVerificationViewController.m in Sources */,
FCF72A131A02D27F006BC849 /* ContactDetailTableViewController.m in Sources */,
B65EDA1219E1BE6400AAA7CB /* RPAPICall.m in Sources */,
@ -3379,6 +3394,7 @@
A157076117F0CD6D007C2BD6 /* RtpPacketTests.m in Sources */,
76EB05C518170B33006006FC /* HandshakePacket.m in Sources */,
76EB058F18170B33006006FC /* HostNameEndPoint.m in Sources */,
B640C4771A477B0F005C7C8A /* TSAttachementsTest.m in Sources */,
76EB062118170B33006006FC /* BloomFilter.m in Sources */,
76EB064518170B33006006FC /* ThreadManager.m in Sources */,
76EB068718170B34006006FC /* ContactTableViewCell.m in Sources */,

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6254" systemVersion="14C68k" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6254" systemVersion="14B25" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
<capability name="Alignment constraints with different attributes" minToolsVersion="5.1"/>

View file

@ -15,7 +15,7 @@
- (instancetype)initWithIdentifier:(uint64_t)identifier
key:(NSData*)key
contentType:(NSString*)contentType
relay:(NSString*)relay;
relay:(NSString*)relay NS_DESIGNATED_INITIALIZER;;
@property NSString *relay;

View file

@ -13,13 +13,11 @@
- (instancetype)initWithIdentifier:(NSString*)identifier
data:(NSData*)data
key:(NSData*)key
contentType:(NSString*)contentType;
contentType:(NSString*)contentType NS_DESIGNATED_INITIALIZER;;
- (NSString*)path;
- (UIImage *)image;
- (BOOL)isImage;
- (UIImage*)image;
- (BOOL)isVideo;
@end

View file

@ -62,6 +62,14 @@
}
}
- (BOOL)isVideo{
if ([self.contentType containsString:@"video/"]) {
return YES;
} else{
return NO;
}
}
- (UIImage*)image{
if (![self isImage]) {
return nil;

View file

@ -22,5 +22,4 @@
encryptionKey:(NSData*)encryptionKey
contentType:(NSString*)contentType;
@end

View file

@ -13,5 +13,6 @@
- (void)handleReceivedMediaMessage:(IncomingPushMessageSignal*)message withContent:(PushMessageContent*)content;
- (void)retrieveAttachment:(TSAttachment*)attachment;
- (void)sendAttachment:(NSData*)attachmentData contentType:(NSString*)contentType thread:(TSThread*)thread;
@end

View file

@ -11,12 +11,15 @@
#import "Cryptography.h"
#import "TSConstants.h"
#import "TSMessagesManager+attachments.h"
#import "TSAllocAttachmentRequest.h"
#import "TSAttachmentEncryptionResult.h"
#import "TSAttachmentPointer.h"
#import "TSAttachmentStream.h"
#import "TSAttachmentRequest.h"
#import "TSUploadAttachment.h"
#import "TSConstants.h"
#import "TSInfoMessage.h"
#import "TSattachmentPointer.h"
#import "TSMessagesManager+attachments.h"
#import "TSMessagesManager+sendMessages.h"
#import "TSNetworkManager.h"
@interface TSMessagesManager ()
@ -53,6 +56,39 @@ dispatch_queue_t attachmentsQueue() {
[self handleReceivedMessage:message withContent:content attachments:attachments];
}
- (void)sendAttachment:(NSData*)attachmentData contentType:(NSString*)contentType thread:(TSThread*)thread {
TSRequest *allocateAttachment = [[TSAllocAttachmentRequest alloc] init];
[[TSNetworkManager sharedManager] queueAuthenticatedRequest:allocateAttachment success:^(NSURLSessionDataTask *task, id responseObject) {
dispatch_async(attachmentsQueue(), ^{
if ([responseObject isKindOfClass:[NSDictionary class]]){
NSDictionary *responseDict = (NSDictionary*)responseObject;
NSString *attachementId = [[responseDict objectForKey:@"id"] stringValue];
NSString *location = [responseDict objectForKey:@"location"];
TSAttachmentEncryptionResult *result =
[Cryptography encryptAttachment:attachmentData contentType:contentType identifier:attachementId];
BOOL success = [self uploadData:result.body location:location];
if (success) {
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[result.pointer saveWithTransaction:transaction];
}];
TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:thread messageBody:nil attachments:@[attachementId]];
[self sendMessage:message inThread:thread];
} else{
DDLogWarn(@"Failed to upload attachment");
}
} else{
DDLogError(@"The server didn't returned an empty responseObject");
}
});
} failure:^(NSURLSessionDataTask *task, NSError *error) {
DDLogError(@"Failed to get attachment allocated: %@", error);
}];
}
- (void)retrieveAttachment:(TSAttachmentPointer*)attachment {
TSAttachmentRequest *attachmentRequest = [[TSAttachmentRequest alloc] initWithId:[attachment identifier]
@ -74,6 +110,21 @@ dispatch_queue_t attachmentsQueue() {
}];
}
- (void)decryptedAndSaveAttachment:(TSAttachmentPointer*)attachment data:(NSData*)cipherText {
NSData *plaintext = [Cryptography decryptAttachment:cipherText withKey:attachment.encryptionKey];
if (!plaintext) {
DDLogError(@"Failed to get attachment decrypted ...");
} else {
TSAttachmentStream *stream = [[TSAttachmentStream alloc] initWithIdentifier:attachment.uniqueId
data:plaintext key:attachment.encryptionKey
contentType:attachment.contentType];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[stream saveWithTransaction:transaction];
}];
}
}
- (NSData*)downloadFromLocation:(NSString*)location {
__block NSData *data;
@ -96,21 +147,31 @@ dispatch_queue_t attachmentsQueue() {
return data;
}
- (void)decryptedAndSaveAttachment:(TSAttachmentPointer*)attachment data:(NSData*)cipherText {
NSData *plaintext = [Cryptography decryptAttachment:cipherText withKey:attachment.encryptionKey];
- (BOOL)uploadData:(NSData*)cipherText location:(NSString*)location {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
__block BOOL success = NO;
if (!plaintext) {
DDLogError(@"Failed to get attachment decrypted ...");
} else {
TSAttachmentStream *stream = [[TSAttachmentStream alloc] initWithIdentifier:attachment.uniqueId
data:plaintext key:attachment.encryptionKey
contentType:attachment.contentType];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[stream saveWithTransaction:transaction];
}];
NSLog(@"We got %@ of type %@", plaintext, attachment.contentType);
}
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:location]];
request.HTTPMethod = @"PUT";
request.HTTPBody = cipherText;
[request setValue:@"application/octet-stream" forHTTPHeaderField:@"Content-Type"];
AFHTTPRequestOperation *httpOperation = [manager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
success = YES;
dispatch_semaphore_signal(sema);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
DDLogError(@"Failed uploading attachment with error: %@", error.description);
success = NO;
dispatch_semaphore_signal(sema);
}];
[httpOperation start];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
return success;
}
@end

View file

@ -21,8 +21,8 @@
#import "TSStorageManager+SignedPreKeyStore.h"
#import "PreKeyBundle+jsonDict.h"
#import "TSErrorMessage.h"
#import "TSAttachmentStream.h"
#import "TSNetworkManager.h"
#import "TSServerMessage.h"
#import "TSSubmitMessageRequest.h"
@ -219,9 +219,27 @@ dispatch_queue_t sendingQueue() {
PushMessageContentBuilder *builder = [PushMessageContentBuilder new];
[builder setBody:message.body];
return [builder.build data];
//TO-DO: DEAL WITH ATTACHEMENTS AND GROUPS STUFF
NSMutableArray *attachmentsArray = [NSMutableArray array];
for (NSString *attachmentId in message.attachments){
id dbObject = [TSAttachmentStream fetchObjectWithUniqueID:attachmentId];
if ([dbObject isKindOfClass:[TSAttachmentStream class]]) {
TSAttachmentStream *attachment = (TSAttachmentStream*)dbObject;
PushMessageContentAttachmentPointerBuilder *attachmentbuilder = [PushMessageContentAttachmentPointerBuilder new];
[attachmentbuilder setId:[attachment.identifier unsignedLongLongValue]];
[attachmentbuilder setContentType:attachment.contentType];
[attachmentbuilder setKey:attachment.encryptionKey];
[attachmentsArray addObject:[attachmentbuilder build]];
}
}
[builder setAttachmentsArray:attachmentsArray];
return [builder.build data];
}
@end

View file

@ -0,0 +1,13 @@
//
// TSAllocAttachmentRequest.h
// Signal
//
// Created by Frederic Jacobs on 21/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "TSRequest.h"
@interface TSAllocAttachmentRequest : TSRequest
@end

View file

@ -0,0 +1,26 @@
//
// TSAllocAttachmentRequest.m
// Signal
//
// Created by Frederic Jacobs on 21/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "TSAllocAttachmentRequest.h"
#import "TSConstants.h"
@implementation TSAllocAttachmentRequest
-(instancetype)init {
NSString *path = [NSString stringWithFormat:@"%@", textSecureAttachmentsAPI];
self = [super initWithURL:[NSURL URLWithString:path]];
if (self) {
[self setHTTPMethod:@"GET"];
}
return self;
}
@end

View file

@ -1,16 +0,0 @@
//
// TSUploadAttachment.h
// TextSecureiOS
//
// Created by Christine Corbett Moran on 12/3/13.
// Copyright (c) 2013 Open Whisper Systems. All rights reserved.
//
#import "TSRequest.h"
#import "TSAttachmentStream.h"
@interface TSUploadAttachment : TSRequest
-(TSRequest*) initWithAttachment:(TSAttachmentStream*)attachment;
@end

View file

@ -1,32 +0,0 @@
//
// TSUploadAttachment.m
// TextSecureiOS
//
// Created by Christine Corbett Moran on 12/3/13.
// Copyright (c) 2013 Open Whisper Systems. All rights reserved.
//
#import "TSUploadAttachment.h"
#import "TSAttachmentStream.h"
#import <AFNetworking/AFHTTPRequestOperation.h>
@interface TSUploadAttachment ()
@property(nonatomic,strong) TSAttachment* attachment;
@end
@implementation TSUploadAttachment
-(TSRequest*) initWithAttachment:(TSAttachmentStream*)attachment{
// self = [super initWithURL:attachment.attachmentURL];
// self.HTTPMethod = @"PUT";
// self.attachment = attachment;
//
// [self setHTTPBody:[self.attachment getData]];
// [self setAllHTTPHeaderFields: @{@"Content-Type": @"application/octet-stream"}];
//
// return self;
}
@end

View file

@ -14,7 +14,6 @@
#import "TSRequest.h"
#import "TSRegisterWithTokenRequest.h"
#import "TSStorageManager+keyingMaterial.h"
#import "TSUploadAttachment.h"
@interface TSNetworkManager ()

View file

@ -7,6 +7,7 @@
//
#import <Foundation/Foundation.h>
#import "TSAttachmentEncryptionResult.h"
@interface Cryptography : NSObject
@ -32,7 +33,6 @@ typedef NS_ENUM(NSInteger, TSMACType) {
#pragma mark encrypt and decrypt attachment data
+(NSData*) decryptAttachment:(NSData*)dataToDecrypt withKey:(NSData*)key ;
+(NSData*) encryptAttachment:(NSData*)attachment withRandomKey:(NSData**)key;
+(TSAttachmentEncryptionResult*)encryptAttachment:(NSData*)attachment contentType:(NSString*)contentType identifier:(NSString*)identifier;
@end

View file

@ -6,13 +6,15 @@
// Copyright (c) 2013 Open Whisper Systems. All rights reserved.
//
#import "Cryptography.h"
#import "Constraints.h"
#import <Security/Security.h>
#import <CommonCrypto/CommonHMAC.h>
#import <CommonCrypto/CommonCryptor.h>
#include "NSData+Base64.h"
#import "Cryptography.h"
#import "Constraints.h"
#import "TSAttachmentStream.h"
#import "NSData+Base64.h"
#define HMAC256_KEY_LENGTH 32
#define HMAC256_OUTPUT_LENGTH 32
@ -138,9 +140,10 @@
if(hmacType == TSHMACSHA1Truncated10Bytes) {
*hmac = [Cryptography truncatedSHA1HMAC:dataToHmac withHMACKey:hmacKey truncation:10];
}
else if (hmacType == TSHMACSHA256Truncated10Bytes) {
} else if (hmacType == TSHMACSHA256Truncated10Bytes) {
*hmac = [Cryptography truncatedSHA256HMAC:dataToHmac withHMACKey:hmacKey truncation:10];
} else if (hmacType == TSHMACSHA256AttachementType) {
*hmac = [Cryptography truncatedSHA256HMAC:dataToHmac withHMACKey:hmacKey truncation:HMAC256_OUTPUT_LENGTH];
}
return encryptedData;
@ -240,7 +243,7 @@
}
+(NSData*) decryptAttachment:(NSData*) dataToDecrypt withKey:(NSData*) key {
+ (NSData*)decryptAttachment:(NSData*)dataToDecrypt withKey:(NSData*)key {
if (([dataToDecrypt length] < AES_CBC_IV_LENGTH + HMAC256_OUTPUT_LENGTH) || ([key length] < AES_KEY_SIZE + HMAC256_KEY_LENGTH)) {
DDLogError(@"Message shorter than crypto overhead!");
return nil;
@ -254,35 +257,39 @@
NSData *iv = [dataToDecrypt subdataWithRange:NSMakeRange(0, AES_CBC_IV_LENGTH)];
NSData *encryptedAttachment = [dataToDecrypt subdataWithRange:NSMakeRange(AES_CBC_IV_LENGTH, [dataToDecrypt length]-AES_CBC_IV_LENGTH-HMAC256_OUTPUT_LENGTH)];
NSData *hmac = [dataToDecrypt subdataWithRange:NSMakeRange([dataToDecrypt length]-HMAC256_OUTPUT_LENGTH, HMAC256_OUTPUT_LENGTH)];
return [Cryptography decryptCBCMode:encryptedAttachment key:encryptionKey IV:iv version:nil HMACKey:hmacKey HMACType:TSHMACSHA256AttachementType matchingHMAC:hmac];
return [Cryptography decryptCBCMode:encryptedAttachment
key:encryptionKey
IV:iv version:nil
HMACKey:hmacKey
HMACType:TSHMACSHA256AttachementType
matchingHMAC:hmac];
}
+(NSData*) encryptAttachment:(NSData*) attachment withRandomKey:(NSData**)key{
// generate
// random 10 byte IV
// key: 32 byte AES key || 32 byte Hmac-SHA256 key.
// returns: IV || Ciphertext || truncated MAC(IV||Ciphertext)
NSData* iv = [Cryptography generateRandomBytes:10];
NSData* encryptionKey = [Cryptography generateRandomBytes:32];
NSData* hmacKey = [Cryptography generateRandomBytes:32];
+ (TSAttachmentEncryptionResult*)encryptAttachment:(NSData*)attachment contentType:(NSString*)contentType identifier:(NSString*)identifier {
NSData* iv = [Cryptography generateRandomBytes:AES_CBC_IV_LENGTH];
NSData* encryptionKey = [Cryptography generateRandomBytes:AES_KEY_SIZE];
NSData* hmacKey = [Cryptography generateRandomBytes:HMAC256_KEY_LENGTH];
// The concatenated key for storage
NSMutableData *outKey = [NSMutableData data];
[outKey appendData:encryptionKey];
[outKey appendData:hmacKey];
*key = [NSData dataWithData:outKey];
NSData* computedHMAC;
NSData* ciphertext = [Cryptography encryptCBCMode:attachment withKey:encryptionKey withIV:iv withVersion:nil withHMACKey:hmacKey withHMACType:TSHMACSHA256Truncated10Bytes computedHMAC:&computedHMAC];
NSData* ciphertext = [Cryptography encryptCBCMode:attachment withKey:encryptionKey withIV:iv withVersion:nil withHMACKey:hmacKey withHMACType:TSHMACSHA256AttachementType computedHMAC:&computedHMAC];
NSMutableData* encryptedAttachment = [NSMutableData data];
[encryptedAttachment appendData:iv];
[encryptedAttachment appendData:ciphertext];
[encryptedAttachment appendData:computedHMAC];
return encryptedAttachment;
NSLog(@"Resulting IV: %@ cipherText: %@ hmac: %@", iv, ciphertext, computedHMAC);
TSAttachmentStream *pointer = [[TSAttachmentStream alloc] initWithIdentifier:identifier data:attachment key:outKey contentType:contentType];
return [[TSAttachmentEncryptionResult alloc] initWithPointer:pointer body:encryptedAttachment];
}
@end

View file

@ -0,0 +1,20 @@
//
// TSAttachmentEncryptionResult.h
// Signal
//
// Created by Frederic Jacobs on 21/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "TSAttachmentStream.h"
@interface TSAttachmentEncryptionResult : NSData
@property (readonly) TSAttachmentStream *pointer;
@property (readonly) NSData *body;
- (instancetype)initWithPointer:(TSAttachmentStream*)pointer
body:(NSData*)cipherText;
@end

View file

@ -0,0 +1,25 @@
//
// TSAttachmentEncryptionResult.m
// Signal
//
// Created by Frederic Jacobs on 21/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "TSAttachmentEncryptionResult.h"
@implementation TSAttachmentEncryptionResult
- (instancetype)initWithPointer:(TSAttachmentStream*)pointer
body:(NSData*)cipherText {
self = [super init];
if (self) {
_body = cipherText;
_pointer = pointer;
}
return self;
}
@end

View file

@ -0,0 +1,16 @@
//
// UIImage+contentTypes.h
// Signal
//
// Created by Frederic Jacobs on 21/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIImage (contentTypes)
- (NSString*)contentType;
- (BOOL)isSupportedImageType;
@end

View file

@ -0,0 +1,38 @@
//
// UIImage+contentTypes.m
// Signal
//
// Created by Frederic Jacobs on 21/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "UIImage+contentTypes.h"
@implementation UIImage (contentTypes)
- (NSString*)contentType {
uint8_t c;
[UIImagePNGRepresentation(self) getBytes:&c length:1];
switch (c) {
case 0xFF:
return @"image/jpeg";
case 0x89:
return @"image/png";
case 0x47:
return @"image/gif";
case 0x49:
break;
case 0x42:
return @"image/bmp";
case 0x4D:
return @"image/tiff";
}
return nil;
}
- (BOOL)isSupportedImageType {
return ([self contentType]?YES:NO);
}
@end

View file

@ -17,7 +17,6 @@
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%@",self.navigationController);
[[Environment getCurrent]setSignUpFlowNavigationController:self.navigationController];
}

View file

@ -40,6 +40,7 @@
#import "TSAttachmentAdapter.h"
#import "TSMessagesManager+sendMessages.h"
#import "TSMessagesManager+attachments.h"
#import "NSDate+millisecondTimeStamp.h"
#import "PhoneNumber.h"
@ -614,35 +615,10 @@ typedef enum : NSUInteger {
NSString *mediaType = [info objectForKey: UIImagePickerControllerMediaType];
if (CFStringCompare ((__bridge_retained CFStringRef)mediaType, kUTTypeMovie, 0) == kCFCompareEqualTo) {
//Is a video
NSURL* videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
AVURLAsset *asset1 = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
AVAssetImageGenerator *generate1 = [[AVAssetImageGenerator alloc] initWithAsset:asset1];
generate1.appliesPreferredTrackTransform = YES;
NSError *err = NULL;
CMTime time = CMTimeMake(2, 1);
CGImageRef snapshotRef = [generate1 copyCGImageAtTime:time actualTime:NULL error:&err];
__unused UIImage *snapshot = [[UIImage alloc] initWithCGImage:snapshotRef];
JSQVideoMediaItem * videoItem = [[JSQVideoMediaItem alloc] initWithFileURL:videoURL isReadyToPlay:YES];
JSQMessage * videoMessage = [JSQMessage messageWithSenderId:self.senderId
displayName:self.senderDisplayName
media:videoItem];
self.
[self finishSendingMessage];
DDLogWarn(@"Video formats not supported, yet");
} else if (picture_camera) {
//Is a photo
JSQPhotoMediaItem *photoItem = [[JSQPhotoMediaItem alloc] initWithImage:picture_camera];
JSQMessage *photoMessage = [JSQMessage messageWithSenderId:self.senderId
displayName:self.senderDisplayName
media:photoItem];
[self finishSendingMessage];
DDLogVerbose(@"Sending picture attachement ...");
[[TSMessagesManager sharedManager] sendAttachment:UIImagePNGRepresentation(picture_camera) contentType:@"image/png" thread:self.thread];
}
[self dismissViewControllerAnimated:YES completion:nil];

View file

@ -88,8 +88,7 @@
TSMessage *message = (TSMessage*)interaction;
adapter.messageBody = message.body;
if (message.attachments > 0) {
if ([message.attachments count] > 0) {
for (NSString *attachmentID in message.attachments) {
TSAttachment *attachment = [TSAttachment fetchObjectWithUniqueID:attachmentID];

View file

@ -0,0 +1,43 @@
//
// TSAttachementsTest.m
// Signal
//
// Created by Frederic Jacobs on 21/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <XCTest/XCTest.h>
#import "TSAttachmentStream.h"
#import "Cryptography.h"
@interface TSAttachementsTest : XCTestCase
@end
@implementation TSAttachementsTest
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testAttachementEncryptionDecryption {
NSData *plaintext = [Cryptography generateRandomBytes:100];
NSString *contentType = @"img/jpg";
uint64_t identifier = 3063578577793591963;
NSNumber *number = [NSNumber numberWithUnsignedLongLong:identifier];
TSAttachmentEncryptionResult *encryptionResult = [Cryptography encryptAttachment:plaintext contentType:contentType identifier:[number stringValue]];
NSData *plaintextBis = [Cryptography decryptAttachment:encryptionResult.body withKey:encryptionResult.pointer.encryptionKey];
XCTAssert([plaintext isEqualToData:plaintextBis], @"Attachements encryption failed");
}
@end