Receiving and displaying attachements

This commit is contained in:
Frederic Jacobs 2014-12-18 00:00:10 +01:00
parent 71ad9beeb2
commit 3dc21ba654
28 changed files with 605 additions and 135 deletions

View File

@ -334,8 +334,7 @@
B63AF5CB1A1F757900D01AAD /* TSRegisterPrekeysRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5B51A1F757900D01AAD /* TSRegisterPrekeysRequest.m */; };
B63AF5CC1A1F757900D01AAD /* TSRegisterWithTokenRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5B71A1F757900D01AAD /* TSRegisterWithTokenRequest.m */; };
B63AF5CD1A1F757900D01AAD /* TSRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5B91A1F757900D01AAD /* TSRequest.m */; };
B63AF5CE1A1F757900D01AAD /* TSRequestAttachment.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5BB1A1F757900D01AAD /* TSRequestAttachment.m */; };
B63AF5CF1A1F757900D01AAD /* TSRequestAttachmentId.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5BD1A1F757900D01AAD /* TSRequestAttachmentId.m */; };
B63AF5CE1A1F757900D01AAD /* TSAttachementRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5BB1A1F757900D01AAD /* TSAttachementRequest.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 */; };
@ -349,6 +348,7 @@
B684A46D19C3446200B11029 /* PushManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B684A46C19C3446200B11029 /* PushManagerTest.m */; };
B6850E5A1995A4710068E715 /* whisperFake.cer in Resources */ = {isa = PBXBuildFile; fileRef = B6850E591995A4710068E715 /* whisperFake.cer */; };
B69CD25119773E79005CE69A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B69CD25019773E79005CE69A /* XCTest.framework */; };
B6A3EB4B1A423B3800B2236B /* TSAttachementAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = B6A3EB4A1A423B3800B2236B /* TSAttachementAdapter.m */; };
B6AE33BD1A1EB121003DF39D /* GroupModel.m in Sources */ = {isa = PBXBuildFile; fileRef = B6AE33BC1A1EB121003DF39D /* GroupModel.m */; };
B6B095E41A1D25C5008BFAA6 /* CryptographyTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = B6B095DE1A1D25C5008BFAA6 /* CryptographyTests.mm */; };
B6B095E51A1D25C5008BFAA6 /* TextSecureKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095DF1A1D25C5008BFAA6 /* TextSecureKitTests.m */; };
@ -393,12 +393,15 @@
B6B096941A1D25ED008BFAA6 /* NSString+escape.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B0965E1A1D25ED008BFAA6 /* NSString+escape.m */; };
B6B096951A1D25ED008BFAA6 /* NSURLSessionDataTask+StatusCode.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096601A1D25ED008BFAA6 /* NSURLSessionDataTask+StatusCode.m */; };
B6B1013C196D213F007E3930 /* SignalKeyingStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B1013B196D213F007E3930 /* SignalKeyingStorage.m */; };
B6B50AAB1A4192C500F8F607 /* TSMessagesManager+attachements.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B50AAA1A4192C500F8F607 /* TSMessagesManager+attachements.m */; };
B6B9ECFC198B31BA00C620D3 /* PushManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B9ECFB198B31BA00C620D3 /* PushManager.m */; };
B6C6AE551A305ED1006BAF8F /* redphone.cer in Resources */ = {isa = PBXBuildFile; fileRef = B6C6AE531A305ED1006BAF8F /* redphone.cer */; };
B6C6AE561A305ED1006BAF8F /* textsecure.cer in Resources */ = {isa = PBXBuildFile; fileRef = B6C6AE541A305ED1006BAF8F /* textsecure.cer */; };
B6C93C4E199567AD00EDF894 /* DebugLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = B6C93C4D199567AD00EDF894 /* DebugLogger.m */; };
B6CBF53F1A254BD1000D4184 /* ContactDetailCell.m in Sources */ = {isa = PBXBuildFile; fileRef = B6CBF53E1A254BD1000D4184 /* ContactDetailCell.m */; };
B6E314C91A38FAAF00A41AFB /* TSFingerprintGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = B6E314C81A38FAAF00A41AFB /* TSFingerprintGenerator.m */; };
B6FAAAE81A41BC6C007FEC1D /* TSAttachementPointer.m in Sources */ = {isa = PBXBuildFile; fileRef = B6FAAAE71A41BC6C007FEC1D /* TSAttachementPointer.m */; };
B6FAAAEE1A41C918007FEC1D /* TSAttachementStream.m in Sources */ = {isa = PBXBuildFile; fileRef = B6FAAAED1A41C918007FEC1D /* TSAttachementStream.m */; };
B90418E6183E9DD40038554A /* DateUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B90418E5183E9DD40038554A /* DateUtil.m */; };
B90418E7183E9DD40038554A /* DateUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B90418E5183E9DD40038554A /* DateUtil.m */; };
B96A3100187DA1B600648F3E /* HelveticaNeueLTStd-Bd.otf in Resources */ = {isa = PBXBuildFile; fileRef = B96A30FE187DA1B600648F3E /* HelveticaNeueLTStd-Bd.otf */; };
@ -941,10 +944,8 @@
B63AF5B71A1F757900D01AAD /* TSRegisterWithTokenRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSRegisterWithTokenRequest.m; sourceTree = "<group>"; };
B63AF5B81A1F757900D01AAD /* TSRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSRequest.h; sourceTree = "<group>"; };
B63AF5B91A1F757900D01AAD /* TSRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSRequest.m; sourceTree = "<group>"; };
B63AF5BA1A1F757900D01AAD /* TSRequestAttachment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSRequestAttachment.h; sourceTree = "<group>"; };
B63AF5BB1A1F757900D01AAD /* TSRequestAttachment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSRequestAttachment.m; sourceTree = "<group>"; };
B63AF5BC1A1F757900D01AAD /* TSRequestAttachmentId.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSRequestAttachmentId.h; sourceTree = "<group>"; };
B63AF5BD1A1F757900D01AAD /* TSRequestAttachmentId.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSRequestAttachmentId.m; sourceTree = "<group>"; };
B63AF5BA1A1F757900D01AAD /* TSAttachementRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSAttachementRequest.h; sourceTree = "<group>"; };
B63AF5BB1A1F757900D01AAD /* TSAttachementRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachementRequest.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>"; };
@ -967,6 +968,8 @@
B684A46C19C3446200B11029 /* PushManagerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PushManagerTest.m; path = Signal/test/push/PushManagerTest.m; sourceTree = SOURCE_ROOT; };
B6850E591995A4710068E715 /* whisperFake.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = whisperFake.cer; sourceTree = "<group>"; };
B69CD25019773E79005CE69A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
B6A3EB491A423B3800B2236B /* TSAttachementAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSAttachementAdapter.h; sourceTree = "<group>"; };
B6A3EB4A1A423B3800B2236B /* TSAttachementAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachementAdapter.m; sourceTree = "<group>"; };
B6AE33BB1A1EB121003DF39D /* GroupModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GroupModel.h; sourceTree = "<group>"; };
B6AE33BC1A1EB121003DF39D /* GroupModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GroupModel.m; sourceTree = "<group>"; };
B6B095DE1A1D25C5008BFAA6 /* CryptographyTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CryptographyTests.mm; sourceTree = "<group>"; };
@ -1051,6 +1054,8 @@
B6B096601A1D25ED008BFAA6 /* NSURLSessionDataTask+StatusCode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURLSessionDataTask+StatusCode.m"; sourceTree = "<group>"; };
B6B1013A196D213F007E3930 /* SignalKeyingStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SignalKeyingStorage.h; sourceTree = "<group>"; };
B6B1013B196D213F007E3930 /* SignalKeyingStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalKeyingStorage.m; sourceTree = "<group>"; };
B6B50AA91A4192C500F8F607 /* TSMessagesManager+attachements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TSMessagesManager+attachements.h"; sourceTree = "<group>"; };
B6B50AAA1A4192C500F8F607 /* TSMessagesManager+attachements.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TSMessagesManager+attachements.m"; sourceTree = "<group>"; };
B6B9ECFA198B31BA00C620D3 /* PushManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PushManager.h; sourceTree = "<group>"; };
B6B9ECFB198B31BA00C620D3 /* PushManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PushManager.m; sourceTree = "<group>"; };
B6C6AE531A305ED1006BAF8F /* redphone.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = redphone.cer; sourceTree = "<group>"; };
@ -1061,6 +1066,10 @@
B6CBF53E1A254BD1000D4184 /* ContactDetailCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ContactDetailCell.m; path = "Signal/src/view controllers/ContactDetailCell.m"; sourceTree = SOURCE_ROOT; };
B6E314C71A38FAAF00A41AFB /* TSFingerprintGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSFingerprintGenerator.h; sourceTree = "<group>"; };
B6E314C81A38FAAF00A41AFB /* TSFingerprintGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSFingerprintGenerator.m; sourceTree = "<group>"; };
B6FAAAE61A41BC6C007FEC1D /* TSAttachementPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSAttachementPointer.h; path = Attachements/TSAttachementPointer.h; sourceTree = "<group>"; };
B6FAAAE71A41BC6C007FEC1D /* TSAttachementPointer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSAttachementPointer.m; path = Attachements/TSAttachementPointer.m; sourceTree = "<group>"; };
B6FAAAEC1A41C918007FEC1D /* TSAttachementStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSAttachementStream.h; path = Attachements/TSAttachementStream.h; sourceTree = "<group>"; };
B6FAAAED1A41C918007FEC1D /* TSAttachementStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSAttachementStream.m; path = Attachements/TSAttachementStream.m; sourceTree = "<group>"; };
B90418E4183E9DD40038554A /* DateUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DateUtil.h; sourceTree = "<group>"; };
B90418E5183E9DD40038554A /* DateUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DateUtil.m; sourceTree = "<group>"; };
B96A30FE187DA1B600648F3E /* HelveticaNeueLTStd-Bd.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "HelveticaNeueLTStd-Bd.otf"; sourceTree = "<group>"; };
@ -2112,6 +2121,8 @@
B62D53F41A23CC8B009AAF82 /* TSMessageAdapters */ = {
isa = PBXGroup;
children = (
B6A3EB491A423B3800B2236B /* TSAttachementAdapter.h */,
B6A3EB4A1A423B3800B2236B /* TSAttachementAdapter.m */,
B62D53F51A23CCAD009AAF82 /* TSMessageAdapter.h */,
B62D53F61A23CCAD009AAF82 /* TSMessageAdapter.m */,
);
@ -2219,10 +2230,8 @@
B63AF5B71A1F757900D01AAD /* TSRegisterWithTokenRequest.m */,
B63AF5B81A1F757900D01AAD /* TSRequest.h */,
B63AF5B91A1F757900D01AAD /* TSRequest.m */,
B63AF5BA1A1F757900D01AAD /* TSRequestAttachment.h */,
B63AF5BB1A1F757900D01AAD /* TSRequestAttachment.m */,
B63AF5BC1A1F757900D01AAD /* TSRequestAttachmentId.h */,
B63AF5BD1A1F757900D01AAD /* TSRequestAttachmentId.m */,
B63AF5BA1A1F757900D01AAD /* TSAttachementRequest.h */,
B63AF5BB1A1F757900D01AAD /* TSAttachementRequest.m */,
B63AF5BE1A1F757900D01AAD /* TSSubmitMessageRequest.h */,
B63AF5BF1A1F757900D01AAD /* TSSubmitMessageRequest.m */,
B63AF5C01A1F757900D01AAD /* TSUploadAttachment.h */,
@ -2336,10 +2345,9 @@
B6B096001A1D25ED008BFAA6 /* Messages */ = {
isa = PBXGroup;
children = (
B6FAAAE91A41C7CC007FEC1D /* Attachement */,
B6B096011A1D25ED008BFAA6 /* IncomingPushMessageSignal.pb.h */,
B6B096021A1D25ED008BFAA6 /* IncomingPushMessageSignal.pb.m */,
B6B096031A1D25ED008BFAA6 /* TSAttachement.h */,
B6B096041A1D25ED008BFAA6 /* TSAttachement.m */,
B6B096051A1D25ED008BFAA6 /* TSCall.h */,
B6B096061A1D25ED008BFAA6 /* TSCall.m */,
B6B096071A1D25ED008BFAA6 /* TSErrorMessage.h */,
@ -2360,6 +2368,8 @@
B6B096141A1D25ED008BFAA6 /* TSMessagesManager+sendMessages.m */,
B6B096151A1D25ED008BFAA6 /* TSMessagesManager.h */,
B6B096161A1D25ED008BFAA6 /* TSMessagesManager.m */,
B6B50AA91A4192C500F8F607 /* TSMessagesManager+attachements.h */,
B6B50AAA1A4192C500F8F607 /* TSMessagesManager+attachements.m */,
B6B096171A1D25ED008BFAA6 /* TSOutgoingMessage.h */,
B6B096181A1D25ED008BFAA6 /* TSOutgoingMessage.m */,
B6B096191A1D25ED008BFAA6 /* TSServerMessage.h */,
@ -2451,6 +2461,19 @@
path = Certificates;
sourceTree = "<group>";
};
B6FAAAE91A41C7CC007FEC1D /* Attachement */ = {
isa = PBXGroup;
children = (
B6B096031A1D25ED008BFAA6 /* TSAttachement.h */,
B6B096041A1D25ED008BFAA6 /* TSAttachement.m */,
B6FAAAEC1A41C918007FEC1D /* TSAttachementStream.h */,
B6FAAAED1A41C918007FEC1D /* TSAttachementStream.m */,
B6FAAAE61A41BC6C007FEC1D /* TSAttachementPointer.h */,
B6FAAAE71A41BC6C007FEC1D /* TSAttachementPointer.m */,
);
name = Attachement;
sourceTree = "<group>";
};
BF8C3D8119CE3B6A008F644C /* call */ = {
isa = PBXGroup;
children = (
@ -3104,6 +3127,7 @@
76EB063C18170B33006006FC /* NumberUtil.m in Sources */,
B6B096691A1D25ED008BFAA6 /* TSThread.m in Sources */,
B6B096641A1D25ED008BFAA6 /* TSContactThread.m in Sources */,
B6A3EB4B1A423B3800B2236B /* TSAttachementAdapter.m in Sources */,
76EB063A18170B33006006FC /* FunctionalUtil.m in Sources */,
76EB060A18170B33006006FC /* SignalUtil.m in Sources */,
76EB062818170B33006006FC /* BadArgument.m in Sources */,
@ -3142,10 +3166,11 @@
76EB05DA18170B33006006FC /* LowLatencyConnector.m in Sources */,
76EB05EE18170B33006006FC /* CallTermination.m in Sources */,
E1CD329618BCFF9900B1A496 /* SoundInstance.m in Sources */,
B6FAAAEE1A41C918007FEC1D /* TSAttachementStream.m in Sources */,
76EB05B418170B33006006FC /* HashChain.m in Sources */,
76EB05E418170B33006006FC /* UdpSocket.m in Sources */,
B6B096931A1D25ED008BFAA6 /* NSData+messagePadding.m in Sources */,
B63AF5CE1A1F757900D01AAD /* TSRequestAttachment.m in Sources */,
B63AF5CE1A1F757900D01AAD /* TSAttachementRequest.m in Sources */,
76EB058218170B33006006FC /* Environment.m in Sources */,
76EB064418170B33006006FC /* ThreadManager.m in Sources */,
E197B61E18BBEC6D00F073E5 /* AudioRouter.m in Sources */,
@ -3201,7 +3226,9 @@
7038632718F70C0700D4A43F /* CryptoTools.m in Sources */,
76EB058C18170B33006006FC /* DnsManager.m in Sources */,
B63AF5CB1A1F757900D01AAD /* TSRegisterPrekeysRequest.m in Sources */,
B6FAAAE81A41BC6C007FEC1D /* TSAttachementPointer.m in Sources */,
B6B096881A1D25ED008BFAA6 /* TSStorageManager+keyFromIntLong.m in Sources */,
B6B50AAB1A4192C500F8F607 /* TSMessagesManager+attachements.m in Sources */,
76EB059018170B33006006FC /* IgnoredPacketFailure.m in Sources */,
765052AF182AC9B5008313E1 /* DialerButtonView.m in Sources */,
76EB05D418170B33006006FC /* ZrtpManager.m in Sources */,
@ -3273,7 +3300,6 @@
76EB05AE18170B33006006FC /* SrtpStream.m in Sources */,
B6B096711A1D25ED008BFAA6 /* TSInteraction.m in Sources */,
B6B0966D1A1D25ED008BFAA6 /* TSErrorMessage.m in Sources */,
B63AF5CF1A1F757900D01AAD /* TSRequestAttachmentId.m in Sources */,
E197B61318BBEC1A00F073E5 /* DesiredBufferDepthController.m in Sources */,
76EB064818170B33006006FC /* Zid.m in Sources */,
B6B096741A1D25ED008BFAA6 /* TSMessagesManager.m in Sources */,

View File

@ -0,0 +1,22 @@
//
// TSAttachementPointer.h
// Signal
//
// Created by Frederic Jacobs on 17/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "TSAttachement.h"
@interface TSAttachementPointer : TSAttachement
- (instancetype)initWithIdentifier:(uint64_t)identifier
key:(NSData*)key
contentType:(NSString*)contentType
relay:(NSString*)relay;
@property NSString *relay;
@end

View File

@ -0,0 +1,32 @@
//
// TSAttachementPointer.m
// Signal
//
// Created by Frederic Jacobs on 17/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "TSAttachementPointer.h"
@implementation TSAttachementPointer
- (instancetype)initWithIdentifier:(uint64_t)identifier
key:(NSData*)key
contentType:(NSString*)contentType
relay:(NSString*)relay
{
self = [super initWithIdentifier:[[NSNumber numberWithUnsignedLongLong:identifier] stringValue] encryptionKey:key contentType:contentType];
if (self) {
self.relay = relay;
}
return self;
}
- (BOOL)isDownloaded{
return NO;
}
@end

View File

@ -0,0 +1,25 @@
//
// TSAttachementStream.h
// Signal
//
// Created by Frederic Jacobs on 17/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "TSAttachement.h"
@interface TSAttachementStream : TSAttachement
- (instancetype)initWithIdentifier:(NSString*)identifier
data:(NSData*)data
key:(NSData*)key
contentType:(NSString*)contentType;
- (NSString*)path;
- (BOOL)isImage;
- (UIImage*)image;
- (BOOL)isVideo;
@end

View File

@ -0,0 +1,73 @@
//
// TSAttachementStream.m
// Signal
//
// Created by Frederic Jacobs on 17/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "TSAttachementStream.h"
@interface TSAttachementStream ()
@property (nonatomic) NSString *path;
@end
@implementation TSAttachementStream
- (instancetype)initWithIdentifier:(NSString*)identifier
data:(NSData*)data
key:(NSData*)key
contentType:(NSString*)contentType{
self = [super initWithIdentifier:identifier encryptionKey:key contentType:contentType];
NSString *path = [self filePath];
[[NSFileManager defaultManager] createFileAtPath:path contents:data attributes:nil];
return self;
}
- (BOOL)isDownloaded{
return YES;
}
+ (NSString*)attachmentsFolder {
NSFileManager* fileManager = [NSFileManager defaultManager];
NSURL *fileURL = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSString *path = [fileURL path];
NSString *attachementFolder = [path stringByAppendingFormat:@"/Attachements"];
NSError * error = nil;
[[NSFileManager defaultManager] createDirectoryAtPath:attachementFolder
withIntermediateDirectories:YES
attributes:nil
error:&error];
if (error != nil) {
DDLogError(@"Failed to create attachments directory: %@", error.description);
}
return attachementFolder;
}
- (NSString*)filePath {
return [[[self class] attachmentsFolder] stringByAppendingFormat:@"/%@", self.uniqueId];
}
- (BOOL)isImage{
if ([self.contentType containsString:@"image/"]) {
return YES;
} else{
return NO;
}
}
- (UIImage*)image{
if (![self isImage]) {
return nil;
}
return [UIImage imageWithContentsOfFile:[self filePath]];
}
@end

View File

@ -9,19 +9,18 @@
#import <Foundation/Foundation.h>
#import "TSYapDatabaseObject.h"
/**
* TSAttachements are stored by attachement id;
*/
@interface TSAttachement : TSYapDatabaseObject
- (NSNumber*)identifier;
- (BOOL)isDownloaded;
@property (nonatomic, readonly) NSData *encryptionKey;
@property (nonatomic, readonly) NSString *contentType;
@property (nonatomic, readonly) NSURL *url;
@property (nonatomic, readonly) NSData *encryptionKey;
- (BOOL)expired;
- (NSString*)attachementId;
- (instancetype)initWithIdentifier:(NSString*)identifier
encryptionKey:(NSData*)encryptionKey
contentType:(NSString*)contentType;
- (instancetype)initWithAttachementId:(NSString*)attachementId url:(NSURL*)url encryptionKey:(NSData*)encryptionKey;
@end

View File

@ -1,3 +1,4 @@
//
// TSAttachement.m
// TextSecureKit
@ -10,4 +11,31 @@
@implementation TSAttachement
- (instancetype)initWithIdentifier:(NSString*)identifier
encryptionKey:(NSData*)encryptionKey
contentType:(NSString*)contentType {
self = [super initWithUniqueId:identifier];
if (self) {
_encryptionKey = encryptionKey;
_contentType = contentType;
}
return self;
}
+ (NSString *)collection{
return @"TSAttachements";
}
- (NSNumber*)identifier{
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
return [f numberFromString:self.uniqueId];
}
- (BOOL)isDownloaded{
return NO;
}
@end

View File

@ -15,14 +15,16 @@
@interface TSMessage : TSInteraction
@property (nonatomic, readonly) NSArray *attachements;// contains TSAttachements
@property (nonatomic, readonly) NSString *body;
@property (nonatomic, readonly) NSMutableArray *attachements;
@property (nonatomic, readonly) NSString *body;
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(TSThread*)thread
messageBody:(NSString*)body
attachements:(NSArray*)attachements;
- (void)addAttachements:(NSArray*)attachements;
- (void)addAttachement:(NSString*)attachement;
- (BOOL)hasAttachements;
@end

View File

@ -11,6 +11,20 @@
@implementation TSMessage
- (void)addAttachements:(NSArray*)attachements {
for (NSString *identifier in attachements) {
[self addAttachement:identifier];
}
}
- (void)addAttachement:(NSString*)attachement {
if (!_attachements) {
_attachements = [NSMutableArray array];
}
[self.attachements addObject:attachement];
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(TSThread*)thread
messageBody:(NSString*)body
@ -20,7 +34,7 @@
if (self) {
_body = body;
_attachements = attachements;
_attachements = [attachements mutableCopy];
}
return self;
}
@ -30,7 +44,11 @@
}
- (NSString *)description{
return self.body;
if(self.attachements > 0){
return @"Attachement";
} else {
return self.body;
}
}
@end

View File

@ -0,0 +1,17 @@
//
// TSMessagesManager+attachements.h
// Signal
//
// Created by Frederic Jacobs on 17/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "TSMessagesManager.h"
#import "TSAttachement.h"
@interface TSMessagesManager (attachements)
- (void)handleReceivedMediaMessage:(IncomingPushMessageSignal*)message withContent:(PushMessageContent*)content;
- (void)retrieveAttachment:(TSAttachement*)attachement;
@end

View File

@ -0,0 +1,116 @@
//
// TSMessagesManager+attachements.m
// Signal
//
// Created by Frederic Jacobs on 17/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "NSDate+millisecondTimeStamp.h"
#import <YapDatabase/YapDatabaseConnection.h>
#import "Cryptography.h"
#import "TSConstants.h"
#import "TSMessagesManager+attachements.h"
#import "TSAttachementRequest.h"
#import "TSUploadAttachment.h"
#import "TSInfoMessage.h"
#import "TSAttachementPointer.h"
#import "TSNetworkManager.h"
@interface TSMessagesManager ()
dispatch_queue_t attachementsQueue(void);
@end
dispatch_queue_t attachementsQueue() {
static dispatch_once_t queueCreationGuard;
static dispatch_queue_t queue;
dispatch_once(&queueCreationGuard, ^{
queue = dispatch_queue_create("org.whispersystems.signal.attachements", NULL);
});
return queue;
}
@implementation TSMessagesManager (attachements)
- (void)handleReceivedMediaMessage:(IncomingPushMessageSignal*)message withContent:(PushMessageContent*)content {
NSMutableArray *attachements = [NSMutableArray array];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
for (PushMessageContentAttachmentPointer *pointer in content.attachments) {
TSAttachementPointer *attachementPointer = [[TSAttachementPointer alloc] initWithIdentifier:pointer.id key:pointer.key contentType:pointer.contentType relay:message.relay];
[attachementPointer saveWithTransaction:transaction];
dispatch_async(attachementsQueue(), ^{
[self retrieveAttachment:attachementPointer];
});
[attachements addObject:attachementPointer.uniqueId];
}
}];
[self handleReceivedMessage:message withContent:content attachements:attachements];
}
- (void)retrieveAttachment:(TSAttachementPointer*)attachement {
TSAttachementRequest *attachementRequest = [[TSAttachementRequest alloc] initWithId:[attachement identifier]
relay:attachement.relay];
[[TSNetworkManager sharedManager] queueAuthenticatedRequest:attachementRequest success:^(NSURLSessionDataTask *task, id responseObject) {
if ([responseObject isKindOfClass:[NSDictionary class]]) {
NSString *location = [(NSDictionary*)responseObject objectForKey:@"location"];
NSData *data = [self downloadFromLocation:location];
if (data) {
dispatch_async(attachementsQueue(), ^{
[self decryptedAndSaveAttachement:attachement data:data];
});
}
}
} failure:^(NSURLSessionDataTask *task, NSError *error) {
DDLogError(@"Failed task %@ error: %@", task.description, error.description);
}];
}
- (NSData*)downloadFromLocation:(NSString*)location {
__block NSData *data;
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.completionQueue = attachementsQueue();
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
[manager.requestSerializer setValue:@"application/octet-stream" forHTTPHeaderField:@"Content-Type"];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[manager GET:location parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
data = responseObject;
dispatch_semaphore_signal(sema);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
DDLogError(@"Failed to retreive attachment with error: %@", error.description);
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
return data;
}
- (void)decryptedAndSaveAttachement:(TSAttachementPointer*)attachement data:(NSData*)cipherText {
NSData *plaintext = [Cryptography decryptAttachment:cipherText withKey:attachement.encryptionKey];
if (!plaintext) {
DDLogError(@"Failed to get attachement decrypted ...");
} else {
TSAttachementStream *stream = [[TSAttachementStream alloc] initWithIdentifier:attachement.uniqueId
data:plaintext key:attachement.encryptionKey
contentType:attachement.contentType];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
[stream saveWithTransaction:transaction];
}];
NSLog(@"We got %@ of type %@", plaintext, attachement.contentType);
}
}
@end

View File

@ -8,6 +8,7 @@
#import <Foundation/Foundation.h>
#import "IncomingPushMessageSignal.pb.h"
#import "TSIncomingMessage.h"
#import "TSOutgoingMessage.h"
@interface TSMessagesManager : NSObject
@ -20,4 +21,6 @@
- (void)processException:(NSException*)exception outgoingMessage:(TSOutgoingMessage*)message;
- (void)handleReceivedMessage:(IncomingPushMessageSignal*)message withContent:(PushMessageContent*)content attachements:(NSArray*)attachements;
@end

View File

@ -28,6 +28,7 @@
#import "TSStorageManager+PreKeyStore.h"
#import "TSNetworkManager.h"
#import "TSSubmitMessageRequest.h"
#import "TSMessagesManager+attachements.h"
#import "NSData+messagePadding.h"
@ -184,13 +185,6 @@
} else if (content.attachments.count > 0) {
DDLogVerbose(@"Received push media message (attachement) ...");
[self handleReceivedMediaMessage:incomingMessage withContent:content];
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
TSInfoMessage *message = [[TSInfoMessage alloc] initWithTimestamp:incomingMessage.timestamp
inThread:[TSContactThread threadWithContactId:incomingMessage.source transaction:transaction]
messageType:TSInfoMessageTypeUnsupportedMessage];
[message saveWithTransaction:transaction];
}];
} else {
DDLogVerbose(@"Received push text message...");
[self handleReceivedTextMessage:incomingMessage withContent:content];
@ -214,11 +208,11 @@
// TO DO
}
- (void)handleReceivedMediaMessage:(IncomingPushMessageSignal*)message withContent:(PushMessageContent*)content{
// TO DO
- (void)handleReceivedTextMessage:(IncomingPushMessageSignal*)message withContent:(PushMessageContent*)content{
[self handleReceivedMessage:message withContent:content attachements:nil];
}
- (void)handleReceivedTextMessage:(IncomingPushMessageSignal*)message withContent:(PushMessageContent*)content{
- (void)handleReceivedMessage:(IncomingPushMessageSignal*)message withContent:(PushMessageContent*)content attachements:(NSArray*)attachements {
uint64_t timeStamp = message.timestamp;
NSString *body = content.body;
NSData *groupId = content.hasGroup?content.group.id:nil;
@ -229,12 +223,12 @@
if (groupId) {
TSGroupThread *gThread = [TSGroupThread threadWithGroupId:groupId];
[gThread saveWithTransaction:transaction];
incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:timeStamp inThread:gThread authorId:message.source messageBody:body attachements:nil];
incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:timeStamp inThread:gThread authorId:message.source messageBody:body attachements:attachements];
thread = gThread;
} else{
TSContactThread *cThread = [TSContactThread threadWithContactId:message.source transaction:transaction];
[cThread saveWithTransaction:transaction];
incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:timeStamp inThread:cThread messageBody:body attachements:nil];
incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:timeStamp inThread:cThread messageBody:body attachements:attachements];
thread = cThread;
}
[incomingMessage saveWithTransaction:transaction];

View File

@ -13,7 +13,7 @@
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(TSThread *)thread
messageBody:(NSString *)body
attachements:(NSArray *)attachements
attachements:(NSMutableArray*)attachements
{
self = [super initWithTimestamp:timestamp inThread:thread
messageBody:body attachements:attachements];

View File

@ -8,6 +8,8 @@
#import "TSRequest.h"
@interface TSRequestAttachment : TSRequest
-(TSRequest*) initWithId:(NSNumber*) attachmentId;
@interface TSAttachementRequest : TSRequest
-(TSRequest*) initWithId:(NSNumber*) attachmentId relay:(NSString*)relay;
@end

View File

@ -0,0 +1,28 @@
//
// TSRequestAttachment.m
// TextSecureiOS
//
// Created by Christine Corbett Moran on 12/1/13.
// Copyright (c) 2013 Open Whisper Systems. All rights reserved.
//
#import "TSAttachementRequest.h"
#import "TSConstants.h"
@implementation TSAttachementRequest
-(TSRequest*) initWithId:(NSNumber*) attachmentId relay:(NSString*)relay {
NSString *path = [NSString stringWithFormat:@"%@/%@", textSecureAttachmentsAPI, attachmentId];
if (relay && ![relay isEqualToString:@""]) {
path = [path stringByAppendingFormat:@"?relay=%@", relay];
}
self = [super initWithURL:[NSURL URLWithString:path]];
self.HTTPMethod = @"GET";
return self;
}
@end

View File

@ -1,20 +0,0 @@
//
// TSRequestAttachment.m
// TextSecureiOS
//
// Created by Christine Corbett Moran on 12/1/13.
// Copyright (c) 2013 Open Whisper Systems. All rights reserved.
//
#import "TSRequestAttachment.h"
#import "Constants.h"
@implementation TSRequestAttachment
-(TSRequest*) initWithId:(NSNumber*) attachmentId {
//self = [super initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/%@",textSecureAttachmentsAPI,attachmentId]]];
self.HTTPMethod = @"GET";
return self;
}
@end

View File

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

View File

@ -1,20 +0,0 @@
//
// TSRequestAttachmentId.m
// TextSecureiOS
//
// Created by Christine Corbett Moran on 12/1/13.
// Copyright (c) 2013 Open Whisper Systems. All rights reserved.
//
#import "TSConstants.h"
#import "TSRequestAttachmentId.h"
@implementation TSRequestAttachmentId
-(TSRequest*) init {
self = [super initWithURL:[NSURL URLWithString:textSecureAttachmentsAPI]];
self.HTTPMethod = @"GET";
return self;
}
@end

View File

@ -7,9 +7,10 @@
//
#import "TSRequest.h"
@class TSAttachment;
#import "TSAttachementStream.h"
@interface TSUploadAttachment : TSRequest
@property(nonatomic,strong) TSAttachment* attachment;
-(TSRequest*) initWithAttachment:(TSAttachment*) attachment ;
-(TSRequest*) initWithAttachment:(TSAttachementStream*)attachment;
@end

View File

@ -7,11 +7,17 @@
//
#import "TSUploadAttachment.h"
#import "TSAttachementStream.h"
#import <AFNetworking/AFHTTPRequestOperation.h>
@interface TSUploadAttachment ()
@property(nonatomic,strong) TSAttachement* attachment;
@end
@implementation TSUploadAttachment
//-(TSRequest*) initWithAttachment:(TSAttachment*) attachment{
//
-(TSRequest*) initWithAttachment:(TSAttachementStream*)attachment{
// self = [super initWithURL:attachment.attachmentURL];
// self.HTTPMethod = @"PUT";
// self.attachment = attachment;
@ -20,14 +26,7 @@
// [self setAllHTTPHeaderFields: @{@"Content-Type": @"application/octet-stream"}];
//
// return self;
//
//}
}
@end

View File

@ -69,7 +69,7 @@
[self.operationManager.requestSerializer setAuthorizationHeaderFieldWithUsername:[TSAccountManager registeredNumber] password:[TSStorageManager serverAuthToken]];
if ([request.HTTPMethod isEqualToString:@"GET"]) {
if ([request.HTTPMethod isEqualToString:@"GET"]) {
[self.operationManager GET:[textSecureServerURL stringByAppendingString:request.URL.absoluteString] parameters:request.parameters success:success failure:failure];
} else if ([request.HTTPMethod isEqualToString:@"POST"]){
[self.operationManager POST:[textSecureServerURL stringByAppendingString:request.URL.absoluteString] parameters:request.parameters success:success failure:failure];

View File

@ -12,7 +12,8 @@
typedef NS_ENUM(NSInteger, TSMACType) {
TSHMACSHA1Truncated10Bytes = 1,
TSHMACSHA256Truncated10Bytes = 2
TSHMACSHA256Truncated10Bytes = 2,
TSHMACSHA256AttachementType = 3
};
+(NSMutableData*) generateRandomBytes:(int)numberBytes;

View File

@ -14,6 +14,10 @@
#include "NSData+Base64.h"
#define HMAC256_KEY_LENGTH 32
#define HMAC256_OUTPUT_LENGTH 32
#define AES_CBC_IV_LENGTH 16
#define AES_KEY_SIZE 32
@implementation Cryptography
@ -163,9 +167,10 @@
*/
//verify hmac of version||encrypted data||iv
NSMutableData *dataToHmac = [NSMutableData data ];
if(version!=nil) {
if(version != nil) {
[dataToHmac appendData:version];
}
[dataToHmac appendData:iv];
[dataToHmac appendData:dataToDecrypt];
@ -173,20 +178,22 @@
if(hmacType == TSHMACSHA1Truncated10Bytes) {
ourHmacData = [Cryptography truncatedSHA1HMAC:dataToHmac withHMACKey:hmacKey truncation:10];
}
else if (hmacType == TSHMACSHA256Truncated10Bytes) {
} else if (hmacType == TSHMACSHA256Truncated10Bytes) {
ourHmacData = [Cryptography truncatedSHA256HMAC:dataToHmac withHMACKey:hmacKey truncation:10];
} else if (hmacType == TSHMACSHA256AttachementType){
ourHmacData = [Cryptography truncatedSHA256HMAC:dataToHmac withHMACKey:hmacKey truncation:HMAC256_OUTPUT_LENGTH];
}
if(hmac == nil || ![ourHmacData isEqualToData:hmac] ) {
DDLogError(@"Bad HMAC on decrypting payload");
return nil;
}
// decrypt
size_t bufferSize = [dataToDecrypt length] + kCCBlockSizeAES128;
void* buffer = malloc(bufferSize);
size_t bytesDecrypted = 0;
size_t bytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
[key bytes], [key length],
[iv bytes],
@ -195,9 +202,11 @@
&bytesDecrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:bytesDecrypted];
} else{
DDLogError(@"Failed CBC decryption");
free(buffer);
}
free(buffer);
return nil;
}
@ -232,14 +241,20 @@
}
+(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;
}
// key: 32 byte AES key || 32 byte Hmac-SHA256 key.
NSData *encryptionKey = [key subdataWithRange:NSMakeRange(0, 32)];
NSData *hmacKey = [key subdataWithRange:NSMakeRange(32, 32)];
NSData *encryptionKey = [key subdataWithRange:NSMakeRange(0, AES_KEY_SIZE)];
NSData *hmacKey = [key subdataWithRange:NSMakeRange(AES_KEY_SIZE, HMAC256_KEY_LENGTH)];
// dataToDecrypt: IV || Ciphertext || truncated MAC(IV||Ciphertext)
NSData *iv = [dataToDecrypt subdataWithRange:NSMakeRange(0, 10)];
NSData *encryptedAttachment = [dataToDecrypt subdataWithRange:NSMakeRange(10, [dataToDecrypt length]-10-10)];
NSData *hmac = [dataToDecrypt subdataWithRange:NSMakeRange([dataToDecrypt length]-10, 10)];
return [Cryptography decryptCBCMode:encryptedAttachment key:encryptionKey IV:iv version:nil HMACKey:hmacKey HMACType:TSHMACSHA256Truncated10Bytes matchingHMAC:hmac];
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];
}

View File

@ -37,6 +37,7 @@
#import "TSErrorMessage.h"
#import "TSIncomingMessage.h"
#import "TSInteraction.h"
#import "TSAttachementAdapter.h"
#import "TSMessagesManager+sendMessages.h"
#import "NSDate+millisecondTimeStamp.h"
@ -288,7 +289,7 @@ typedef enum : NSUInteger {
case TSErrorMessageAdapter:
return [self loadErrorMessageCellForMessage:msg atIndexPath:indexPath];
break;
default:
NSLog(@"Something went wrong");
return nil;
@ -467,15 +468,15 @@ typedef enum : NSUInteger {
BOOL isMediaMessage = [messageItem isMediaMessage];
if (isMediaMessage) {
id<JSQMessageMediaData> messageMedia = [messageItem media];
TSAttachementAdapter * messageMedia = (TSAttachementAdapter*)[messageItem media];
if ([messageMedia isKindOfClass:JSQPhotoMediaItem.class]) {
if ([messageMedia isImage]) {
//is a photo
tappedImage = ((JSQPhotoMediaItem*)messageMedia).image ;
tappedImage = ((UIImageView*)[messageMedia mediaView]).image ;
[self performSegueWithIdentifier:@"fullImage" sender:self];
} else if ([messageMedia isKindOfClass:JSQVideoMediaItem.class]) {
//is a video
} else {
DDLogWarn(@"Currently unsupported");
}
}

View File

@ -0,0 +1,19 @@
//
// TSAttachementAdapter.h
// Signal
//
// Created by Frederic Jacobs on 17/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <JSQMessagesViewController/JSQMediaItem.h>
#import "TSAttachementStream.h"
#import <Foundation/Foundation.h>
@interface TSAttachementAdapter : JSQMediaItem
- (instancetype)initWithAttachement:(TSAttachementStream*)attachement;
- (BOOL)isImage;
@end

View File

@ -0,0 +1,74 @@
//
// TSAttachementAdapter.m
// Signal
//
// Created by Frederic Jacobs on 17/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "TSAttachementAdapter.h"
#import "JSQMessagesMediaViewBubbleImageMasker.h"
@interface TSAttachementAdapter ()
@property UIImage *image;
@property (strong, nonatomic) UIImageView *cachedImageView;
@property (assign, nonatomic, readonly) BOOL isImageAttachment;
@end
@implementation TSAttachementAdapter
- (instancetype)initWithAttachement:(TSAttachementStream*)attachement{
self = [super init];
if (self) {
_image = [UIImage imageWithCGImage:attachement.image.CGImage];
_cachedImageView = nil;
_isImageAttachment = YES;
}
return self;
}
- (void)dealloc
{
_image = nil;
_cachedImageView = nil;
}
- (void)setAppliesMediaViewMaskAsOutgoing:(BOOL)appliesMediaViewMaskAsOutgoing
{
[super setAppliesMediaViewMaskAsOutgoing:appliesMediaViewMaskAsOutgoing];
_cachedImageView = nil;
}
#pragma mark - JSQMessageMediaData protocol
- (UIView *)mediaView
{
if (self.image == nil) {
return nil;
}
if (self.cachedImageView == nil) {
CGSize size = [self mediaViewDisplaySize];
UIImageView *imageView = [[UIImageView alloc] initWithImage:self.image];
imageView.frame = CGRectMake(0.0f, 0.0f, size.width, size.height);
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.clipsToBounds = YES;
[JSQMessagesMediaViewBubbleImageMasker applyBubbleImageMaskToMediaView:imageView isOutgoing:self.appliesMediaViewMaskAsOutgoing];
self.cachedImageView = imageView;
}
return self.cachedImageView;
}
-(BOOL)isImage
{
return _isImageAttachment;
}
@end

View File

@ -12,6 +12,9 @@
#import "TSCall.h"
#import "TSInfoMessage.h"
#import "TSErrorMessage.h"
#import "TSAttachement.h"
#import "TSAttachementStream.h"
#import "TSAttachementAdapter.h"
@interface TSMessageAdapter ()
@ -36,6 +39,10 @@
@property NSInteger outgoingMessageStatus;
// for MediaMessages
@property JSQMediaItem *mediaItem;
// ---
@property (nonatomic, copy) NSDate *messageDate;
@ -48,11 +55,11 @@
@implementation TSMessageAdapter
+ (instancetype)messageViewDataWithInteraction:(TSInteraction*)interaction inThread:(TSThread*)thread{
+ (id<JSQMessageData>)messageViewDataWithInteraction:(TSInteraction*)interaction inThread:(TSThread*)thread{
TSMessageAdapter *adapter = [[TSMessageAdapter alloc] init];
adapter.messageDate = interaction.date;
adapter.identifier = (NSUInteger)interaction.uniqueId;
adapter.messageDate = interaction.date;
adapter.identifier = (NSUInteger)interaction.uniqueId;
if ([thread isKindOfClass:[TSContactThread class]]) {
adapter.thread = (TSContactThread*)thread;
@ -80,6 +87,23 @@
if ([interaction isKindOfClass:[TSIncomingMessage class]] || [interaction isKindOfClass:[TSOutgoingMessage class]]) {
TSMessage *message = (TSMessage*)interaction;
adapter.messageBody = message.body;
if (message.attachements > 0) {
for (NSString *attachementID in message.attachements) {
TSAttachement *attachement = [TSAttachement fetchObjectWithUniqueID:attachementID];
if ([attachement isKindOfClass:[TSAttachementStream class]]) {
TSAttachementStream *stream = (TSAttachementStream*)attachement;
if ([stream isImage]) {
adapter.mediaItem = [[TSAttachementAdapter alloc] initWithAttachement:stream];
adapter.mediaItem.appliesMediaViewMaskAsOutgoing = [interaction isKindOfClass:[TSOutgoingMessage class]];
}
}
}
}
} else if ([interaction isKindOfClass:[TSCall class]]){
adapter.messageBody = @"Placeholder for TSCalls";
adapter.messageType = TSCallAdapter;
@ -123,7 +147,11 @@
}
- (BOOL)isMediaMessage{
return NO;
return _mediaItem?YES:NO;
}
- (id<JSQMessageMediaData>)media{
return _mediaItem;
}
- (NSString *)text{