diff --git a/.clang-format b/.clang-format index b9661ce97..0ef36b1e5 100644 --- a/.clang-format +++ b/.clang-format @@ -1,7 +1,11 @@ --- BasedOnStyle: Chromium AlignTrailingComments: true -BreakBeforeBraces: Linux +AlignConsecutiveAssignments: true +AllowShortIfStatementsOnASingleLine: false +BreakBeforeBraces: Attach +BinPackArguments: false +BinPackParameters: false ColumnLimit: 120 IndentWidth: 4 KeepEmptyLinesAtTheStartOfBlocks: false diff --git a/.gitignore b/.gitignore index f29dd36b6..7f82260de 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,6 @@ xcuserdata DerivedData *.hmap *.ipa -*.xcuserstate \ No newline at end of file +*.xcuserstate + +Pods/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index ddc193faa..e69de29bb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "Pods"] - path = Pods - url = https://github.com/FredericJacobs/Precompiled-Signal-Dependencies.git diff --git a/.travis.yml b/.travis.yml index 61b3a4435..5a0f6cb43 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ xcode_sdk: iphonesimulator9.1 before_install: - brew update - brew uninstall xctool && brew install --HEAD xctool -install: true +install: travis_wait pod install xcode_workspace: Signal.xcworkspace xcode_scheme: Signal diff --git a/Libraries/spandsp/spandsp/spandsp.xcodeproj/xcshareddata/xcschemes/spandsp.xcscheme b/Libraries/spandsp/spandsp/spandsp.xcodeproj/xcshareddata/xcschemes/spandsp.xcscheme index d3775c9d2..fe7a6fa76 100644 --- a/Libraries/spandsp/spandsp/spandsp.xcodeproj/xcshareddata/xcschemes/spandsp.xcscheme +++ b/Libraries/spandsp/spandsp/spandsp.xcodeproj/xcshareddata/xcschemes/spandsp.xcscheme @@ -1,6 +1,6 @@ 1.0.204.1' -pod 'libPhoneNumber-iOS', '~> 0.8.7' -pod 'AxolotlKit' +pod 'TextSecureKit', :git => 'https://github.com/WhisperSystems/TextSecureKit', :branch => 'master' +pod 'OpenSSL', '~> 1.0.205' pod 'PastelogKit', '~> 1.3' -pod 'TwistedOakCollapsingFutures','~> 1.0' -pod 'AFNetworking', '~> 2.6' -pod 'Mantle', '~> 2.0.4' pod 'FFCircularProgressView', '~> 0.5' pod 'SCWaveformView', '~> 1.0' -pod 'YapDatabase/SQLCipher', '~> 2.7.2' pod 'iRate', '~> 1.11' -pod 'SSKeychain' pod 'DJWActionSheet' -pod 'SocketRocket', :git => 'https://github.com/FredericJacobs/SocketRocket.git', :commit => 'dd7e47fed78214785d7c032081da94008335fc35' pod 'JSQMessagesViewController', :git => 'https://github.com/WhisperSystems/JSQMessagesViewController', :commit => 'e5582fef8a6b3e35f8070361ef37237222da712b' diff --git a/Podfile.lock b/Podfile.lock index 718fafc97..df4eb9d8e 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,27 +1,21 @@ PODS: - 25519 (2.0.2) - - AFNetworking (2.6.3): - - AFNetworking/NSURLConnection (= 2.6.3) - - AFNetworking/NSURLSession (= 2.6.3) - - AFNetworking/Reachability (= 2.6.3) - - AFNetworking/Security (= 2.6.3) - - AFNetworking/Serialization (= 2.6.3) - - AFNetworking/UIKit (= 2.6.3) - - AFNetworking/NSURLConnection (2.6.3): + - AFNetworking (3.0.4): + - AFNetworking/NSURLSession (= 3.0.4) + - AFNetworking/Reachability (= 3.0.4) + - AFNetworking/Security (= 3.0.4) + - AFNetworking/Serialization (= 3.0.4) + - AFNetworking/UIKit (= 3.0.4) + - AFNetworking/NSURLSession (3.0.4): - AFNetworking/Reachability - AFNetworking/Security - AFNetworking/Serialization - - AFNetworking/NSURLSession (2.6.3): - - AFNetworking/Reachability - - AFNetworking/Security - - AFNetworking/Serialization - - AFNetworking/Reachability (2.6.3) - - AFNetworking/Security (2.6.3) - - AFNetworking/Serialization (2.6.3) - - AFNetworking/UIKit (2.6.3): - - AFNetworking/NSURLConnection + - AFNetworking/Reachability (3.0.4) + - AFNetworking/Security (3.0.4) + - AFNetworking/Serialization (3.0.4) + - AFNetworking/UIKit (3.0.4): - AFNetworking/NSURLSession - - AxolotlKit (0.7): + - AxolotlKit (0.8): - 25519 (~> 2.0.1) - HKDFKit (~> 0.0.3) - ProtocolBuffers (~> 1.9.8) @@ -41,65 +35,69 @@ PODS: - JSQSystemSoundPlayer (~> 2.0.1) - JSQSystemSoundPlayer (2.0.1) - libPhoneNumber-iOS (0.8.10) - - Mantle (2.0.5): - - Mantle/extobjc (= 2.0.5) - - Mantle/extobjc (2.0.5) - - OpenSSL (1.0.204.1) + - Mantle (2.0.6): + - Mantle/extobjc (= 2.0.6) + - Mantle/extobjc (2.0.6) + - OpenSSL (1.0.205) - PastelogKit (1.3): - CocoaLumberjack (~> 2.0) - ProtocolBuffers (1.9.9.2) - SCWaveformView (1.0.0) - - SocketRocket (0.4.2) - - SQLCipher/common (3.1.0) - - SQLCipher/fts (3.1.0): + - SocketRocket-PinningPolicy (0.4.3) + - SQLCipher/common (3.3.1) + - SQLCipher/fts (3.3.1): - SQLCipher/common - - SSKeychain (1.2.3) + - SSKeychain (1.3.1) + - TextSecureKit (0.0.4): + - '25519' + - AFNetworking + - AxolotlKit + - CocoaLumberjack + - libPhoneNumber-iOS + - Mantle + - SocketRocket-PinningPolicy + - SSKeychain + - TwistedOakCollapsingFutures + - YapDatabase/SQLCipher - TwistedOakCollapsingFutures (1.0.0): - UnionFind (~> 1.0) - UnionFind (1.0.1) - - YapDatabase/SQLCipher (2.7.6): + - YapDatabase/SQLCipher (2.7.7): - CocoaLumberjack (~> 2) - SQLCipher/fts DEPENDENCIES: - - AFNetworking (~> 2.6) - - AxolotlKit - DJWActionSheet - FFCircularProgressView (~> 0.5) - iRate (~> 1.11) - JSQMessagesViewController (from `https://github.com/WhisperSystems/JSQMessagesViewController`, commit `e5582fef8a6b3e35f8070361ef37237222da712b`) - - libPhoneNumber-iOS (~> 0.8.7) - - Mantle (~> 2.0.4) - - OpenSSL (~> 1.0.204.1) + - OpenSSL (~> 1.0.205) - PastelogKit (~> 1.3) - SCWaveformView (~> 1.0) - - SocketRocket (from `https://github.com/FredericJacobs/SocketRocket.git`, commit - `dd7e47fed78214785d7c032081da94008335fc35`) - - SSKeychain - - TwistedOakCollapsingFutures (~> 1.0) - - YapDatabase/SQLCipher (~> 2.7.2) + - TextSecureKit (from `https://github.com/WhisperSystems/TextSecureKit`, branch + `master`) EXTERNAL SOURCES: JSQMessagesViewController: :commit: e5582fef8a6b3e35f8070361ef37237222da712b :git: https://github.com/WhisperSystems/JSQMessagesViewController - SocketRocket: - :commit: dd7e47fed78214785d7c032081da94008335fc35 - :git: https://github.com/FredericJacobs/SocketRocket.git + TextSecureKit: + :branch: master + :git: https://github.com/WhisperSystems/TextSecureKit CHECKOUT OPTIONS: JSQMessagesViewController: :commit: e5582fef8a6b3e35f8070361ef37237222da712b :git: https://github.com/WhisperSystems/JSQMessagesViewController - SocketRocket: - :commit: dd7e47fed78214785d7c032081da94008335fc35 - :git: https://github.com/FredericJacobs/SocketRocket.git + TextSecureKit: + :commit: 8d6ce0b57c2d7de63d4e22f205ea87622432088e + :git: https://github.com/WhisperSystems/TextSecureKit SPEC CHECKSUMS: '25519': dc4bad7e2dbcbf1efa121068a705a44cd98c80fc - AFNetworking: cb8d14a848e831097108418f5d49217339d4eb60 - AxolotlKit: 8652fca51f4bc8225cbda791b0026c21e912b694 + AFNetworking: a0075feb321559dc78d9d85b55d11caa19eabb93 + AxolotlKit: a33962f26943990e5d69d05b30470cea18caeed0 CocoaLumberjack: 17fe8581f84914d5d7e6360f7c70022b173c3ae0 DJWActionSheet: 2fe54b1298a7f0fe44462233752c76a530e0cd80 FFCircularProgressView: 683a4ab1e1bd613246a3dffa61503ffdebcde8d8 @@ -108,16 +106,17 @@ SPEC CHECKSUMS: JSQMessagesViewController: ca11f86fa68ca70835f05e169df9244147c1dc40 JSQSystemSoundPlayer: c5850e77a4363ffd374cd851154b9af93264ed8d libPhoneNumber-iOS: 7bfd00f843fdcd82b5182b463e8eb3b27579f41d - Mantle: 1912395033f601de5adc8ee91e48f46e4c7051ad - OpenSSL: 7f853fcada78e5162c2183b4d90ebbd0aa02f5ac + Mantle: 299966b00759634931699f69cb6a30b9239b944d + OpenSSL: 162687d7e96a3edeb4cf443ca6ce7cdb2912df7b PastelogKit: 7b475be4cf577713506a943dd940bcc0499c8bca ProtocolBuffers: 7111461618460961e6b7469177ec45ee551b4f0e SCWaveformView: 52a96750255d817e300565a80c81fb643e233e07 - SocketRocket: ffe08119b00ef982f6c37052a4705a057c8494ad - SQLCipher: c44fcca49c31483c2489cfb79aa7a69407f3794a - SSKeychain: 3f42991739c6c60a9cf1bbd4dff6c0d3694bcf3d + SocketRocket-PinningPolicy: f2ef00c3927bac05cd04d9d5171f82d922b40d3d + SQLCipher: d490d2effe735895d2204d25a154b1e722278421 + SSKeychain: 04c4ec40f4c3deda524e269bc76e5f30e638a174 + TextSecureKit: b7419cbc792e5be4cbfd93a4da340f7a51d7bc41 TwistedOakCollapsingFutures: f359b90f203e9ab13dfb92c9ff41842a7fe1cd0c UnionFind: c33be5adb12983981d6e827ea94fc7f9e370f52d - YapDatabase: 00e5a5d1b5dba1bd540ef644576233b5612e6122 + YapDatabase: a7a1ae3e0f89c319e3b22615c2351987fbbdbded COCOAPODS: 0.39.0 diff --git a/Pods b/Pods deleted file mode 160000 index e6c803ff3..000000000 --- a/Pods +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e6c803ff3cdb391d5c0dc9a2418f1e2f0797a1a3 diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index effa024f0..bb30dd52c 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -7,257 +7,113 @@ objects = { /* Begin PBXBuildFile section */ - 057B54FA6208D8269CFE6146 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D488327B732CFBE8349C7024 /* libPods.a */; }; - 28508611F3DF531CEDF5103D /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D488327B732CFBE8349C7024 /* libPods.a */; }; + 4B552ED26FB6FB54EDDBB7BD /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D124A70602BD07D5F1EE5FD8 /* libPods.a */; }; 4CE0E3771B954546007210CF /* TSAnimatedAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CE0E3761B954546007210CF /* TSAnimatedAdapter.m */; }; - 53EF5134D8FB5FCBDEDE2A35 /* (null) in Frameworks */ = {isa = PBXBuildFile; settings = {ATTRIBUTES = (Weak, ); }; }; 701231B518ECAA4500D456C4 /* EvpMessageDigest.m in Sources */ = {isa = PBXBuildFile; fileRef = 701231B418ECAA4500D456C4 /* EvpMessageDigest.m */; }; 70377AAB1918450100CAF501 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 70377AAA1918450100CAF501 /* MobileCoreServices.framework */; }; 7038632718F70C0700D4A43F /* CryptoTools.m in Sources */ = {isa = PBXBuildFile; fileRef = 7038632418F70C0700D4A43F /* CryptoTools.m */; }; 7038632818F70C0700D4A43F /* EvpSymetricUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 7038632618F70C0700D4A43F /* EvpSymetricUtil.m */; }; - 7095B7B018F46D35002C66E2 /* PhoneNumberUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 7095B7AF18F46D35002C66E2 /* PhoneNumberUtil.m */; }; 70B800A6190C53180042E3F0 /* libspandsp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 70B800A3190C529C0042E3F0 /* libspandsp.a */; }; 70B800AF190C548D0042E3F0 /* libspeex.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 70B800AC190C54790042E3F0 /* libspeex.a */; }; 70B8FEE21909FE360042E3F0 /* 171756__nenadsimic__picked-coin-echo-2.wav in Resources */ = {isa = PBXBuildFile; fileRef = 70B8FEE11909FE360042E3F0 /* 171756__nenadsimic__picked-coin-echo-2.wav */; }; 70BAFD5D190584BE00FA5E0B /* NotificationTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 70BAFD5C190584BE00FA5E0B /* NotificationTracker.m */; }; 768A1A2B17FC9CD300E00ED8 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 768A1A2A17FC9CD300E00ED8 /* libz.dylib */; }; - 76919BF71805D190008C664A /* ContactManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 76919BF61805D190008C664A /* ContactManagerTest.m */; }; 76C87F19181EFCE600C4ACAB /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 76C87F18181EFCE600C4ACAB /* MediaPlayer.framework */; }; 76EB054018170B33006006FC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB03C318170B33006006FC /* AppDelegate.m */; }; - 76EB054118170B33006006FC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB03C318170B33006006FC /* AppDelegate.m */; }; 76EB057218170B33006006FC /* RecentCall.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040018170B33006006FC /* RecentCall.m */; }; - 76EB057318170B33006006FC /* RecentCall.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040018170B33006006FC /* RecentCall.m */; }; 76EB057418170B33006006FC /* RecentCallManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040218170B33006006FC /* RecentCallManager.m */; }; - 76EB057518170B33006006FC /* RecentCallManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040218170B33006006FC /* RecentCallManager.m */; }; - 76EB057618170B33006006FC /* Contact.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040518170B33006006FC /* Contact.m */; }; - 76EB057718170B33006006FC /* Contact.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040518170B33006006FC /* Contact.m */; }; 76EB057A18170B33006006FC /* ContactsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040918170B33006006FC /* ContactsManager.m */; }; - 76EB057B18170B33006006FC /* ContactsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040918170B33006006FC /* ContactsManager.m */; }; 76EB058218170B33006006FC /* Environment.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041318170B33006006FC /* Environment.m */; }; - 76EB058318170B33006006FC /* Environment.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041318170B33006006FC /* Environment.m */; }; 76EB058418170B33006006FC /* LocalizableText.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041518170B33006006FC /* LocalizableText.m */; }; - 76EB058518170B33006006FC /* LocalizableText.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041518170B33006006FC /* LocalizableText.m */; }; 76EB058618170B33006006FC /* PreferencesUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041718170B33006006FC /* PreferencesUtil.m */; }; - 76EB058718170B33006006FC /* PreferencesUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041718170B33006006FC /* PreferencesUtil.m */; }; 76EB058818170B33006006FC /* PropertyListPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041918170B33006006FC /* PropertyListPreferences.m */; }; - 76EB058918170B33006006FC /* PropertyListPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041918170B33006006FC /* PropertyListPreferences.m */; }; 76EB058A18170B33006006FC /* Release.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041B18170B33006006FC /* Release.m */; }; - 76EB058B18170B33006006FC /* Release.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041B18170B33006006FC /* Release.m */; }; 76EB058C18170B33006006FC /* DnsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB042018170B33006006FC /* DnsManager.m */; }; - 76EB058D18170B33006006FC /* DnsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB042018170B33006006FC /* DnsManager.m */; }; 76EB058E18170B33006006FC /* HostNameEndPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB042218170B33006006FC /* HostNameEndPoint.m */; }; - 76EB058F18170B33006006FC /* HostNameEndPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB042218170B33006006FC /* HostNameEndPoint.m */; }; 76EB059018170B33006006FC /* IgnoredPacketFailure.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB042518170B33006006FC /* IgnoredPacketFailure.m */; }; - 76EB059118170B33006006FC /* IgnoredPacketFailure.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB042518170B33006006FC /* IgnoredPacketFailure.m */; }; 76EB059218170B33006006FC /* UnrecognizedRequestFailure.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB042718170B33006006FC /* UnrecognizedRequestFailure.m */; }; - 76EB059318170B33006006FC /* UnrecognizedRequestFailure.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB042718170B33006006FC /* UnrecognizedRequestFailure.m */; }; 76EB059418170B33006006FC /* HttpManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB042A18170B33006006FC /* HttpManager.m */; }; - 76EB059518170B33006006FC /* HttpManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB042A18170B33006006FC /* HttpManager.m */; }; 76EB059E18170B33006006FC /* HttpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB043418170B33006006FC /* HttpSocket.m */; }; - 76EB059F18170B33006006FC /* HttpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB043418170B33006006FC /* HttpSocket.m */; }; 76EB05A018170B33006006FC /* IpAddress.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB043618170B33006006FC /* IpAddress.m */; }; - 76EB05A118170B33006006FC /* IpAddress.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB043618170B33006006FC /* IpAddress.m */; }; 76EB05A218170B33006006FC /* IpEndPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB043818170B33006006FC /* IpEndPoint.m */; }; - 76EB05A318170B33006006FC /* IpEndPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB043818170B33006006FC /* IpEndPoint.m */; }; 76EB05A418170B33006006FC /* PacketHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB043B18170B33006006FC /* PacketHandler.m */; }; - 76EB05A518170B33006006FC /* PacketHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB043B18170B33006006FC /* PacketHandler.m */; }; 76EB05A618170B33006006FC /* RtpPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB043E18170B33006006FC /* RtpPacket.m */; }; - 76EB05A718170B33006006FC /* RtpPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB043E18170B33006006FC /* RtpPacket.m */; }; 76EB05A818170B33006006FC /* RtpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044018170B33006006FC /* RtpSocket.m */; }; - 76EB05A918170B33006006FC /* RtpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044018170B33006006FC /* RtpSocket.m */; }; 76EB05AA18170B33006006FC /* SequenceCounter.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044318170B33006006FC /* SequenceCounter.m */; }; - 76EB05AB18170B33006006FC /* SequenceCounter.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044318170B33006006FC /* SequenceCounter.m */; }; 76EB05AC18170B33006006FC /* SrtpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044518170B33006006FC /* SrtpSocket.m */; }; - 76EB05AD18170B33006006FC /* SrtpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044518170B33006006FC /* SrtpSocket.m */; }; 76EB05AE18170B33006006FC /* SrtpStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044718170B33006006FC /* SrtpStream.m */; }; - 76EB05AF18170B33006006FC /* SrtpStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044718170B33006006FC /* SrtpStream.m */; }; 76EB05B218170B33006006FC /* DH3KKeyAgreementProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044D18170B33006006FC /* DH3KKeyAgreementProtocol.m */; }; - 76EB05B318170B33006006FC /* DH3KKeyAgreementProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044D18170B33006006FC /* DH3KKeyAgreementProtocol.m */; }; 76EB05B418170B33006006FC /* HashChain.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044F18170B33006006FC /* HashChain.m */; }; - 76EB05B518170B33006006FC /* HashChain.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044F18170B33006006FC /* HashChain.m */; }; 76EB05B618170B33006006FC /* MasterSecret.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045118170B33006006FC /* MasterSecret.m */; }; - 76EB05B718170B33006006FC /* MasterSecret.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045118170B33006006FC /* MasterSecret.m */; }; 76EB05B818170B33006006FC /* NegotiationFailed.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045318170B33006006FC /* NegotiationFailed.m */; }; - 76EB05B918170B33006006FC /* NegotiationFailed.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045318170B33006006FC /* NegotiationFailed.m */; }; 76EB05BA18170B33006006FC /* CommitPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045618170B33006006FC /* CommitPacket.m */; }; - 76EB05BB18170B33006006FC /* CommitPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045618170B33006006FC /* CommitPacket.m */; }; 76EB05BC18170B33006006FC /* ConfirmAckPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045818170B33006006FC /* ConfirmAckPacket.m */; }; - 76EB05BD18170B33006006FC /* ConfirmAckPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045818170B33006006FC /* ConfirmAckPacket.m */; }; 76EB05BE18170B33006006FC /* ConfirmPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045A18170B33006006FC /* ConfirmPacket.m */; }; - 76EB05BF18170B33006006FC /* ConfirmPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045A18170B33006006FC /* ConfirmPacket.m */; }; 76EB05C018170B33006006FC /* DhPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045C18170B33006006FC /* DhPacket.m */; }; - 76EB05C118170B33006006FC /* DhPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045C18170B33006006FC /* DhPacket.m */; }; 76EB05C218170B33006006FC /* DhPacketSharedSecretHashes.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045E18170B33006006FC /* DhPacketSharedSecretHashes.m */; }; - 76EB05C318170B33006006FC /* DhPacketSharedSecretHashes.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045E18170B33006006FC /* DhPacketSharedSecretHashes.m */; }; 76EB05C418170B33006006FC /* HandshakePacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046018170B33006006FC /* HandshakePacket.m */; }; - 76EB05C518170B33006006FC /* HandshakePacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046018170B33006006FC /* HandshakePacket.m */; }; 76EB05C618170B33006006FC /* HelloAckPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046218170B33006006FC /* HelloAckPacket.m */; }; - 76EB05C718170B33006006FC /* HelloAckPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046218170B33006006FC /* HelloAckPacket.m */; }; 76EB05C818170B33006006FC /* HelloPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046418170B33006006FC /* HelloPacket.m */; }; - 76EB05C918170B33006006FC /* HelloPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046418170B33006006FC /* HelloPacket.m */; }; 76EB05CA18170B33006006FC /* RecipientUnavailable.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046A18170B33006006FC /* RecipientUnavailable.m */; }; - 76EB05CB18170B33006006FC /* RecipientUnavailable.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046A18170B33006006FC /* RecipientUnavailable.m */; }; 76EB05CC18170B33006006FC /* ShortAuthenticationStringGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046C18170B33006006FC /* ShortAuthenticationStringGenerator.m */; }; - 76EB05CD18170B33006006FC /* ShortAuthenticationStringGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046C18170B33006006FC /* ShortAuthenticationStringGenerator.m */; }; 76EB05CE18170B33006006FC /* ZrtpHandshakeResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046E18170B33006006FC /* ZrtpHandshakeResult.m */; }; - 76EB05CF18170B33006006FC /* ZrtpHandshakeResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046E18170B33006006FC /* ZrtpHandshakeResult.m */; }; 76EB05D018170B33006006FC /* ZrtpHandshakeSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047018170B33006006FC /* ZrtpHandshakeSocket.m */; }; - 76EB05D118170B33006006FC /* ZrtpHandshakeSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047018170B33006006FC /* ZrtpHandshakeSocket.m */; }; 76EB05D218170B33006006FC /* ZrtpInitiator.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047218170B33006006FC /* ZrtpInitiator.m */; }; - 76EB05D318170B33006006FC /* ZrtpInitiator.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047218170B33006006FC /* ZrtpInitiator.m */; }; 76EB05D418170B33006006FC /* ZrtpManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047418170B33006006FC /* ZrtpManager.m */; }; - 76EB05D518170B33006006FC /* ZrtpManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047418170B33006006FC /* ZrtpManager.m */; }; 76EB05D618170B33006006FC /* ZrtpResponder.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047618170B33006006FC /* ZrtpResponder.m */; }; - 76EB05D718170B33006006FC /* ZrtpResponder.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047618170B33006006FC /* ZrtpResponder.m */; }; 76EB05D818170B33006006FC /* LowLatencyCandidate.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047918170B33006006FC /* LowLatencyCandidate.m */; }; - 76EB05D918170B33006006FC /* LowLatencyCandidate.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047918170B33006006FC /* LowLatencyCandidate.m */; }; 76EB05DA18170B33006006FC /* LowLatencyConnector.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047B18170B33006006FC /* LowLatencyConnector.m */; }; - 76EB05DB18170B33006006FC /* LowLatencyConnector.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047B18170B33006006FC /* LowLatencyConnector.m */; }; 76EB05DC18170B33006006FC /* StreamPair.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047D18170B33006006FC /* StreamPair.m */; }; - 76EB05DD18170B33006006FC /* StreamPair.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047D18170B33006006FC /* StreamPair.m */; }; 76EB05DE18170B33006006FC /* Certificate.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048018170B33006006FC /* Certificate.m */; }; - 76EB05DF18170B33006006FC /* Certificate.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048018170B33006006FC /* Certificate.m */; }; 76EB05E018170B33006006FC /* NetworkStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048218170B33006006FC /* NetworkStream.m */; }; - 76EB05E118170B33006006FC /* NetworkStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048218170B33006006FC /* NetworkStream.m */; }; 76EB05E218170B33006006FC /* SecureEndPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048418170B33006006FC /* SecureEndPoint.m */; }; - 76EB05E318170B33006006FC /* SecureEndPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048418170B33006006FC /* SecureEndPoint.m */; }; 76EB05E418170B33006006FC /* UdpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048718170B33006006FC /* UdpSocket.m */; }; - 76EB05E518170B33006006FC /* UdpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048718170B33006006FC /* UdpSocket.m */; }; 76EB05E618170B33006006FC /* CallController.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048B18170B33006006FC /* CallController.m */; }; - 76EB05E718170B33006006FC /* CallController.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048B18170B33006006FC /* CallController.m */; }; 76EB05E818170B33006006FC /* CallFailedServerMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048D18170B33006006FC /* CallFailedServerMessage.m */; }; - 76EB05E918170B33006006FC /* CallFailedServerMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048D18170B33006006FC /* CallFailedServerMessage.m */; }; 76EB05EA18170B33006006FC /* CallProgress.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048F18170B33006006FC /* CallProgress.m */; }; - 76EB05EB18170B33006006FC /* CallProgress.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048F18170B33006006FC /* CallProgress.m */; }; 76EB05EC18170B33006006FC /* CallState.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049118170B33006006FC /* CallState.m */; }; - 76EB05ED18170B33006006FC /* CallState.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049118170B33006006FC /* CallState.m */; }; 76EB05EE18170B33006006FC /* CallTermination.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049318170B33006006FC /* CallTermination.m */; }; - 76EB05EF18170B33006006FC /* CallTermination.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049318170B33006006FC /* CallTermination.m */; }; 76EB05F018170B33006006FC /* PhoneManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049518170B33006006FC /* PhoneManager.m */; }; - 76EB05F118170B33006006FC /* PhoneManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049518170B33006006FC /* PhoneManager.m */; }; - 76EB05F218170B33006006FC /* PhoneNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049718170B33006006FC /* PhoneNumber.m */; }; - 76EB05F318170B33006006FC /* PhoneNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049718170B33006006FC /* PhoneNumber.m */; }; 76EB05F418170B33006006FC /* CallConnectResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049A18170B33006006FC /* CallConnectResult.m */; }; - 76EB05F518170B33006006FC /* CallConnectResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049A18170B33006006FC /* CallConnectResult.m */; }; 76EB05F618170B33006006FC /* CallConnectUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049C18170B33006006FC /* CallConnectUtil.m */; }; - 76EB05F718170B33006006FC /* CallConnectUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049C18170B33006006FC /* CallConnectUtil.m */; }; 76EB05F818170B33006006FC /* CallConnectUtil_Initiator.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049E18170B33006006FC /* CallConnectUtil_Initiator.m */; }; - 76EB05F918170B33006006FC /* CallConnectUtil_Initiator.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049E18170B33006006FC /* CallConnectUtil_Initiator.m */; }; 76EB05FA18170B33006006FC /* CallConnectUtil_Responder.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04A018170B33006006FC /* CallConnectUtil_Responder.m */; }; - 76EB05FB18170B33006006FC /* CallConnectUtil_Responder.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04A018170B33006006FC /* CallConnectUtil_Responder.m */; }; 76EB05FC18170B33006006FC /* CallConnectUtil_Server.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04A218170B33006006FC /* CallConnectUtil_Server.m */; }; - 76EB05FD18170B33006006FC /* CallConnectUtil_Server.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04A218170B33006006FC /* CallConnectUtil_Server.m */; }; 76EB05FE18170B33006006FC /* InitiateSignal.pb.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04A418170B33006006FC /* InitiateSignal.pb.m */; settings = {COMPILER_FLAGS = "-w"; }; }; - 76EB05FF18170B33006006FC /* InitiateSignal.pb.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04A418170B33006006FC /* InitiateSignal.pb.m */; settings = {COMPILER_FLAGS = "-w"; }; }; 76EB060118170B33006006FC /* InitiateSignal.proto in Resources */ = {isa = PBXBuildFile; fileRef = 76EB04A518170B33006006FC /* InitiateSignal.proto */; }; 76EB060218170B33006006FC /* InitiatorSessionDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04A718170B33006006FC /* InitiatorSessionDescriptor.m */; }; - 76EB060318170B33006006FC /* InitiatorSessionDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04A718170B33006006FC /* InitiatorSessionDescriptor.m */; }; 76EB060818170B33006006FC /* ResponderSessionDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04AE18170B33006006FC /* ResponderSessionDescriptor.m */; }; - 76EB060918170B33006006FC /* ResponderSessionDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04AE18170B33006006FC /* ResponderSessionDescriptor.m */; }; 76EB060A18170B33006006FC /* SignalUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04B018170B33006006FC /* SignalUtil.m */; }; - 76EB060B18170B33006006FC /* SignalUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04B018170B33006006FC /* SignalUtil.m */; }; 76EB060C18170B33006006FC /* CategorizingLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04B318170B33006006FC /* CategorizingLogger.m */; }; - 76EB060D18170B33006006FC /* CategorizingLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04B318170B33006006FC /* CategorizingLogger.m */; }; 76EB060E18170B33006006FC /* DecayingSampleEstimator.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04B518170B33006006FC /* DecayingSampleEstimator.m */; }; - 76EB060F18170B33006006FC /* DecayingSampleEstimator.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04B518170B33006006FC /* DecayingSampleEstimator.m */; }; 76EB061018170B33006006FC /* EventWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04B718170B33006006FC /* EventWindow.m */; }; - 76EB061118170B33006006FC /* EventWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04B718170B33006006FC /* EventWindow.m */; }; 76EB061218170B33006006FC /* LoggingUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04B918170B33006006FC /* LoggingUtil.m */; }; - 76EB061318170B33006006FC /* LoggingUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04B918170B33006006FC /* LoggingUtil.m */; }; 76EB061418170B33006006FC /* AnonymousConditionLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04C018170B33006006FC /* AnonymousConditionLogger.m */; }; - 76EB061518170B33006006FC /* AnonymousConditionLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04C018170B33006006FC /* AnonymousConditionLogger.m */; }; 76EB061618170B33006006FC /* AnonymousOccurrenceLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04C218170B33006006FC /* AnonymousOccurrenceLogger.m */; }; - 76EB061718170B33006006FC /* AnonymousOccurrenceLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04C218170B33006006FC /* AnonymousOccurrenceLogger.m */; }; 76EB061818170B33006006FC /* AnonymousValueLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04C418170B33006006FC /* AnonymousValueLogger.m */; }; - 76EB061918170B33006006FC /* AnonymousValueLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04C418170B33006006FC /* AnonymousValueLogger.m */; }; 76EB061A18170B33006006FC /* DiscardingLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04C618170B33006006FC /* DiscardingLog.m */; }; - 76EB061B18170B33006006FC /* DiscardingLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04C618170B33006006FC /* DiscardingLog.m */; }; 76EB061C18170B33006006FC /* ArrayUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04CA18170B33006006FC /* ArrayUtil.m */; }; - 76EB061D18170B33006006FC /* ArrayUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04CA18170B33006006FC /* ArrayUtil.m */; }; 76EB062218170B33006006FC /* CyclicalBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04D118170B33006006FC /* CyclicalBuffer.m */; }; - 76EB062318170B33006006FC /* CyclicalBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04D118170B33006006FC /* CyclicalBuffer.m */; }; 76EB062418170B33006006FC /* PriorityQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04D318170B33006006FC /* PriorityQueue.m */; }; - 76EB062518170B33006006FC /* PriorityQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04D318170B33006006FC /* PriorityQueue.m */; }; 76EB062618170B33006006FC /* Queue.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04D518170B33006006FC /* Queue.m */; }; - 76EB062718170B33006006FC /* Queue.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04D518170B33006006FC /* Queue.m */; }; - 76EB062818170B33006006FC /* BadArgument.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04D818170B33006006FC /* BadArgument.m */; }; - 76EB062918170B33006006FC /* BadArgument.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04D818170B33006006FC /* BadArgument.m */; }; - 76EB062A18170B33006006FC /* BadState.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04DA18170B33006006FC /* BadState.m */; }; - 76EB062B18170B33006006FC /* BadState.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04DA18170B33006006FC /* BadState.m */; }; - 76EB062C18170B33006006FC /* OperationFailed.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04DD18170B33006006FC /* OperationFailed.m */; }; - 76EB062D18170B33006006FC /* OperationFailed.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04DD18170B33006006FC /* OperationFailed.m */; }; - 76EB062E18170B33006006FC /* SecurityFailure.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04DF18170B33006006FC /* SecurityFailure.m */; }; - 76EB062F18170B33006006FC /* SecurityFailure.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04DF18170B33006006FC /* SecurityFailure.m */; }; 76EB063018170B33006006FC /* Conversions.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04E118170B33006006FC /* Conversions.m */; }; - 76EB063118170B33006006FC /* Conversions.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04E118170B33006006FC /* Conversions.m */; }; 76EB063218170B33006006FC /* Crc32.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04E318170B33006006FC /* Crc32.m */; }; - 76EB063318170B33006006FC /* Crc32.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04E318170B33006006FC /* Crc32.m */; }; 76EB063618170B33006006FC /* DataUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04E718170B33006006FC /* DataUtil.m */; }; - 76EB063718170B33006006FC /* DataUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04E718170B33006006FC /* DataUtil.m */; }; 76EB063818170B33006006FC /* DictionaryUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04E918170B33006006FC /* DictionaryUtil.m */; }; - 76EB063918170B33006006FC /* DictionaryUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04E918170B33006006FC /* DictionaryUtil.m */; }; 76EB063A18170B33006006FC /* FunctionalUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04EB18170B33006006FC /* FunctionalUtil.m */; }; - 76EB063B18170B33006006FC /* FunctionalUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04EB18170B33006006FC /* FunctionalUtil.m */; }; 76EB063C18170B33006006FC /* NumberUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04ED18170B33006006FC /* NumberUtil.m */; }; - 76EB063D18170B33006006FC /* NumberUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04ED18170B33006006FC /* NumberUtil.m */; }; 76EB063E18170B33006006FC /* Operation.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04EF18170B33006006FC /* Operation.m */; }; - 76EB063F18170B33006006FC /* Operation.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04EF18170B33006006FC /* Operation.m */; }; 76EB064018170B33006006FC /* AnonymousTerminator.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04F418170B33006006FC /* AnonymousTerminator.m */; }; - 76EB064118170B33006006FC /* AnonymousTerminator.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04F418170B33006006FC /* AnonymousTerminator.m */; }; 76EB064218170B33006006FC /* StringUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04F618170B33006006FC /* StringUtil.m */; }; - 76EB064318170B33006006FC /* StringUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04F618170B33006006FC /* StringUtil.m */; }; 76EB064418170B33006006FC /* ThreadManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04F818170B33006006FC /* ThreadManager.m */; }; - 76EB064518170B33006006FC /* ThreadManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04F818170B33006006FC /* ThreadManager.m */; }; 76EB064618170B33006006FC /* TimeUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04FA18170B33006006FC /* TimeUtil.m */; }; - 76EB064718170B33006006FC /* TimeUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04FA18170B33006006FC /* TimeUtil.m */; }; 76EB064818170B33006006FC /* Zid.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04FD18170B33006006FC /* Zid.m */; }; - 76EB064918170B33006006FC /* Zid.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04FD18170B33006006FC /* Zid.m */; }; 76EB065618170B34006006FC /* InCallViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB050C18170B33006006FC /* InCallViewController.m */; }; - 76EB065718170B34006006FC /* InCallViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB050C18170B33006006FC /* InCallViewController.m */; }; 76EB065A18170B34006006FC /* NextResponderScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB051018170B33006006FC /* NextResponderScrollView.m */; }; - 76EB065B18170B34006006FC /* NextResponderScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB051018170B33006006FC /* NextResponderScrollView.m */; }; 76EB068618170B34006006FC /* ContactTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB052F18170B33006006FC /* ContactTableViewCell.m */; }; - 76EB068718170B34006006FC /* ContactTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB052F18170B33006006FC /* ContactTableViewCell.m */; }; - 7FAA7C04BD50D54101D1BB1A /* (null) in Frameworks */ = {isa = PBXBuildFile; settings = {ATTRIBUTES = (Weak, ); }; }; A10FDF79184FB4BB007FF963 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 76C87F18181EFCE600C4ACAB /* MediaPlayer.framework */; }; A11CD70D17FA230600A2D1B1 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A11CD70C17FA230600A2D1B1 /* QuartzCore.framework */; }; A123C14916F902EE000AE905 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A163E8AA16F3F6A90094D68B /* Security.framework */; }; - A157075717F0CD6D007C2BD6 /* AudioFrameTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A15706F417F0CD6D007C2BD6 /* AudioFrameTest.m */; }; - A157075817F0CD6D007C2BD6 /* AudioRemoteIOTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A15706F617F0CD6D007C2BD6 /* AudioRemoteIOTest.m */; }; - A157075917F0CD6D007C2BD6 /* AudioStretcherTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A15706F817F0CD6D007C2BD6 /* AudioStretcherTest.m */; }; - A157075A17F0CD6D007C2BD6 /* JitterQueueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A15706FA17F0CD6D007C2BD6 /* JitterQueueTest.m */; }; - A157075B17F0CD6D007C2BD6 /* SpeexCodecTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A15706FC17F0CD6D007C2BD6 /* SpeexCodecTest.m */; }; - A157075D17F0CD6D007C2BD6 /* DnsManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157070317F0CD6D007C2BD6 /* DnsManagerTest.m */; }; - A157075E17F0CD6D007C2BD6 /* HttpRequestResponseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157070617F0CD6D007C2BD6 /* HttpRequestResponseTest.m */; }; - A157075F17F0CD6D007C2BD6 /* IpAddressTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157070817F0CD6D007C2BD6 /* IpAddressTest.m */; }; - A157076017F0CD6D007C2BD6 /* IpEndPointTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157070A17F0CD6D007C2BD6 /* IpEndPointTest.m */; }; - A157076117F0CD6D007C2BD6 /* RtpPacketTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A157070D17F0CD6D007C2BD6 /* RtpPacketTests.m */; }; - A157076217F0CD6D007C2BD6 /* SecureStreamTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157071017F0CD6D007C2BD6 /* SecureStreamTest.m */; }; - A157076317F0CD6D007C2BD6 /* SequenceCounterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157071217F0CD6D007C2BD6 /* SequenceCounterTest.m */; }; - A157076517F0CD6D007C2BD6 /* HandshakePacketTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157071717F0CD6D007C2BD6 /* HandshakePacketTest.m */; }; - A157076617F0CD6D007C2BD6 /* HashChainTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157071917F0CD6D007C2BD6 /* HashChainTest.m */; }; - A157076717F0CD6D007C2BD6 /* MasterSecretTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157071B17F0CD6D007C2BD6 /* MasterSecretTest.m */; }; - A157076817F0CD6D007C2BD6 /* ShortAuthenticationStringGeneratorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157071D17F0CD6D007C2BD6 /* ShortAuthenticationStringGeneratorTest.m */; }; - A157076917F0CD6D007C2BD6 /* PregeneratedKeyAgreementParticipantProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = A157072017F0CD6D007C2BD6 /* PregeneratedKeyAgreementParticipantProtocol.m */; }; - A157076A17F0CD6D007C2BD6 /* ZrtpTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157072217F0CD6D007C2BD6 /* ZrtpTest.m */; }; - A157076B17F0CD6D007C2BD6 /* LowLatencyConnectorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157072517F0CD6D007C2BD6 /* LowLatencyConnectorTest.m */; }; - A157076C17F0CD6D007C2BD6 /* NetworkStreamTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157072817F0CD6D007C2BD6 /* NetworkStreamTest.m */; }; - A157076D17F0CD6D007C2BD6 /* SecureEndPointTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157072A17F0CD6D007C2BD6 /* SecureEndPointTest.m */; }; - A157076E17F0CD6D007C2BD6 /* UdpSocketTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157072D17F0CD6D007C2BD6 /* UdpSocketTest.m */; }; - A157076F17F0CD6D007C2BD6 /* PhoneNumberTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157073017F0CD6D007C2BD6 /* PhoneNumberTest.m */; }; - A157077017F0CD6D007C2BD6 /* SessionDescriptorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157073317F0CD6D007C2BD6 /* SessionDescriptorTest.m */; }; - A157077117F0CD6D007C2BD6 /* DecayingSampleEstimatorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157073617F0CD6D007C2BD6 /* DecayingSampleEstimatorTest.m */; }; - A157077217F0CD6D007C2BD6 /* EventWindowTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157073817F0CD6D007C2BD6 /* EventWindowTest.m */; }; - A157077417F0CD6D007C2BD6 /* TestUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = A157073C17F0CD6D007C2BD6 /* TestUtil.m */; }; - A157077717F0CD6D007C2BD6 /* ConversionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157074317F0CD6D007C2BD6 /* ConversionsTest.m */; }; - A157077817F0CD6D007C2BD6 /* Crc32Test.m in Sources */ = {isa = PBXBuildFile; fileRef = A157074517F0CD6D007C2BD6 /* Crc32Test.m */; }; - A157077917F0CD6D007C2BD6 /* CryptoToolsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157074717F0CD6D007C2BD6 /* CryptoToolsTest.m */; }; - A157077A17F0CD6D007C2BD6 /* CyclicalBufferTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157074917F0CD6D007C2BD6 /* CyclicalBufferTest.m */; }; - A157077B17F0CD6D007C2BD6 /* ExceptionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157074B17F0CD6D007C2BD6 /* ExceptionsTest.m */; }; - A157077C17F0CD6D007C2BD6 /* FunctionalUtilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157074D17F0CD6D007C2BD6 /* FunctionalUtilTest.m */; }; - A157077D17F0CD6D007C2BD6 /* PriorityQueueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157074F17F0CD6D007C2BD6 /* PriorityQueueTest.m */; }; - A157077E17F0CD6D007C2BD6 /* QueueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157075117F0CD6D007C2BD6 /* QueueTest.m */; }; - A157077F17F0CD6D007C2BD6 /* UtilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A157075317F0CD6D007C2BD6 /* UtilTest.m */; }; A163E8AB16F3F6AA0094D68B /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A163E8AA16F3F6A90094D68B /* Security.framework */; }; A194D3B917A08CD1004BD3A9 /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1C32D4D17A0652C000A904E /* AddressBook.framework */; }; A194D3BA17A08CD5004BD3A9 /* AddressBookUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1C32D4F17A06537000A904E /* AddressBookUI.framework */; }; @@ -272,10 +128,8 @@ A56977911A351BC400173BF2 /* ScanIdentityBarcodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A569778E1A351BC400173BF2 /* ScanIdentityBarcodeViewController.m */; }; A56977921A351BC400173BF2 /* PresentIdentityQRCodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A569778F1A351BC400173BF2 /* PresentIdentityQRCodeViewController.m */; }; A5988A811A8A70D0002AD6BE /* UIButton+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = A5988A801A8A70D0002AD6BE /* UIButton+OWS.m */; }; - A59E6D721A79E5D100D98E2E /* MIMETypeUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = A59E6D711A79E5D100D98E2E /* MIMETypeUtil.m */; }; A5D0699B1A50E9CB004CB540 /* ShowGroupMembersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A5D069991A50E9CB004CB540 /* ShowGroupMembersViewController.m */; }; A5E9D4BB1A65FAD800E4481C /* TSVideoAttachmentAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = A5E9D4B91A65FAD800E4481C /* TSVideoAttachmentAdapter.m */; }; - AA0C8E498E2046B0B81EEE6E /* (null) in Frameworks */ = {isa = PBXBuildFile; }; AD41D7B51A6F6F0600241130 /* play_button.png in Resources */ = {isa = PBXBuildFile; fileRef = AD41D7B31A6F6F0600241130 /* play_button.png */; }; AD41D7B61A6F6F0600241130 /* play_button@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AD41D7B41A6F6F0600241130 /* play_button@2x.png */; }; AD83FF3F1A73426500B5C81A /* audio_pause_button_blue.png in Resources */ = {isa = PBXBuildFile; fileRef = AD83FF381A73426500B5C81A /* audio_pause_button_blue.png */; }; @@ -290,19 +144,12 @@ B10C9B601A7049EC00ECA2BF /* pause_icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B10C9B5C1A7049EC00ECA2BF /* pause_icon@2x.png */; }; B10C9B611A7049EC00ECA2BF /* play_icon.png in Resources */ = {isa = PBXBuildFile; fileRef = B10C9B5D1A7049EC00ECA2BF /* play_icon.png */; }; B10C9B621A7049EC00ECA2BF /* play_icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B10C9B5E1A7049EC00ECA2BF /* play_icon@2x.png */; }; - 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 */; }; - B617E9241A9F962600753F00 /* MessagePaddingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B617E9231A9F962600753F00 /* MessagePaddingTests.m */; }; + B6258B331C29E2E60014138E /* NotificationsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B6258B321C29E2E60014138E /* NotificationsManager.m */; }; B625CD561ABB589C00E8B23C /* NewMessage.aifc in Resources */ = {isa = PBXBuildFile; fileRef = B625CD551ABB589C00E8B23C /* NewMessage.aifc */; }; B62D53F71A23CCAD009AAF82 /* TSMessageAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = B62D53F61A23CCAD009AAF82 /* TSMessageAdapter.m */; }; - B62EFBEC1A91352F0072ADD3 /* TSInvalidIdentityKeyErrorMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = B62EFBE71A91352F0072ADD3 /* TSInvalidIdentityKeyErrorMessage.m */; }; - B62EFBED1A91352F0072ADD3 /* TSInvalidIdentityKeyReceivingErrorMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = B62EFBE91A91352F0072ADD3 /* TSInvalidIdentityKeyReceivingErrorMessage.m */; }; - B62EFBEE1A91352F0072ADD3 /* TSInvalidIdentityKeySendingErrorMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = B62EFBEB1A91352F0072ADD3 /* TSInvalidIdentityKeySendingErrorMessage.m */; }; - B63006431B9631EC00F2FEB5 /* AFSecurityOWSPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = B63006421B9631EC00F2FEB5 /* AFSecurityOWSPolicy.m */; }; + B62F5E101C2980B4000D370C /* NSData+ows_StripToken.m in Sources */ = {isa = PBXBuildFile; fileRef = B62F5E0F1C2980B4000D370C /* NSData+ows_StripToken.m */; }; B633C5861A1D190B0059AC12 /* call@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C5041A1D190B0059AC12 /* call@2x.png */; }; B633C58D1A1D190B0059AC12 /* contact_default_feed.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C50B1A1D190B0059AC12 /* contact_default_feed.png */; }; B633C59D1A1D190B0059AC12 /* endcall@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B633C51B1A1D190B0059AC12 /* endcall@2x.png */; }; @@ -315,112 +162,222 @@ B63761ED19E1FBE8005735D1 /* HttpRequestOrResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = B63761E719E1FBE8005735D1 /* HttpRequestOrResponse.m */; }; B63761EE19E1FBE8005735D1 /* HttpRequestUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B63761E919E1FBE8005735D1 /* HttpRequestUtil.m */; }; B63761EF19E1FBE8005735D1 /* HttpResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = B63761EB19E1FBE8005735D1 /* HttpResponse.m */; }; - B63885D01A2685D700A226A6 /* PreKeyBundle+jsonDict.m in Sources */ = {isa = PBXBuildFile; fileRef = B63885CF1A2685D700A226A6 /* PreKeyBundle+jsonDict.m */; }; - B63AF5C71A1F757900D01AAD /* TSContactsIntersectionRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5AD1A1F757900D01AAD /* TSContactsIntersectionRequest.m */; }; - B63AF5C81A1F757900D01AAD /* TSUnregisterAccountRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5AF1A1F757900D01AAD /* TSUnregisterAccountRequest.m */; }; - B63AF5C91A1F757900D01AAD /* TSRecipientPrekeyRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5B11A1F757900D01AAD /* TSRecipientPrekeyRequest.m */; }; - B63AF5CA1A1F757900D01AAD /* TSRegisterForPushRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5B31A1F757900D01AAD /* TSRegisterForPushRequest.m */; }; - 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 /* TSAttachmentRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5BB1A1F757900D01AAD /* TSAttachmentRequest.m */; }; - B63AF5D01A1F757900D01AAD /* TSSubmitMessageRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63AF5BF1A1F757900D01AAD /* TSSubmitMessageRequest.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"; }; }; - B63BAD6D1A74DA8F00269E74 /* TSStorageManager+messageIDs.m in Sources */ = {isa = PBXBuildFile; fileRef = B63BAD6C1A74DA8F00269E74 /* TSStorageManager+messageIDs.m */; }; - B640C4771A477B0F005C7C8A /* TSAttachementsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B640C4761A477B0F005C7C8A /* TSAttachementsTest.m */; }; - B65031CF1A7862AA002EBBBD /* SignedPreKeyDeletionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B65031CE1A7862AA002EBBBD /* SignedPreKeyDeletionTests.m */; }; + B640BFA81C257843006038B3 /* RPAccountManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B640BFA71C257843006038B3 /* RPAccountManager.m */; }; B65EDA1219E1BE6400AAA7CB /* RPAPICall.m in Sources */ = {isa = PBXBuildFile; fileRef = B65EDA1119E1BE6400AAA7CB /* RPAPICall.m */; }; + B660F6B51C29868000687D6E /* AudioFrameTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F66E1C29867F00687D6E /* AudioFrameTest.m */; }; + B660F6B61C29868000687D6E /* AudioRemoteIOTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F66F1C29867F00687D6E /* AudioRemoteIOTest.m */; }; + B660F6B71C29868000687D6E /* AudioStretcherTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6701C29867F00687D6E /* AudioStretcherTest.m */; }; + B660F6B81C29868000687D6E /* JitterQueueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6711C29867F00687D6E /* JitterQueueTest.m */; }; + B660F6B91C29868000687D6E /* SpeexCodecTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6721C29867F00687D6E /* SpeexCodecTest.m */; }; + B660F6BA1C29868000687D6E /* RecentCallTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6741C29867F00687D6E /* RecentCallTest.m */; }; + B660F6BB1C29868000687D6E /* ContactManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6761C29867F00687D6E /* ContactManagerTest.m */; }; + B660F6BC1C29868000687D6E /* DnsManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6791C29867F00687D6E /* DnsManagerTest.m */; }; + B660F6BD1C29868000687D6E /* HttpRequestResponseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F67B1C29867F00687D6E /* HttpRequestResponseTest.m */; }; + B660F6BE1C29868000687D6E /* IpAddressTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F67C1C29867F00687D6E /* IpAddressTest.m */; }; + B660F6BF1C29868000687D6E /* IpEndPointTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F67D1C29867F00687D6E /* IpEndPointTest.m */; }; + B660F6C01C29868000687D6E /* RtpPacketTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F67F1C29867F00687D6E /* RtpPacketTests.m */; }; + B660F6C11C29868000687D6E /* SecureStreamTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6811C29867F00687D6E /* SecureStreamTest.m */; }; + B660F6C21C29868000687D6E /* SequenceCounterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6821C29867F00687D6E /* SequenceCounterTest.m */; }; + B660F6C31C29868000687D6E /* EC25AgreerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6841C29867F00687D6E /* EC25AgreerTest.m */; }; + B660F6C41C29868000687D6E /* HandshakePacketTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6851C29867F00687D6E /* HandshakePacketTest.m */; }; + B660F6C51C29868000687D6E /* HashChainTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6861C29867F00687D6E /* HashChainTest.m */; }; + B660F6C61C29868000687D6E /* MasterSecretTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6871C29867F00687D6E /* MasterSecretTest.m */; }; + B660F6C71C29868000687D6E /* ShortAuthenticationStringGeneratorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6881C29867F00687D6E /* ShortAuthenticationStringGeneratorTest.m */; }; + B660F6C81C29868000687D6E /* PregeneratedKeyAgreementParticipantProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F68B1C29867F00687D6E /* PregeneratedKeyAgreementParticipantProtocol.m */; }; + B660F6C91C29868000687D6E /* ZrtpTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F68C1C29867F00687D6E /* ZrtpTest.m */; }; + B660F6CA1C29868000687D6E /* LowLatencyConnectorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F68E1C29867F00687D6E /* LowLatencyConnectorTest.m */; }; + B660F6CB1C29868000687D6E /* NetworkStreamTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6901C29868000687D6E /* NetworkStreamTest.m */; }; + B660F6CC1C29868000687D6E /* SecureEndPointTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6911C29868000687D6E /* SecureEndPointTest.m */; }; + B660F6CD1C29868000687D6E /* UdpSocketTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6931C29868000687D6E /* UdpSocketTest.m */; }; + B660F6CE1C29868000687D6E /* PhoneNumberTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6951C29868000687D6E /* PhoneNumberTest.m */; }; + B660F6CF1C29868000687D6E /* SessionDescriptorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6971C29868000687D6E /* SessionDescriptorTest.m */; }; + B660F6D01C29868000687D6E /* DecayingSampleEstimatorTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6991C29868000687D6E /* DecayingSampleEstimatorTest.m */; }; + B660F6D11C29868000687D6E /* EventWindowTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F69A1C29868000687D6E /* EventWindowTest.m */; }; + B660F6D21C29868000687D6E /* PushManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F69C1C29868000687D6E /* PushManagerTest.m */; }; + B660F6D41C29868000687D6E /* whisperFake.cer in Resources */ = {isa = PBXBuildFile; fileRef = B660F69F1C29868000687D6E /* whisperFake.cer */; }; + B660F6D51C29868000687D6E /* TestUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6A11C29868000687D6E /* TestUtil.m */; }; + B660F6D61C29868000687D6E /* ConversionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6A41C29868000687D6E /* ConversionsTest.m */; }; + B660F6D71C29868000687D6E /* Crc32Test.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6A61C29868000687D6E /* Crc32Test.m */; }; + B660F6D81C29868000687D6E /* CryptoToolsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6A71C29868000687D6E /* CryptoToolsTest.m */; }; + B660F6D91C29868000687D6E /* CyclicalBufferTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6A91C29868000687D6E /* CyclicalBufferTest.m */; }; + B660F6DA1C29868000687D6E /* ExceptionsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6AB1C29868000687D6E /* ExceptionsTest.m */; }; + B660F6DB1C29868000687D6E /* FunctionalUtilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6AD1C29868000687D6E /* FunctionalUtilTest.m */; }; + B660F6DC1C29868000687D6E /* FutureUtilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6AE1C29868000687D6E /* FutureUtilTest.m */; }; + B660F6DD1C29868000687D6E /* ObservableTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6AF1C29868000687D6E /* ObservableTest.m */; }; + B660F6DE1C29868000687D6E /* PriorityQueueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6B01C29868000687D6E /* PriorityQueueTest.m */; }; + B660F6DF1C29868000687D6E /* QueueTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6B21C29868000687D6E /* QueueTest.m */; }; + B660F6E01C29868000687D6E /* UtilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B660F6B41C29868000687D6E /* UtilTest.m */; }; + B660F6E91C29938A00687D6E /* libTwistedOakCollapsingFutures.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B660F6E81C29938A00687D6E /* libTwistedOakCollapsingFutures.a */; }; + B660F7001C29988E00687D6E /* AppAudioManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B62018BBF12700F073E5 /* AppAudioManager.m */; }; + B660F7011C29988E00687D6E /* AudioRouter.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B61D18BBEC6D00F073E5 /* AudioRouter.m */; }; + B660F7021C29988E00687D6E /* AudioPacker.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B5E918BBEC1A00F073E5 /* AudioPacker.m */; }; + B660F7031C29988E00687D6E /* AudioSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B5EB18BBEC1A00F073E5 /* AudioSocket.m */; }; + B660F7041C29988E00687D6E /* CallAudioManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B5ED18BBEC1A00F073E5 /* CallAudioManager.m */; }; + B660F7051C29988E00687D6E /* EncodedAudioFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B5EF18BBEC1A00F073E5 /* EncodedAudioFrame.m */; }; + B660F7061C29988E00687D6E /* EncodedAudioPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B5F118BBEC1A00F073E5 /* EncodedAudioPacket.m */; }; + B660F7071C29988E00687D6E /* AudioProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B5F418BBEC1A00F073E5 /* AudioProcessor.m */; }; + B660F7081C29988E00687D6E /* AudioStretcher.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B5F618BBEC1A00F073E5 /* AudioStretcher.m */; }; + B660F7091C29988E00687D6E /* DesiredBufferDepthController.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B5F818BBEC1A00F073E5 /* DesiredBufferDepthController.m */; }; + B660F70A1C29988E00687D6E /* DropoutTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B5FA18BBEC1A00F073E5 /* DropoutTracker.m */; }; + B660F70B1C29988E00687D6E /* JitterQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B5FC18BBEC1A00F073E5 /* JitterQueue.m */; }; + B660F70C1C29988E00687D6E /* StretchFactorController.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B5FE18BBEC1A00F073E5 /* StretchFactorController.m */; }; + B660F70D1C29988E00687D6E /* AnonymousAudioCallbackHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B60518BBEC1A00F073E5 /* AnonymousAudioCallbackHandler.m */; }; + B660F70E1C29988E00687D6E /* RemoteIOAudio.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B60718BBEC1A00F073E5 /* RemoteIOAudio.m */; }; + B660F70F1C29988E00687D6E /* RemoteIOBufferListWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B60918BBEC1A00F073E5 /* RemoteIOBufferListWrapper.m */; }; + B660F7101C29988E00687D6E /* SpeexCodec.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B60B18BBEC1A00F073E5 /* SpeexCodec.m */; }; + B660F7111C29988E00687D6E /* SoundBoard.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B62618BBF63B00F073E5 /* SoundBoard.m */; }; + B660F7121C29988E00687D6E /* SoundInstance.m in Sources */ = {isa = PBXBuildFile; fileRef = E1CD329518BCFF9900B1A496 /* SoundInstance.m */; }; + B660F7131C29988E00687D6E /* SoundPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B62318BBF5BB00F073E5 /* SoundPlayer.m */; }; + B660F7141C29988E00687D6E /* RecentCall.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040018170B33006006FC /* RecentCall.m */; }; + B660F7151C29988E00687D6E /* RecentCallManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040218170B33006006FC /* RecentCallManager.m */; }; + B660F7161C29988E00687D6E /* GroupContactsResult.m in Sources */ = {isa = PBXBuildFile; fileRef = B671B2451A93B238002BBD9D /* GroupContactsResult.m */; }; + B660F7171C29988E00687D6E /* ContactsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB040918170B33006006FC /* ContactsManager.m */; }; + B660F7181C29988E00687D6E /* CryptoTools.m in Sources */ = {isa = PBXBuildFile; fileRef = 7038632418F70C0700D4A43F /* CryptoTools.m */; }; + B660F7191C29988E00687D6E /* EvpMessageDigest.m in Sources */ = {isa = PBXBuildFile; fileRef = 701231B418ECAA4500D456C4 /* EvpMessageDigest.m */; }; + B660F71A1C29988E00687D6E /* EvpSymetricUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 7038632618F70C0700D4A43F /* EvpSymetricUtil.m */; }; + B660F71B1C29988E00687D6E /* Environment.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041318170B33006006FC /* Environment.m */; }; + B660F71C1C29988E00687D6E /* DebugLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = B6C93C4D199567AD00EDF894 /* DebugLogger.m */; }; + B660F71D1C29988E00687D6E /* LocalizableText.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041518170B33006006FC /* LocalizableText.m */; }; + B660F71E1C29988E00687D6E /* PreferencesUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041718170B33006006FC /* PreferencesUtil.m */; }; + B660F71F1C29988E00687D6E /* PropertyListPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041918170B33006006FC /* PropertyListPreferences.m */; }; + B660F7201C29988E00687D6E /* Release.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB041B18170B33006006FC /* Release.m */; }; + B660F7211C29988E00687D6E /* SignalKeyingStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B1013B196D213F007E3930 /* SignalKeyingStorage.m */; }; + B660F7221C29988E00687D6E /* VersionMigrations.m in Sources */ = {isa = PBXBuildFile; fileRef = B60C16641988999D00E97A6C /* VersionMigrations.m */; }; + B660F7231C29988E00687D6E /* DnsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB042018170B33006006FC /* DnsManager.m */; }; + B660F7241C29988E00687D6E /* HostNameEndPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB042218170B33006006FC /* HostNameEndPoint.m */; }; + B660F7251C29988E00687D6E /* IgnoredPacketFailure.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB042518170B33006006FC /* IgnoredPacketFailure.m */; }; + B660F7261C29988E00687D6E /* UnrecognizedRequestFailure.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB042718170B33006006FC /* UnrecognizedRequestFailure.m */; }; + B660F7271C29988E00687D6E /* RPAPICall.m in Sources */ = {isa = PBXBuildFile; fileRef = B65EDA1119E1BE6400AAA7CB /* RPAPICall.m */; }; + B660F7281C29988E00687D6E /* RPServerRequestsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B67ADDC31989FF8700E1A773 /* RPServerRequestsManager.m */; }; + B660F7291C29988E00687D6E /* AFHTTPSessionManager+SignalMethods.m in Sources */ = {isa = PBXBuildFile; fileRef = B63761E219E1F487005735D1 /* AFHTTPSessionManager+SignalMethods.m */; }; + B660F72A1C29988E00687D6E /* HttpRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B63761E519E1FBE8005735D1 /* HttpRequest.m */; }; + B660F72B1C29988E00687D6E /* HttpRequestOrResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = B63761E719E1FBE8005735D1 /* HttpRequestOrResponse.m */; }; + B660F72C1C29988E00687D6E /* HttpRequestUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B63761E919E1FBE8005735D1 /* HttpRequestUtil.m */; }; + B660F72D1C29988E00687D6E /* HttpResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = B63761EB19E1FBE8005735D1 /* HttpResponse.m */; }; + B660F72E1C29988E00687D6E /* HttpManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB042A18170B33006006FC /* HttpManager.m */; }; + B660F72F1C29988E00687D6E /* HttpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB043418170B33006006FC /* HttpSocket.m */; }; + B660F7301C29988E00687D6E /* IpAddress.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB043618170B33006006FC /* IpAddress.m */; }; + B660F7311C29988E00687D6E /* IpEndPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB043818170B33006006FC /* IpEndPoint.m */; }; + B660F7321C29988E00687D6E /* PacketHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB043B18170B33006006FC /* PacketHandler.m */; }; + B660F7331C29988E00687D6E /* RtpPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB043E18170B33006006FC /* RtpPacket.m */; }; + B660F7341C29988E00687D6E /* RtpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044018170B33006006FC /* RtpSocket.m */; }; + B660F7351C29988E00687D6E /* SequenceCounter.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044318170B33006006FC /* SequenceCounter.m */; }; + B660F7361C29988E00687D6E /* SrtpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044518170B33006006FC /* SrtpSocket.m */; }; + B660F7371C29988E00687D6E /* SrtpStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044718170B33006006FC /* SrtpStream.m */; }; + B660F7381C29988E00687D6E /* DH3KKeyAgreementParticipant.m in Sources */ = {isa = PBXBuildFile; fileRef = E19167A318A9687800B7A468 /* DH3KKeyAgreementParticipant.m */; }; + B660F7391C29988E00687D6E /* DH3KKeyAgreementProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044D18170B33006006FC /* DH3KKeyAgreementProtocol.m */; }; + B660F73A1C29988E00687D6E /* EC25KeyAgreementParticipant.m in Sources */ = {isa = PBXBuildFile; fileRef = E16E5BE918AAC40200B7C403 /* EC25KeyAgreementParticipant.m */; }; + B660F73B1C29988E00687D6E /* EC25KeyAgreementProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = E16E5BEB18AAC40200B7C403 /* EC25KeyAgreementProtocol.m */; }; + B660F73C1C29988E00687D6E /* EvpKeyAgreement.m in Sources */ = {isa = PBXBuildFile; fileRef = E16E5BED18AAC40200B7C403 /* EvpKeyAgreement.m */; }; + B660F73D1C29988E00687D6E /* HashChain.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB044F18170B33006006FC /* HashChain.m */; }; + B660F73E1C29988E00687D6E /* MasterSecret.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045118170B33006006FC /* MasterSecret.m */; }; + B660F73F1C29988E00687D6E /* NegotiationFailed.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045318170B33006006FC /* NegotiationFailed.m */; }; + B660F7401C29988E00687D6E /* CommitPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045618170B33006006FC /* CommitPacket.m */; }; + B660F7411C29988E00687D6E /* ConfirmAckPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045818170B33006006FC /* ConfirmAckPacket.m */; }; + B660F7421C29988E00687D6E /* ConfirmPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045A18170B33006006FC /* ConfirmPacket.m */; }; + B660F7431C29988E00687D6E /* DhPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045C18170B33006006FC /* DhPacket.m */; }; + B660F7441C29988E00687D6E /* DhPacketSharedSecretHashes.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB045E18170B33006006FC /* DhPacketSharedSecretHashes.m */; }; + B660F7451C29988E00687D6E /* HandshakePacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046018170B33006006FC /* HandshakePacket.m */; }; + B660F7461C29988E00687D6E /* HelloAckPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046218170B33006006FC /* HelloAckPacket.m */; }; + B660F7471C29988E00687D6E /* HelloPacket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046418170B33006006FC /* HelloPacket.m */; }; + B660F7481C29988E00687D6E /* RecipientUnavailable.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046A18170B33006006FC /* RecipientUnavailable.m */; }; + B660F7491C29988E00687D6E /* ShortAuthenticationStringGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046C18170B33006006FC /* ShortAuthenticationStringGenerator.m */; }; + B660F74A1C29988E00687D6E /* ZrtpHandshakeResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB046E18170B33006006FC /* ZrtpHandshakeResult.m */; }; + B660F74B1C29988E00687D6E /* ZrtpHandshakeSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047018170B33006006FC /* ZrtpHandshakeSocket.m */; }; + B660F74C1C29988E00687D6E /* ZrtpInitiator.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047218170B33006006FC /* ZrtpInitiator.m */; }; + B660F74D1C29988E00687D6E /* ZrtpManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047418170B33006006FC /* ZrtpManager.m */; }; + B660F74E1C29988E00687D6E /* ZrtpResponder.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047618170B33006006FC /* ZrtpResponder.m */; }; + B660F74F1C29988E00687D6E /* LowLatencyCandidate.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047918170B33006006FC /* LowLatencyCandidate.m */; }; + B660F7501C29988E00687D6E /* LowLatencyConnector.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047B18170B33006006FC /* LowLatencyConnector.m */; }; + B660F7511C29988E00687D6E /* StreamPair.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB047D18170B33006006FC /* StreamPair.m */; }; + B660F7521C29988E00687D6E /* Certificate.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048018170B33006006FC /* Certificate.m */; }; + B660F7531C29988E00687D6E /* NetworkStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048218170B33006006FC /* NetworkStream.m */; }; + B660F7541C29988E00687D6E /* SecureEndPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048418170B33006006FC /* SecureEndPoint.m */; }; + B660F7551C29988E00687D6E /* UdpSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048718170B33006006FC /* UdpSocket.m */; }; + B660F7561C29988E00687D6E /* PushManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B9ECFB198B31BA00C620D3 /* PushManager.m */; }; + B660F7571C29988E00687D6E /* NotificationTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 70BAFD5C190584BE00FA5E0B /* NotificationTracker.m */; }; + B660F7581C29988E00687D6E /* RPAccountManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B640BFA71C257843006038B3 /* RPAccountManager.m */; }; + B660F7591C29988E00687D6E /* CallController.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048B18170B33006006FC /* CallController.m */; }; + B660F75A1C29988E00687D6E /* CallFailedServerMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048D18170B33006006FC /* CallFailedServerMessage.m */; }; + B660F75B1C29988E00687D6E /* CallProgress.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB048F18170B33006006FC /* CallProgress.m */; }; + B660F75C1C29988E00687D6E /* CallState.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049118170B33006006FC /* CallState.m */; }; + B660F75D1C29988E00687D6E /* CallTermination.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049318170B33006006FC /* CallTermination.m */; }; + B660F75E1C29988E00687D6E /* PhoneManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049518170B33006006FC /* PhoneManager.m */; }; + B660F75F1C29988E00687D6E /* CallConnectResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049A18170B33006006FC /* CallConnectResult.m */; }; + B660F7601C29988E00687D6E /* CallConnectUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049C18170B33006006FC /* CallConnectUtil.m */; }; + B660F7611C29988E00687D6E /* CallConnectUtil_Initiator.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB049E18170B33006006FC /* CallConnectUtil_Initiator.m */; }; + B660F7621C29988E00687D6E /* CallConnectUtil_Responder.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04A018170B33006006FC /* CallConnectUtil_Responder.m */; }; + B660F7631C29988E00687D6E /* CallConnectUtil_Server.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04A218170B33006006FC /* CallConnectUtil_Server.m */; }; + B660F7641C29988E00687D6E /* InitiateSignal.pb.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04A418170B33006006FC /* InitiateSignal.pb.m */; }; + B660F7651C29988E00687D6E /* InitiatorSessionDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04A718170B33006006FC /* InitiatorSessionDescriptor.m */; }; + B660F7661C29988E00687D6E /* ResponderSessionDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04AE18170B33006006FC /* ResponderSessionDescriptor.m */; }; + B660F7671C29988E00687D6E /* SignalUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04B018170B33006006FC /* SignalUtil.m */; }; + B660F7681C29988E00687D6E /* CategorizingLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04B318170B33006006FC /* CategorizingLogger.m */; }; + B660F7691C29988E00687D6E /* DecayingSampleEstimator.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04B518170B33006006FC /* DecayingSampleEstimator.m */; }; + B660F76A1C29988E00687D6E /* EventWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04B718170B33006006FC /* EventWindow.m */; }; + B660F76B1C29988E00687D6E /* LoggingUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04B918170B33006006FC /* LoggingUtil.m */; }; + B660F76C1C29988E00687D6E /* AnonymousConditionLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04C018170B33006006FC /* AnonymousConditionLogger.m */; }; + B660F76D1C29988E00687D6E /* AnonymousOccurrenceLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04C218170B33006006FC /* AnonymousOccurrenceLogger.m */; }; + B660F76E1C29988E00687D6E /* AnonymousValueLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04C418170B33006006FC /* AnonymousValueLogger.m */; }; + B660F76F1C29988E00687D6E /* DiscardingLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04C618170B33006006FC /* DiscardingLog.m */; }; + B660F7701C29988E00687D6E /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = B68EF9B71C0B1EBD009C3DCD /* FLAnimatedImage.m */; }; + B660F7711C29988E00687D6E /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = B68EF9B91C0B1EBD009C3DCD /* FLAnimatedImageView.m */; }; + B660F7721C29988E00687D6E /* AppStoreRating.m in Sources */ = {isa = PBXBuildFile; fileRef = B6DA6B061B8A2F9A00CA6F98 /* AppStoreRating.m */; }; + B660F7731C29988E00687D6E /* UIButton+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = A5988A801A8A70D0002AD6BE /* UIButton+OWS.m */; }; + B660F7741C29988E00687D6E /* DJWActionSheet+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = A547DD721A70A87800103EC7 /* DJWActionSheet+OWS.m */; }; + B660F7751C29988E00687D6E /* UIColor+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFA64B31A24F3880007FB87 /* UIColor+OWS.m */; }; + B660F7761C29988E00687D6E /* UIFont+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFA64B61A24F6730007FB87 /* UIFont+OWS.m */; }; + B660F7771C29988E00687D6E /* UIImage+normalizeImage.m in Sources */ = {isa = PBXBuildFile; fileRef = B68112E91A4D9EC400BA82FF /* UIImage+normalizeImage.m */; }; + B660F7781C29988E00687D6E /* ArrayUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04CA18170B33006006FC /* ArrayUtil.m */; }; + B660F7791C29988E00687D6E /* CyclicalBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04D118170B33006006FC /* CyclicalBuffer.m */; }; + B660F77A1C29988E00687D6E /* PriorityQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04D318170B33006006FC /* PriorityQueue.m */; }; + B660F77B1C29988E00687D6E /* Queue.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04D518170B33006006FC /* Queue.m */; }; + B660F77C1C29988E00687D6E /* Conversions.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04E118170B33006006FC /* Conversions.m */; }; + B660F77D1C29988E00687D6E /* Crc32.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04E318170B33006006FC /* Crc32.m */; }; + B660F77E1C29988E00687D6E /* DataUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04E718170B33006006FC /* DataUtil.m */; }; + B660F77F1C29988E00687D6E /* DateUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B90418E5183E9DD40038554A /* DateUtil.m */; }; + B660F7801C29988E00687D6E /* DictionaryUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04E918170B33006006FC /* DictionaryUtil.m */; }; + B660F7811C29988E00687D6E /* FunctionalUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04EB18170B33006006FC /* FunctionalUtil.m */; }; + B660F7821C29988E00687D6E /* FutureUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = BFB074C419A5611000F2947C /* FutureUtil.m */; }; + B660F7831C29988E00687D6E /* NumberUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04ED18170B33006006FC /* NumberUtil.m */; }; + B660F7841C29988E00687D6E /* ObservableValue.m in Sources */ = {isa = PBXBuildFile; fileRef = BFB074C619A5611000F2947C /* ObservableValue.m */; }; + B660F7851C29988E00687D6E /* Operation.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04EF18170B33006006FC /* Operation.m */; }; + B660F7861C29988E00687D6E /* AnonymousTerminator.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04F418170B33006006FC /* AnonymousTerminator.m */; }; + B660F7871C29988E00687D6E /* StringUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04F618170B33006006FC /* StringUtil.m */; }; + B660F7881C29988E00687D6E /* ThreadManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04F818170B33006006FC /* ThreadManager.m */; }; + B660F7891C29988E00687D6E /* TimeUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04FA18170B33006006FC /* TimeUtil.m */; }; + B660F78A1C29988E00687D6E /* UIUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B97940261832BD2400BD66CB /* UIUtil.m */; }; + B660F78B1C29988E00687D6E /* Zid.m in Sources */ = {isa = PBXBuildFile; fileRef = 76EB04FD18170B33006006FC /* Zid.m */; }; + B660F78C1C29988E00687D6E /* UIDevice+TSHardwareVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = FCC81A971A44558300DFEC7D /* UIDevice+TSHardwareVersion.m */; }; + B660F78D1C29988E00687D6E /* TSAdapterCacheManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FC7C7A951A581AF40091823B /* TSAdapterCacheManager.m */; }; B66B9F721AEA6D1100E2E609 /* NotificationSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B66B9F711AEA6D1100E2E609 /* NotificationSettingsViewController.m */; }; B66B9F7D1AEAF40500E2E609 /* NotificationSettingsOptionsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B66B9F7C1AEAF40500E2E609 /* NotificationSettingsOptionsViewController.m */; }; B66DBF4A19D5BBC8006EA940 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B66DBF4919D5BBC8006EA940 /* Images.xcassets */; }; B671B2461A93B238002BBD9D /* GroupContactsResult.m in Sources */ = {isa = PBXBuildFile; fileRef = B671B2451A93B238002BBD9D /* GroupContactsResult.m */; }; - B675C16C1B891B3900A7A87A /* TSAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = B675C16B1B891B3900A7A87A /* TSAttributes.m */; }; B67ADDC41989FF8700E1A773 /* RPServerRequestsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B67ADDC31989FF8700E1A773 /* RPServerRequestsManager.m */; }; B67EBF5D19194AC60084CCFD /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = B67EBF5C19194AC60084CCFD /* Settings.bundle */; }; B68112EA1A4D9EC400BA82FF /* UIImage+normalizeImage.m in Sources */ = {isa = PBXBuildFile; fileRef = B68112E91A4D9EC400BA82FF /* UIImage+normalizeImage.m */; }; - B684A46D19C3446200B11029 /* PushManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B684A46C19C3446200B11029 /* PushManagerTest.m */; }; - B6850E5A1995A4710068E715 /* whisperFake.cer in Resources */ = {isa = PBXBuildFile; fileRef = B6850E591995A4710068E715 /* whisperFake.cer */; }; B68EF9BA1C0B1EBD009C3DCD /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = B68EF9B71C0B1EBD009C3DCD /* FLAnimatedImage.m */; }; B68EF9BB1C0B1EBD009C3DCD /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = B68EF9B91C0B1EBD009C3DCD /* FLAnimatedImageView.m */; }; - B692BF071A76EF0F002786DA /* TSDatabaseSecondaryIndexes.m in Sources */ = {isa = PBXBuildFile; fileRef = B692BF061A76EF0F002786DA /* TSDatabaseSecondaryIndexes.m */; }; B69CD25119773E79005CE69A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B69CD25019773E79005CE69A /* XCTest.framework */; }; B6A3EB4B1A423B3800B2236B /* TSPhotoAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = B6A3EB4A1A423B3800B2236B /* TSPhotoAdapter.m */; }; - B6A5D05C1A7827ED0043D837 /* TSAvailablePreKeysCountRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B6A5D05B1A7827ED0043D837 /* TSAvailablePreKeysCountRequest.m */; }; - B6A5D0631A7850180043D837 /* TSCurrentSignedPreKeyRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B6A5D0621A7850180043D837 /* TSCurrentSignedPreKeyRequest.m */; }; - B6AE33BD1A1EB121003DF39D /* TSGroupModel.m in Sources */ = {isa = PBXBuildFile; fileRef = B6AE33BC1A1EB121003DF39D /* TSGroupModel.m */; }; - B6B095E41A1D25C5008BFAA6 /* CryptographyTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = B6B095DE1A1D25C5008BFAA6 /* CryptographyTests.mm */; }; - B6B095E51A1D25C5008BFAA6 /* TextSecureKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095DF1A1D25C5008BFAA6 /* TextSecureKitTests.m */; }; - B6B095E61A1D25C5008BFAA6 /* TSMessageStorageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095E01A1D25C5008BFAA6 /* TSMessageStorageTests.m */; }; - B6B095E71A1D25C5008BFAA6 /* TSStorageIdentityKeyStoreTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095E11A1D25C5008BFAA6 /* TSStorageIdentityKeyStoreTests.m */; }; - B6B095E81A1D25C5008BFAA6 /* TSStoragePreKeyStoreTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095E21A1D25C5008BFAA6 /* TSStoragePreKeyStoreTests.m */; }; - B6B095E91A1D25C5008BFAA6 /* TSStorageSignedPreKeyStore.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095E31A1D25C5008BFAA6 /* TSStorageSignedPreKeyStore.m */; }; - B6B096611A1D25ED008BFAA6 /* TSAccountManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095ED1A1D25ED008BFAA6 /* TSAccountManager.m */; }; - B6B096631A1D25ED008BFAA6 /* TSPreKeyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095F11A1D25ED008BFAA6 /* TSPreKeyManager.m */; }; - B6B096641A1D25ED008BFAA6 /* TSContactThread.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095F51A1D25ED008BFAA6 /* TSContactThread.m */; }; - B6B096651A1D25ED008BFAA6 /* TSGroupThread.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095F71A1D25ED008BFAA6 /* TSGroupThread.m */; }; - B6B096681A1D25ED008BFAA6 /* SignalRecipient.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095FD1A1D25ED008BFAA6 /* SignalRecipient.m */; }; - B6B096691A1D25ED008BFAA6 /* TSThread.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B095FF1A1D25ED008BFAA6 /* TSThread.m */; }; - B6B0966A1A1D25ED008BFAA6 /* IncomingPushMessageSignal.pb.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096021A1D25ED008BFAA6 /* IncomingPushMessageSignal.pb.m */; settings = {COMPILER_FLAGS = "-w"; }; }; - B6B0966B1A1D25ED008BFAA6 /* TSAttachment.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096041A1D25ED008BFAA6 /* TSAttachment.m */; }; - B6B0966C1A1D25ED008BFAA6 /* TSCall.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096061A1D25ED008BFAA6 /* TSCall.m */; }; - B6B0966D1A1D25ED008BFAA6 /* TSErrorMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096081A1D25ED008BFAA6 /* TSErrorMessage.m */; }; - B6B0966F1A1D25ED008BFAA6 /* TSIncomingMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B0960C1A1D25ED008BFAA6 /* TSIncomingMessage.m */; }; - B6B096701A1D25ED008BFAA6 /* TSInfoMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B0960E1A1D25ED008BFAA6 /* TSInfoMessage.m */; }; - B6B096711A1D25ED008BFAA6 /* TSInteraction.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096101A1D25ED008BFAA6 /* TSInteraction.m */; }; - B6B096721A1D25ED008BFAA6 /* TSMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096121A1D25ED008BFAA6 /* TSMessage.m */; }; - B6B096731A1D25ED008BFAA6 /* TSMessagesManager+sendMessages.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096141A1D25ED008BFAA6 /* TSMessagesManager+sendMessages.m */; }; - B6B096741A1D25ED008BFAA6 /* TSMessagesManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096161A1D25ED008BFAA6 /* TSMessagesManager.m */; }; - B6B096751A1D25ED008BFAA6 /* TSOutgoingMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096181A1D25ED008BFAA6 /* TSOutgoingMessage.m */; }; - B6B096761A1D25ED008BFAA6 /* TSServerMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B0961A1A1D25ED008BFAA6 /* TSServerMessage.m */; }; - B6B096861A1D25ED008BFAA6 /* SecurityUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B0963D1A1D25ED008BFAA6 /* SecurityUtils.m */; }; - B6B096871A1D25ED008BFAA6 /* TSStorageManager+IdentityKeyStore.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096411A1D25ED008BFAA6 /* TSStorageManager+IdentityKeyStore.m */; }; - B6B096881A1D25ED008BFAA6 /* TSStorageManager+keyFromIntLong.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096431A1D25ED008BFAA6 /* TSStorageManager+keyFromIntLong.m */; }; - B6B096891A1D25ED008BFAA6 /* TSStorageManager+PreKeyStore.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096451A1D25ED008BFAA6 /* TSStorageManager+PreKeyStore.m */; }; - B6B0968A1A1D25ED008BFAA6 /* TSStorageManager+SessionStore.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096471A1D25ED008BFAA6 /* TSStorageManager+SessionStore.m */; }; - B6B0968B1A1D25ED008BFAA6 /* TSStorageManager+SignedPreKeyStore.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096491A1D25ED008BFAA6 /* TSStorageManager+SignedPreKeyStore.m */; }; - B6B0968C1A1D25ED008BFAA6 /* TSDatabaseView.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B0964B1A1D25ED008BFAA6 /* TSDatabaseView.m */; }; - B6B0968D1A1D25ED008BFAA6 /* TSStorageManager+keyingMaterial.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B0964E1A1D25ED008BFAA6 /* TSStorageManager+keyingMaterial.m */; }; - B6B0968E1A1D25ED008BFAA6 /* TSStorageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096501A1D25ED008BFAA6 /* TSStorageManager.m */; }; - B6B0968F1A1D25ED008BFAA6 /* TSYapDatabaseObject.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096521A1D25ED008BFAA6 /* TSYapDatabaseObject.m */; }; - B6B096901A1D25ED008BFAA6 /* Cryptography.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096561A1D25ED008BFAA6 /* Cryptography.m */; }; - B6B096911A1D25ED008BFAA6 /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B096581A1D25ED008BFAA6 /* NSData+Base64.m */; }; - B6B096921A1D25ED008BFAA6 /* NSData+hexString.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B0965A1A1D25ED008BFAA6 /* NSData+hexString.m */; }; - B6B096931A1D25ED008BFAA6 /* NSData+messagePadding.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B0965C1A1D25ED008BFAA6 /* NSData+messagePadding.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 */; }; B6B226971BE4B7D200860F4D /* ContactsUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6B226961BE4B7D200860F4D /* ContactsUI.framework */; }; B6B2269A1BE4C59200860F4D /* APNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B226991BE4C59200860F4D /* APNavigationController.m */; }; - B6B50AAB1A4192C500F8F607 /* TSMessagesManager+attachments.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B50AAA1A4192C500F8F607 /* TSMessagesManager+attachments.m */; }; B6B9ECFC198B31BA00C620D3 /* PushManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B9ECFB198B31BA00C620D3 /* PushManager.m */; }; - B6BADBE41B88CB940086A80D /* TSUpdateAttributesRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B6BADBE31B88CB940086A80D /* TSUpdateAttributesRequest.m */; }; B6BADBE71B88D1AC0086A80D /* LockInteractionController.m in Sources */ = {isa = PBXBuildFile; fileRef = B6BADBE61B88D1AC0086A80D /* LockInteractionController.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 */; }; B6DA6B071B8A2F9A00CA6F98 /* AppStoreRating.m in Sources */ = {isa = PBXBuildFile; fileRef = B6DA6B061B8A2F9A00CA6F98 /* AppStoreRating.m */; }; - B6E314C91A38FAAF00A41AFB /* TSFingerprintGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = B6E314C81A38FAAF00A41AFB /* TSFingerprintGenerator.m */; }; - B6E4ECF61C0106DF0014E766 /* ContactsManager+updater.m in Sources */ = {isa = PBXBuildFile; fileRef = B6E4ECF51C0106DF0014E766 /* ContactsManager+updater.m */; }; B6F509971AA53F760068F56A /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = B6F509951AA53F760068F56A /* Localizable.strings */; }; - B6FAAAE81A41BC6C007FEC1D /* TSAttachmentPointer.m in Sources */ = {isa = PBXBuildFile; fileRef = B6FAAAE71A41BC6C007FEC1D /* TSAttachmentPointer.m */; }; - B6FAAAEE1A41C918007FEC1D /* TSAttachmentStream.m in Sources */ = {isa = PBXBuildFile; fileRef = B6FAAAED1A41C918007FEC1D /* TSAttachmentStream.m */; }; B6FE7EB71ADD62FA00A6D22F /* PushKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6FE7EB61ADD62FA00A6D22F /* PushKit.framework */; }; - B6FE7EBA1ADD63AE00A6D22F /* NSData+ows_StripToken.m in Sources */ = {isa = PBXBuildFile; fileRef = B6FE7EB91ADD63AE00A6D22F /* NSData+ows_StripToken.m */; }; B90418E6183E9DD40038554A /* DateUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B90418E5183E9DD40038554A /* DateUtil.m */; }; - B90418E7183E9DD40038554A /* DateUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B90418E5183E9DD40038554A /* DateUtil.m */; }; B97940271832BD2400BD66CB /* UIUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B97940261832BD2400BD66CB /* UIUtil.m */; }; - B97940281832BD2400BD66CB /* UIUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B97940261832BD2400BD66CB /* UIUtil.m */; }; B97CBFA818860EA3008E0DE9 /* CountryCodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B97CBFA618860EA3008E0DE9 /* CountryCodeViewController.m */; }; - B97CBFA918860EA3008E0DE9 /* CountryCodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B97CBFA618860EA3008E0DE9 /* CountryCodeViewController.m */; }; B9EB5ABD1884C002007CBB57 /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B9EB5ABC1884C002007CBB57 /* MessageUI.framework */; }; - BF8C3D8319CE3B6A008F644C /* RecentCallTest.m in Sources */ = {isa = PBXBuildFile; fileRef = BF8C3D8219CE3B6A008F644C /* RecentCallTest.m */; }; - BFB074C119A4BCA400F2947C /* FutureUtilTest.m in Sources */ = {isa = PBXBuildFile; fileRef = BFB074BF19A4BCA400F2947C /* FutureUtilTest.m */; }; - BFB074C219A4BCA400F2947C /* ObservableTest.m in Sources */ = {isa = PBXBuildFile; fileRef = BFB074C019A4BCA400F2947C /* ObservableTest.m */; }; BFB074C719A5611000F2947C /* FutureUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = BFB074C419A5611000F2947C /* FutureUtil.m */; }; - BFB074C819A5611000F2947C /* FutureUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = BFB074C419A5611000F2947C /* FutureUtil.m */; }; BFB074C919A5611000F2947C /* ObservableValue.m in Sources */ = {isa = PBXBuildFile; fileRef = BFB074C619A5611000F2947C /* ObservableValue.m */; }; - BFB074CA19A5611000F2947C /* ObservableValue.m in Sources */ = {isa = PBXBuildFile; fileRef = BFB074C619A5611000F2947C /* ObservableValue.m */; }; + CF6B0CD2D27A0FE420224EE9 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D124A70602BD07D5F1EE5FD8 /* libPods.a */; }; D202868116DBE0E7009068E9 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AEACDB16C426DA00C364C0 /* CFNetwork.framework */; }; D202868216DBE0F4009068E9 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2179CFD16BB0B480006F3AB /* SystemConfiguration.framework */; }; D202868316DBE0FC009068E9 /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2179CFB16BB0B3A0006F3AB /* CoreTelephony.framework */; }; @@ -435,7 +392,6 @@ D221A0E8169DFFC500537ABF /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D221A0E7169DFFC500537ABF /* AVFoundation.framework */; }; D24B5BD5169F568C00681372 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D24B5BD4169F568C00681372 /* AudioToolbox.framework */; }; D2AEACDC16C426DA00C364C0 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AEACDB16C426DA00C364C0 /* CFNetwork.framework */; }; - DE9907A5A8074160B34A8261 /* (null) in Frameworks */ = {isa = PBXBuildFile; }; E1368CBE18A1C36B00109378 /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B9EB5ABC1884C002007CBB57 /* MessageUI.framework */; }; E1370BE018A0686600826894 /* busy.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = E18AB40718A05754001A532A /* busy.mp3 */; }; E1370BE118A0686C00826894 /* completed.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = E18AB40818A05754001A532A /* completed.mp3 */; }; @@ -447,7 +403,6 @@ E16E5BEE18AAC40200B7C403 /* EC25KeyAgreementParticipant.m in Sources */ = {isa = PBXBuildFile; fileRef = E16E5BE918AAC40200B7C403 /* EC25KeyAgreementParticipant.m */; }; E16E5BEF18AAC40200B7C403 /* EC25KeyAgreementProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = E16E5BEB18AAC40200B7C403 /* EC25KeyAgreementProtocol.m */; }; E16E5BF018AAC40200B7C403 /* EvpKeyAgreement.m in Sources */ = {isa = PBXBuildFile; fileRef = E16E5BED18AAC40200B7C403 /* EvpKeyAgreement.m */; }; - E16E5BF918AAF02100B7C403 /* EC25AgreerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E16E5BF818AAF02100B7C403 /* EC25AgreerTest.m */; }; E19167A418A9687800B7A468 /* DH3KKeyAgreementParticipant.m in Sources */ = {isa = PBXBuildFile; fileRef = E19167A318A9687800B7A468 /* DH3KKeyAgreementParticipant.m */; }; E197B60C18BBEC1A00F073E5 /* AudioPacker.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B5E918BBEC1A00F073E5 /* AudioPacker.m */; }; E197B60D18BBEC1A00F073E5 /* AudioSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B5EB18BBEC1A00F073E5 /* AudioSocket.m */; }; @@ -544,8 +499,6 @@ 7038632418F70C0700D4A43F /* CryptoTools.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CryptoTools.m; sourceTree = ""; }; 7038632518F70C0700D4A43F /* EvpSymetricUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EvpSymetricUtil.h; sourceTree = ""; }; 7038632618F70C0700D4A43F /* EvpSymetricUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EvpSymetricUtil.m; sourceTree = ""; }; - 7095B7AE18F46D35002C66E2 /* PhoneNumberUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhoneNumberUtil.h; sourceTree = ""; }; - 7095B7AF18F46D35002C66E2 /* PhoneNumberUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhoneNumberUtil.m; sourceTree = ""; }; 70B8009E190C529C0042E3F0 /* spandsp.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = spandsp.xcodeproj; path = Libraries/spandsp/spandsp/spandsp.xcodeproj; sourceTree = ""; }; 70B800A7190C54790042E3F0 /* speex.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = speex.xcodeproj; path = Libraries/speex/speex.xcodeproj; sourceTree = ""; }; 70B8FEE11909FE360042E3F0 /* 171756__nenadsimic__picked-coin-echo-2.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = "171756__nenadsimic__picked-coin-echo-2.wav"; sourceTree = ""; }; @@ -553,7 +506,6 @@ 70BAFD5C190584BE00FA5E0B /* NotificationTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NotificationTracker.m; sourceTree = ""; }; 70E803ED18F6DD1400BF77BC /* EvpUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EvpUtil.h; sourceTree = ""; }; 768A1A2A17FC9CD300E00ED8 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; - 76919BF61805D190008C664A /* ContactManagerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ContactManagerTest.m; path = contact/ContactManagerTest.m; sourceTree = ""; }; 76C87F18181EFCE600C4ACAB /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; }; 76EB03C218170B33006006FC /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 76EB03C318170B33006006FC /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; @@ -561,8 +513,6 @@ 76EB040018170B33006006FC /* RecentCall.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RecentCall.m; sourceTree = ""; }; 76EB040118170B33006006FC /* RecentCallManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecentCallManager.h; sourceTree = ""; }; 76EB040218170B33006006FC /* RecentCallManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RecentCallManager.m; sourceTree = ""; }; - 76EB040418170B33006006FC /* Contact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Contact.h; sourceTree = ""; }; - 76EB040518170B33006006FC /* Contact.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Contact.m; sourceTree = ""; }; 76EB040818170B33006006FC /* ContactsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactsManager.h; sourceTree = ""; }; 76EB040918170B33006006FC /* ContactsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactsManager.m; sourceTree = ""; }; 76EB041218170B33006006FC /* Environment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Environment.h; sourceTree = ""; }; @@ -671,8 +621,6 @@ 76EB049318170B33006006FC /* CallTermination.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CallTermination.m; sourceTree = ""; }; 76EB049418170B33006006FC /* PhoneManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhoneManager.h; sourceTree = ""; }; 76EB049518170B33006006FC /* PhoneManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhoneManager.m; sourceTree = ""; }; - 76EB049618170B33006006FC /* PhoneNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhoneNumber.h; sourceTree = ""; }; - 76EB049718170B33006006FC /* PhoneNumber.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhoneNumber.m; sourceTree = ""; }; 76EB049918170B33006006FC /* CallConnectResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallConnectResult.h; sourceTree = ""; }; 76EB049A18170B33006006FC /* CallConnectResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CallConnectResult.m; sourceTree = ""; }; 76EB049B18170B33006006FC /* CallConnectUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallConnectUtil.h; sourceTree = ""; }; @@ -720,15 +668,6 @@ 76EB04D318170B33006006FC /* PriorityQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PriorityQueue.m; sourceTree = ""; }; 76EB04D418170B33006006FC /* Queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Queue.h; sourceTree = ""; }; 76EB04D518170B33006006FC /* Queue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Queue.m; sourceTree = ""; }; - 76EB04D718170B33006006FC /* BadArgument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BadArgument.h; sourceTree = ""; }; - 76EB04D818170B33006006FC /* BadArgument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BadArgument.m; sourceTree = ""; }; - 76EB04D918170B33006006FC /* BadState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BadState.h; sourceTree = ""; }; - 76EB04DA18170B33006006FC /* BadState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BadState.m; sourceTree = ""; }; - 76EB04DB18170B33006006FC /* Constraints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Constraints.h; sourceTree = ""; }; - 76EB04DC18170B33006006FC /* OperationFailed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OperationFailed.h; sourceTree = ""; }; - 76EB04DD18170B33006006FC /* OperationFailed.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OperationFailed.m; sourceTree = ""; }; - 76EB04DE18170B33006006FC /* SecurityFailure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecurityFailure.h; sourceTree = ""; }; - 76EB04DF18170B33006006FC /* SecurityFailure.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecurityFailure.m; sourceTree = ""; }; 76EB04E018170B33006006FC /* Conversions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Conversions.h; sourceTree = ""; }; 76EB04E118170B33006006FC /* Conversions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Conversions.m; sourceTree = ""; }; 76EB04E218170B33006006FC /* Crc32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Crc32.h; sourceTree = ""; }; @@ -764,52 +703,6 @@ 91E46203423941C0C94D90E9 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; 9CC6C6BD3B51923FD6317C94 /* Pods.ad-hoc distribution.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods.ad-hoc distribution.xcconfig"; path = "Pods/Target Support Files/Pods/Pods.ad-hoc distribution.xcconfig"; sourceTree = ""; }; A11CD70C17FA230600A2D1B1 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - A15706F417F0CD6D007C2BD6 /* AudioFrameTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioFrameTest.m; sourceTree = ""; }; - A15706F617F0CD6D007C2BD6 /* AudioRemoteIOTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioRemoteIOTest.m; sourceTree = ""; }; - A15706F817F0CD6D007C2BD6 /* AudioStretcherTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioStretcherTest.m; sourceTree = ""; }; - A15706FA17F0CD6D007C2BD6 /* JitterQueueTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JitterQueueTest.m; sourceTree = ""; }; - A15706FC17F0CD6D007C2BD6 /* SpeexCodecTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SpeexCodecTest.m; sourceTree = ""; }; - A157070317F0CD6D007C2BD6 /* DnsManagerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DnsManagerTest.m; sourceTree = ""; }; - A157070617F0CD6D007C2BD6 /* HttpRequestResponseTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HttpRequestResponseTest.m; sourceTree = ""; }; - A157070817F0CD6D007C2BD6 /* IpAddressTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IpAddressTest.m; sourceTree = ""; }; - A157070A17F0CD6D007C2BD6 /* IpEndPointTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IpEndPointTest.m; sourceTree = ""; }; - A157070D17F0CD6D007C2BD6 /* RtpPacketTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RtpPacketTests.m; sourceTree = ""; }; - A157071017F0CD6D007C2BD6 /* SecureStreamTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecureStreamTest.m; sourceTree = ""; }; - A157071217F0CD6D007C2BD6 /* SequenceCounterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SequenceCounterTest.m; sourceTree = ""; }; - A157071717F0CD6D007C2BD6 /* HandshakePacketTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HandshakePacketTest.m; sourceTree = ""; }; - A157071917F0CD6D007C2BD6 /* HashChainTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HashChainTest.m; sourceTree = ""; }; - A157071B17F0CD6D007C2BD6 /* MasterSecretTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MasterSecretTest.m; sourceTree = ""; }; - A157071D17F0CD6D007C2BD6 /* ShortAuthenticationStringGeneratorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ShortAuthenticationStringGeneratorTest.m; sourceTree = ""; }; - A157071F17F0CD6D007C2BD6 /* PregeneratedKeyAgreementParticipantProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PregeneratedKeyAgreementParticipantProtocol.h; sourceTree = ""; }; - A157072017F0CD6D007C2BD6 /* PregeneratedKeyAgreementParticipantProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PregeneratedKeyAgreementParticipantProtocol.m; sourceTree = ""; }; - A157072217F0CD6D007C2BD6 /* ZrtpTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZrtpTest.m; sourceTree = ""; }; - A157072517F0CD6D007C2BD6 /* LowLatencyConnectorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LowLatencyConnectorTest.m; sourceTree = ""; }; - A157072817F0CD6D007C2BD6 /* NetworkStreamTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NetworkStreamTest.m; sourceTree = ""; }; - A157072A17F0CD6D007C2BD6 /* SecureEndPointTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecureEndPointTest.m; sourceTree = ""; }; - A157072D17F0CD6D007C2BD6 /* UdpSocketTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UdpSocketTest.m; sourceTree = ""; }; - A157073017F0CD6D007C2BD6 /* PhoneNumberTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhoneNumberTest.m; sourceTree = ""; }; - A157073317F0CD6D007C2BD6 /* SessionDescriptorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SessionDescriptorTest.m; sourceTree = ""; }; - A157073617F0CD6D007C2BD6 /* DecayingSampleEstimatorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DecayingSampleEstimatorTest.m; sourceTree = ""; }; - A157073817F0CD6D007C2BD6 /* EventWindowTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EventWindowTest.m; sourceTree = ""; }; - A157073A17F0CD6D007C2BD6 /* SignalTests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "SignalTests-Info.plist"; sourceTree = ""; }; - A157073B17F0CD6D007C2BD6 /* TestUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestUtil.h; sourceTree = ""; }; - A157073C17F0CD6D007C2BD6 /* TestUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestUtil.m; sourceTree = ""; }; - A157074217F0CD6D007C2BD6 /* ConversionsTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConversionsTest.h; sourceTree = ""; }; - A157074317F0CD6D007C2BD6 /* ConversionsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConversionsTest.m; sourceTree = ""; }; - A157074417F0CD6D007C2BD6 /* Crc32Test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Crc32Test.h; sourceTree = ""; }; - A157074517F0CD6D007C2BD6 /* Crc32Test.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Crc32Test.m; sourceTree = ""; }; - A157074717F0CD6D007C2BD6 /* CryptoToolsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CryptoToolsTest.m; sourceTree = ""; }; - A157074817F0CD6D007C2BD6 /* CyclicalBufferTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CyclicalBufferTest.h; sourceTree = ""; }; - A157074917F0CD6D007C2BD6 /* CyclicalBufferTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CyclicalBufferTest.m; sourceTree = ""; }; - A157074A17F0CD6D007C2BD6 /* ExceptionsTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExceptionsTest.h; sourceTree = ""; }; - A157074B17F0CD6D007C2BD6 /* ExceptionsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExceptionsTest.m; sourceTree = ""; }; - A157074C17F0CD6D007C2BD6 /* FunctionalUtilTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FunctionalUtilTest.h; sourceTree = ""; }; - A157074D17F0CD6D007C2BD6 /* FunctionalUtilTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FunctionalUtilTest.m; sourceTree = ""; }; - A157074F17F0CD6D007C2BD6 /* PriorityQueueTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PriorityQueueTest.m; sourceTree = ""; }; - A157075017F0CD6D007C2BD6 /* QueueTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QueueTest.h; sourceTree = ""; }; - A157075117F0CD6D007C2BD6 /* QueueTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QueueTest.m; sourceTree = ""; }; - A157075217F0CD6D007C2BD6 /* UtilTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UtilTest.h; sourceTree = ""; }; - A157075317F0CD6D007C2BD6 /* UtilTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UtilTest.m; sourceTree = ""; }; A163E8AA16F3F6A90094D68B /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; A1C32D4D17A0652C000A904E /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; }; A1C32D4F17A06537000A904E /* AddressBookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBookUI.framework; path = System/Library/Frameworks/AddressBookUI.framework; sourceTree = SDKROOT; }; @@ -826,8 +719,6 @@ A56977901A351BC400173BF2 /* PresentIdentityQRCodeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PresentIdentityQRCodeViewController.h; sourceTree = ""; }; A5988A7F1A8A70D0002AD6BE /* UIButton+OWS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIButton+OWS.h"; path = "util/UIButton+OWS.h"; sourceTree = ""; }; A5988A801A8A70D0002AD6BE /* UIButton+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIButton+OWS.m"; path = "util/UIButton+OWS.m"; sourceTree = ""; }; - A59E6D701A79E5D100D98E2E /* MIMETypeUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MIMETypeUtil.h; sourceTree = ""; }; - A59E6D711A79E5D100D98E2E /* MIMETypeUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MIMETypeUtil.m; sourceTree = ""; }; A5D069991A50E9CB004CB540 /* ShowGroupMembersViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ShowGroupMembersViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; A5D0699A1A50E9CB004CB540 /* ShowGroupMembersViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShowGroupMembersViewController.h; sourceTree = ""; }; A5E9D4B91A65FAD800E4481C /* TSVideoAttachmentAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSVideoAttachmentAdapter.m; sourceTree = ""; }; @@ -846,30 +737,17 @@ B10C9B5C1A7049EC00ECA2BF /* pause_icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "pause_icon@2x.png"; sourceTree = ""; }; B10C9B5D1A7049EC00ECA2BF /* play_icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = play_icon.png; sourceTree = ""; }; B10C9B5E1A7049EC00ECA2BF /* play_icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "play_icon@2x.png"; sourceTree = ""; }; - B6019E951A2492AB001118DF /* NSDate+millisecondTimeStamp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+millisecondTimeStamp.h"; sourceTree = ""; }; - B6019E961A2492AB001118DF /* NSDate+millisecondTimeStamp.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSDate+millisecondTimeStamp.mm"; sourceTree = ""; }; B60341CD1AA5469800A01E42 /* ja_JP */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja_JP; path = translations/ja_JP.lproj/Localizable.strings; sourceTree = ""; }; B60C16631988999D00E97A6C /* VersionMigrations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VersionMigrations.h; sourceTree = ""; }; B60C16641988999D00E97A6C /* VersionMigrations.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VersionMigrations.m; sourceTree = ""; }; 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 = ""; }; - B60FB9A61A46F099006A5A66 /* TSAllocAttachmentRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAllocAttachmentRequest.m; sourceTree = ""; }; - B60FB9AB1A46F831006A5A66 /* UIImage+contentTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+contentTypes.h"; sourceTree = ""; }; - B60FB9AC1A46F831006A5A66 /* UIImage+contentTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+contentTypes.m"; sourceTree = ""; }; - B60FB9AE1A4711D4006A5A66 /* TSAttachmentEncryptionResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSAttachmentEncryptionResult.h; sourceTree = ""; }; - B60FB9AF1A4711D4006A5A66 /* TSAttachmentEncryptionResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachmentEncryptionResult.m; sourceTree = ""; }; - B617E9231A9F962600753F00 /* MessagePaddingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MessagePaddingTests.m; sourceTree = ""; }; + B6258B311C29E2E60014138E /* NotificationsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotificationsManager.h; sourceTree = ""; }; + B6258B321C29E2E60014138E /* NotificationsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NotificationsManager.m; sourceTree = ""; }; B625CD551ABB589C00E8B23C /* NewMessage.aifc */ = {isa = PBXFileReference; lastKnownFileType = file; path = NewMessage.aifc; sourceTree = ""; }; B62D53F51A23CCAD009AAF82 /* TSMessageAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSMessageAdapter.h; sourceTree = ""; }; B62D53F61A23CCAD009AAF82 /* TSMessageAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSMessageAdapter.m; sourceTree = ""; }; - B62EFBE61A91352F0072ADD3 /* TSInvalidIdentityKeyErrorMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSInvalidIdentityKeyErrorMessage.h; sourceTree = ""; }; - B62EFBE71A91352F0072ADD3 /* TSInvalidIdentityKeyErrorMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSInvalidIdentityKeyErrorMessage.m; sourceTree = ""; }; - B62EFBE81A91352F0072ADD3 /* TSInvalidIdentityKeyReceivingErrorMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSInvalidIdentityKeyReceivingErrorMessage.h; sourceTree = ""; }; - B62EFBE91A91352F0072ADD3 /* TSInvalidIdentityKeyReceivingErrorMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSInvalidIdentityKeyReceivingErrorMessage.m; sourceTree = ""; }; - B62EFBEA1A91352F0072ADD3 /* TSInvalidIdentityKeySendingErrorMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSInvalidIdentityKeySendingErrorMessage.h; sourceTree = ""; }; - B62EFBEB1A91352F0072ADD3 /* TSInvalidIdentityKeySendingErrorMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSInvalidIdentityKeySendingErrorMessage.m; sourceTree = ""; }; - B63006411B9631EC00F2FEB5 /* AFSecurityOWSPolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFSecurityOWSPolicy.h; sourceTree = ""; }; - B63006421B9631EC00F2FEB5 /* AFSecurityOWSPolicy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFSecurityOWSPolicy.m; sourceTree = ""; }; + B62F5E0E1C2980B4000D370C /* NSData+ows_StripToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+ows_StripToken.h"; sourceTree = ""; }; + B62F5E0F1C2980B4000D370C /* NSData+ows_StripToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+ows_StripToken.m"; sourceTree = ""; }; B633C5041A1D190B0059AC12 /* call@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call@2x.png"; sourceTree = ""; }; B633C50B1A1D190B0059AC12 /* contact_default_feed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = contact_default_feed.png; sourceTree = ""; }; B633C51B1A1D190B0059AC12 /* endcall@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "endcall@2x.png"; sourceTree = ""; }; @@ -889,44 +767,71 @@ B63761E919E1FBE8005735D1 /* HttpRequestUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HttpRequestUtil.m; sourceTree = ""; }; B63761EA19E1FBE8005735D1 /* HttpResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HttpResponse.h; sourceTree = ""; }; B63761EB19E1FBE8005735D1 /* HttpResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HttpResponse.m; sourceTree = ""; }; - B63885CE1A2685D700A226A6 /* PreKeyBundle+jsonDict.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PreKeyBundle+jsonDict.h"; sourceTree = ""; }; - B63885CF1A2685D700A226A6 /* PreKeyBundle+jsonDict.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PreKeyBundle+jsonDict.m"; sourceTree = ""; }; - B63AF5AC1A1F757900D01AAD /* TSContactsIntersectionRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSContactsIntersectionRequest.h; sourceTree = ""; }; - B63AF5AD1A1F757900D01AAD /* TSContactsIntersectionRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSContactsIntersectionRequest.m; sourceTree = ""; }; - B63AF5AE1A1F757900D01AAD /* TSUnregisterAccountRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSUnregisterAccountRequest.h; sourceTree = ""; }; - B63AF5AF1A1F757900D01AAD /* TSUnregisterAccountRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSUnregisterAccountRequest.m; sourceTree = ""; }; - B63AF5B01A1F757900D01AAD /* TSRecipientPrekeyRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSRecipientPrekeyRequest.h; sourceTree = ""; }; - B63AF5B11A1F757900D01AAD /* TSRecipientPrekeyRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSRecipientPrekeyRequest.m; sourceTree = ""; }; - B63AF5B21A1F757900D01AAD /* TSRegisterForPushRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSRegisterForPushRequest.h; sourceTree = ""; }; - B63AF5B31A1F757900D01AAD /* TSRegisterForPushRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSRegisterForPushRequest.m; sourceTree = ""; }; - B63AF5B41A1F757900D01AAD /* TSRegisterPrekeysRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSRegisterPrekeysRequest.h; sourceTree = ""; }; - B63AF5B51A1F757900D01AAD /* TSRegisterPrekeysRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSRegisterPrekeysRequest.m; sourceTree = ""; }; - B63AF5B61A1F757900D01AAD /* TSRegisterWithTokenRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSRegisterWithTokenRequest.h; sourceTree = ""; }; - B63AF5B71A1F757900D01AAD /* TSRegisterWithTokenRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSRegisterWithTokenRequest.m; sourceTree = ""; }; - B63AF5B81A1F757900D01AAD /* TSRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSRequest.h; sourceTree = ""; }; - B63AF5B91A1F757900D01AAD /* TSRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSRequest.m; sourceTree = ""; }; - B63AF5BA1A1F757900D01AAD /* TSAttachmentRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSAttachmentRequest.h; sourceTree = ""; }; - B63AF5BB1A1F757900D01AAD /* TSAttachmentRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachmentRequest.m; sourceTree = ""; }; - B63AF5BE1A1F757900D01AAD /* TSSubmitMessageRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSSubmitMessageRequest.h; sourceTree = ""; }; - B63AF5BF1A1F757900D01AAD /* TSSubmitMessageRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSSubmitMessageRequest.m; sourceTree = ""; }; - B63AF5C21A1F757900D01AAD /* TSNetworkManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSNetworkManager.h; sourceTree = ""; }; - B63AF5C31A1F757900D01AAD /* TSNetworkManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSNetworkManager.m; sourceTree = ""; }; - B63AF5C51A1F757900D01AAD /* TSSocketManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSSocketManager.h; sourceTree = ""; }; - B63AF5C61A1F757900D01AAD /* TSSocketManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSSocketManager.m; sourceTree = ""; }; - B63AF5D61A1F889500D01AAD /* SubProtocol.pb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubProtocol.pb.h; sourceTree = ""; }; - B63AF5D71A1F889500D01AAD /* SubProtocol.pb.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SubProtocol.pb.m; sourceTree = ""; }; - B63BAD6B1A74DA8F00269E74 /* TSStorageManager+messageIDs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TSStorageManager+messageIDs.h"; sourceTree = ""; }; - B63BAD6C1A74DA8F00269E74 /* TSStorageManager+messageIDs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TSStorageManager+messageIDs.m"; sourceTree = ""; }; B63FBC9E1AA545CB00548746 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = translations/fi.lproj/Localizable.strings; sourceTree = ""; }; - B640C4761A477B0F005C7C8A /* TSAttachementsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachementsTest.m; sourceTree = ""; }; + B640BFA61C257843006038B3 /* RPAccountManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RPAccountManager.h; sourceTree = ""; }; + B640BFA71C257843006038B3 /* RPAccountManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RPAccountManager.m; sourceTree = ""; }; B646D10E1AA5461A004133BA /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = translations/fr.lproj/Localizable.strings; sourceTree = ""; }; B646D10F1AA54626004133BA /* fil */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fil; path = translations/fil.lproj/Localizable.strings; sourceTree = ""; }; B646D1141AA54674004133BA /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = translations/hu.lproj/Localizable.strings; sourceTree = ""; }; B646D1151AA5467E004133BA /* it_IT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it_IT; path = translations/it_IT.lproj/Localizable.strings; sourceTree = ""; }; - B65031CE1A7862AA002EBBBD /* SignedPreKeyDeletionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignedPreKeyDeletionTests.m; sourceTree = ""; }; B657DDC91911A40500F45B0C /* Signal.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Signal.entitlements; sourceTree = ""; }; B65EDA1019E1BE6400AAA7CB /* RPAPICall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RPAPICall.h; sourceTree = ""; }; B65EDA1119E1BE6400AAA7CB /* RPAPICall.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RPAPICall.m; sourceTree = ""; }; + B660F66E1C29867F00687D6E /* AudioFrameTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioFrameTest.m; sourceTree = ""; }; + B660F66F1C29867F00687D6E /* AudioRemoteIOTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioRemoteIOTest.m; sourceTree = ""; }; + B660F6701C29867F00687D6E /* AudioStretcherTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioStretcherTest.m; sourceTree = ""; }; + B660F6711C29867F00687D6E /* JitterQueueTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JitterQueueTest.m; sourceTree = ""; }; + B660F6721C29867F00687D6E /* SpeexCodecTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SpeexCodecTest.m; sourceTree = ""; }; + B660F6741C29867F00687D6E /* RecentCallTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RecentCallTest.m; sourceTree = ""; }; + B660F6761C29867F00687D6E /* ContactManagerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactManagerTest.m; sourceTree = ""; }; + B660F6791C29867F00687D6E /* DnsManagerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DnsManagerTest.m; sourceTree = ""; }; + B660F67B1C29867F00687D6E /* HttpRequestResponseTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HttpRequestResponseTest.m; sourceTree = ""; }; + B660F67C1C29867F00687D6E /* IpAddressTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IpAddressTest.m; sourceTree = ""; }; + B660F67D1C29867F00687D6E /* IpEndPointTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IpEndPointTest.m; sourceTree = ""; }; + B660F67F1C29867F00687D6E /* RtpPacketTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RtpPacketTests.m; sourceTree = ""; }; + B660F6811C29867F00687D6E /* SecureStreamTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecureStreamTest.m; sourceTree = ""; }; + B660F6821C29867F00687D6E /* SequenceCounterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SequenceCounterTest.m; sourceTree = ""; }; + B660F6841C29867F00687D6E /* EC25AgreerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EC25AgreerTest.m; sourceTree = ""; }; + B660F6851C29867F00687D6E /* HandshakePacketTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HandshakePacketTest.m; sourceTree = ""; }; + B660F6861C29867F00687D6E /* HashChainTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HashChainTest.m; sourceTree = ""; }; + B660F6871C29867F00687D6E /* MasterSecretTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MasterSecretTest.m; sourceTree = ""; }; + B660F6881C29867F00687D6E /* ShortAuthenticationStringGeneratorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ShortAuthenticationStringGeneratorTest.m; sourceTree = ""; }; + B660F68A1C29867F00687D6E /* PregeneratedKeyAgreementParticipantProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PregeneratedKeyAgreementParticipantProtocol.h; sourceTree = ""; }; + B660F68B1C29867F00687D6E /* PregeneratedKeyAgreementParticipantProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PregeneratedKeyAgreementParticipantProtocol.m; sourceTree = ""; }; + B660F68C1C29867F00687D6E /* ZrtpTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZrtpTest.m; sourceTree = ""; }; + B660F68E1C29867F00687D6E /* LowLatencyConnectorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LowLatencyConnectorTest.m; sourceTree = ""; }; + B660F6901C29868000687D6E /* NetworkStreamTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NetworkStreamTest.m; sourceTree = ""; }; + B660F6911C29868000687D6E /* SecureEndPointTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecureEndPointTest.m; sourceTree = ""; }; + B660F6931C29868000687D6E /* UdpSocketTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UdpSocketTest.m; sourceTree = ""; }; + B660F6951C29868000687D6E /* PhoneNumberTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhoneNumberTest.m; sourceTree = ""; }; + B660F6971C29868000687D6E /* SessionDescriptorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SessionDescriptorTest.m; sourceTree = ""; }; + B660F6991C29868000687D6E /* DecayingSampleEstimatorTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DecayingSampleEstimatorTest.m; sourceTree = ""; }; + B660F69A1C29868000687D6E /* EventWindowTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EventWindowTest.m; sourceTree = ""; }; + B660F69C1C29868000687D6E /* PushManagerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PushManagerTest.m; sourceTree = ""; }; + B660F69E1C29868000687D6E /* SignalTests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "SignalTests-Info.plist"; sourceTree = ""; }; + B660F69F1C29868000687D6E /* whisperFake.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = whisperFake.cer; sourceTree = ""; }; + B660F6A01C29868000687D6E /* TestUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestUtil.h; sourceTree = ""; }; + B660F6A11C29868000687D6E /* TestUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestUtil.m; sourceTree = ""; }; + B660F6A31C29868000687D6E /* ConversionsTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConversionsTest.h; sourceTree = ""; }; + B660F6A41C29868000687D6E /* ConversionsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConversionsTest.m; sourceTree = ""; }; + B660F6A51C29868000687D6E /* Crc32Test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Crc32Test.h; sourceTree = ""; }; + B660F6A61C29868000687D6E /* Crc32Test.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Crc32Test.m; sourceTree = ""; }; + B660F6A71C29868000687D6E /* CryptoToolsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CryptoToolsTest.m; sourceTree = ""; }; + B660F6A81C29868000687D6E /* CyclicalBufferTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CyclicalBufferTest.h; sourceTree = ""; }; + B660F6A91C29868000687D6E /* CyclicalBufferTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CyclicalBufferTest.m; sourceTree = ""; }; + B660F6AA1C29868000687D6E /* ExceptionsTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExceptionsTest.h; sourceTree = ""; }; + B660F6AB1C29868000687D6E /* ExceptionsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExceptionsTest.m; sourceTree = ""; }; + B660F6AC1C29868000687D6E /* FunctionalUtilTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FunctionalUtilTest.h; sourceTree = ""; }; + B660F6AD1C29868000687D6E /* FunctionalUtilTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FunctionalUtilTest.m; sourceTree = ""; }; + B660F6AE1C29868000687D6E /* FutureUtilTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FutureUtilTest.m; sourceTree = ""; }; + B660F6AF1C29868000687D6E /* ObservableTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObservableTest.m; sourceTree = ""; }; + B660F6B01C29868000687D6E /* PriorityQueueTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PriorityQueueTest.m; sourceTree = ""; }; + B660F6B11C29868000687D6E /* QueueTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QueueTest.h; sourceTree = ""; }; + B660F6B21C29868000687D6E /* QueueTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QueueTest.m; sourceTree = ""; }; + B660F6B31C29868000687D6E /* UtilTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UtilTest.h; sourceTree = ""; }; + B660F6B41C29868000687D6E /* UtilTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UtilTest.m; sourceTree = ""; }; + B660F6E11C29886700687D6E /* libTwistedOakCollapsingFutures.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libTwistedOakCollapsingFutures.a; path = "Pods/../build/Debug-iphoneos/libTwistedOakCollapsingFutures.a"; sourceTree = ""; }; + B660F6E81C29938A00687D6E /* libTwistedOakCollapsingFutures.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libTwistedOakCollapsingFutures.a; path = "Pods/../build/Debug-iphoneos/libTwistedOakCollapsingFutures.a"; sourceTree = ""; }; B661C211198EE2EA00548CA1 /* iOSVersions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = iOSVersions.h; path = src/environment/iOSVersions.h; sourceTree = ""; }; B66B9F701AEA6D1100E2E609 /* NotificationSettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotificationSettingsViewController.h; sourceTree = ""; }; B66B9F711AEA6D1100E2E609 /* NotificationSettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NotificationSettingsViewController.m; sourceTree = ""; }; @@ -935,9 +840,6 @@ B66DBF4919D5BBC8006EA940 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; B671B2441A93B238002BBD9D /* GroupContactsResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GroupContactsResult.h; sourceTree = ""; }; B671B2451A93B238002BBD9D /* GroupContactsResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GroupContactsResult.m; sourceTree = ""; }; - B675C16A1B891B3900A7A87A /* TSAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSAttributes.h; sourceTree = ""; }; - B675C16B1B891B3900A7A87A /* TSAttributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttributes.m; sourceTree = ""; }; - B675C16F1B891D6800A7A87A /* TSStorageHeaders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSStorageHeaders.h; path = ../TSStorageHeaders.h; sourceTree = ""; }; B676BCEF1AA544E7009637B8 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = translations/de.lproj/Localizable.strings; sourceTree = ""; }; B676BCF01AA544F5009637B8 /* el_GR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el_GR; path = translations/el_GR.lproj/Localizable.strings; sourceTree = ""; }; B676BCF11AA5451E009637B8 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = translations/es.lproj/Localizable.strings; sourceTree = ""; }; @@ -946,9 +848,6 @@ B67EBF5C19194AC60084CCFD /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = Settings.bundle; path = SettingsBundle/Settings.bundle; sourceTree = SOURCE_ROOT; }; B68112E81A4D9EC400BA82FF /* UIImage+normalizeImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImage+normalizeImage.h"; path = "util/UIImage+normalizeImage.h"; sourceTree = ""; }; B68112E91A4D9EC400BA82FF /* UIImage+normalizeImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIImage+normalizeImage.m"; path = "util/UIImage+normalizeImage.m"; sourceTree = ""; }; - 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 = ""; }; - B68B0E8D1A542AD700DE8A02 /* TSErrorMessage_privateConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSErrorMessage_privateConstructor.h; sourceTree = ""; }; B68CB7D71AA546B80065AC3F /* ko_KR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko_KR; path = translations/ko_KR.lproj/Localizable.strings; sourceTree = ""; }; B68CB7D81AA546C30065AC3F /* lv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lv; path = translations/lv.lproj/Localizable.strings; sourceTree = ""; }; B68CB7D91AA546CE0065AC3F /* nb_NO */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb_NO; path = translations/nb_NO.lproj/Localizable.strings; sourceTree = ""; }; @@ -966,8 +865,6 @@ B68EF9B71C0B1EBD009C3DCD /* FLAnimatedImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FLAnimatedImage.m; path = Libraries/FLAnimatedImage/FLAnimatedImage.m; sourceTree = SOURCE_ROOT; }; B68EF9B81C0B1EBD009C3DCD /* FLAnimatedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FLAnimatedImageView.h; path = Libraries/FLAnimatedImage/FLAnimatedImageView.h; sourceTree = SOURCE_ROOT; }; B68EF9B91C0B1EBD009C3DCD /* FLAnimatedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FLAnimatedImageView.m; path = Libraries/FLAnimatedImage/FLAnimatedImageView.m; sourceTree = SOURCE_ROOT; }; - B692BF051A76EF0F002786DA /* TSDatabaseSecondaryIndexes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSDatabaseSecondaryIndexes.h; sourceTree = ""; }; - B692BF061A76EF0F002786DA /* TSDatabaseSecondaryIndexes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSDatabaseSecondaryIndexes.m; sourceTree = ""; }; B69C2D171AA5445000A640C2 /* az_AZ */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = az_AZ; path = translations/az_AZ.lproj/Localizable.strings; sourceTree = ""; }; B69C2D181AA5445F00A640C2 /* bg_BG */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg_BG; path = translations/bg_BG.lproj/Localizable.strings; sourceTree = ""; }; B69C2D191AA5446C00A640C2 /* bs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bs; path = translations/bs.lproj/Localizable.strings; sourceTree = ""; }; @@ -976,118 +873,25 @@ B69CD25019773E79005CE69A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; B6A3EB491A423B3800B2236B /* TSPhotoAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSPhotoAdapter.h; sourceTree = ""; }; B6A3EB4A1A423B3800B2236B /* TSPhotoAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSPhotoAdapter.m; sourceTree = ""; }; - B6A5D05A1A7827ED0043D837 /* TSAvailablePreKeysCountRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSAvailablePreKeysCountRequest.h; sourceTree = ""; }; - B6A5D05B1A7827ED0043D837 /* TSAvailablePreKeysCountRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAvailablePreKeysCountRequest.m; sourceTree = ""; }; - B6A5D0611A7850180043D837 /* TSCurrentSignedPreKeyRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSCurrentSignedPreKeyRequest.h; sourceTree = ""; }; - B6A5D0621A7850180043D837 /* TSCurrentSignedPreKeyRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSCurrentSignedPreKeyRequest.m; sourceTree = ""; }; - B6AE33BB1A1EB121003DF39D /* TSGroupModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSGroupModel.h; path = "../../view controllers/TSGroupModel.h"; sourceTree = ""; }; - B6AE33BC1A1EB121003DF39D /* TSGroupModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSGroupModel.m; path = "../../view controllers/TSGroupModel.m"; sourceTree = ""; }; - B6B095DE1A1D25C5008BFAA6 /* CryptographyTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CryptographyTests.mm; sourceTree = ""; }; - B6B095DF1A1D25C5008BFAA6 /* TextSecureKitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TextSecureKitTests.m; sourceTree = ""; }; - B6B095E01A1D25C5008BFAA6 /* TSMessageStorageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSMessageStorageTests.m; sourceTree = ""; }; - B6B095E11A1D25C5008BFAA6 /* TSStorageIdentityKeyStoreTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSStorageIdentityKeyStoreTests.m; sourceTree = ""; }; - B6B095E21A1D25C5008BFAA6 /* TSStoragePreKeyStoreTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSStoragePreKeyStoreTests.m; sourceTree = ""; }; - B6B095E31A1D25C5008BFAA6 /* TSStorageSignedPreKeyStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSStorageSignedPreKeyStore.m; sourceTree = ""; }; - B6B095EC1A1D25ED008BFAA6 /* TSAccountManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSAccountManager.h; sourceTree = ""; }; - B6B095ED1A1D25ED008BFAA6 /* TSAccountManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAccountManager.m; sourceTree = ""; }; - B6B095F01A1D25ED008BFAA6 /* TSPreKeyManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSPreKeyManager.h; sourceTree = ""; }; - B6B095F11A1D25ED008BFAA6 /* TSPreKeyManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSPreKeyManager.m; sourceTree = ""; }; - B6B095F41A1D25ED008BFAA6 /* TSContactThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSContactThread.h; sourceTree = ""; }; - B6B095F51A1D25ED008BFAA6 /* TSContactThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSContactThread.m; sourceTree = ""; }; - B6B095F61A1D25ED008BFAA6 /* TSGroupThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSGroupThread.h; sourceTree = ""; }; - B6B095F71A1D25ED008BFAA6 /* TSGroupThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSGroupThread.m; sourceTree = ""; }; - B6B095FC1A1D25ED008BFAA6 /* SignalRecipient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SignalRecipient.h; sourceTree = ""; }; - B6B095FD1A1D25ED008BFAA6 /* SignalRecipient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalRecipient.m; sourceTree = ""; }; - B6B095FE1A1D25ED008BFAA6 /* TSThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSThread.h; path = ../TSThread.h; sourceTree = ""; }; - B6B095FF1A1D25ED008BFAA6 /* TSThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSThread.m; path = ../TSThread.m; sourceTree = ""; }; - B6B096011A1D25ED008BFAA6 /* IncomingPushMessageSignal.pb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IncomingPushMessageSignal.pb.h; sourceTree = ""; }; - B6B096021A1D25ED008BFAA6 /* IncomingPushMessageSignal.pb.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IncomingPushMessageSignal.pb.m; sourceTree = ""; }; - B6B096031A1D25ED008BFAA6 /* TSAttachment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSAttachment.h; sourceTree = ""; }; - B6B096041A1D25ED008BFAA6 /* TSAttachment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAttachment.m; sourceTree = ""; }; - B6B096051A1D25ED008BFAA6 /* TSCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSCall.h; sourceTree = ""; }; - B6B096061A1D25ED008BFAA6 /* TSCall.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSCall.m; sourceTree = ""; }; - B6B096071A1D25ED008BFAA6 /* TSErrorMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSErrorMessage.h; sourceTree = ""; }; - B6B096081A1D25ED008BFAA6 /* TSErrorMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSErrorMessage.m; sourceTree = ""; }; - B6B0960B1A1D25ED008BFAA6 /* TSIncomingMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSIncomingMessage.h; sourceTree = ""; }; - B6B0960C1A1D25ED008BFAA6 /* TSIncomingMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSIncomingMessage.m; sourceTree = ""; }; - B6B0960D1A1D25ED008BFAA6 /* TSInfoMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSInfoMessage.h; sourceTree = ""; }; - B6B0960E1A1D25ED008BFAA6 /* TSInfoMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSInfoMessage.m; sourceTree = ""; }; - B6B0960F1A1D25ED008BFAA6 /* TSInteraction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSInteraction.h; sourceTree = ""; }; - B6B096101A1D25ED008BFAA6 /* TSInteraction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSInteraction.m; sourceTree = ""; }; - B6B096111A1D25ED008BFAA6 /* TSMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSMessage.h; sourceTree = ""; }; - B6B096121A1D25ED008BFAA6 /* TSMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSMessage.m; sourceTree = ""; }; - B6B096131A1D25ED008BFAA6 /* TSMessagesManager+sendMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TSMessagesManager+sendMessages.h"; sourceTree = ""; }; - B6B096141A1D25ED008BFAA6 /* TSMessagesManager+sendMessages.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TSMessagesManager+sendMessages.m"; sourceTree = ""; }; - B6B096151A1D25ED008BFAA6 /* TSMessagesManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSMessagesManager.h; sourceTree = ""; }; - B6B096161A1D25ED008BFAA6 /* TSMessagesManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSMessagesManager.m; sourceTree = ""; }; - B6B096171A1D25ED008BFAA6 /* TSOutgoingMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSOutgoingMessage.h; sourceTree = ""; }; - B6B096181A1D25ED008BFAA6 /* TSOutgoingMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSOutgoingMessage.m; sourceTree = ""; }; - B6B096191A1D25ED008BFAA6 /* TSServerMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSServerMessage.h; sourceTree = ""; }; - B6B0961A1A1D25ED008BFAA6 /* TSServerMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSServerMessage.m; sourceTree = ""; }; - B6B0963C1A1D25ED008BFAA6 /* SecurityUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecurityUtils.h; sourceTree = ""; }; - B6B0963D1A1D25ED008BFAA6 /* SecurityUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecurityUtils.m; sourceTree = ""; }; - B6B096401A1D25ED008BFAA6 /* TSStorageManager+IdentityKeyStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TSStorageManager+IdentityKeyStore.h"; sourceTree = ""; }; - B6B096411A1D25ED008BFAA6 /* TSStorageManager+IdentityKeyStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TSStorageManager+IdentityKeyStore.m"; sourceTree = ""; }; - B6B096421A1D25ED008BFAA6 /* TSStorageManager+keyFromIntLong.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TSStorageManager+keyFromIntLong.h"; sourceTree = ""; }; - B6B096431A1D25ED008BFAA6 /* TSStorageManager+keyFromIntLong.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TSStorageManager+keyFromIntLong.m"; sourceTree = ""; }; - B6B096441A1D25ED008BFAA6 /* TSStorageManager+PreKeyStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TSStorageManager+PreKeyStore.h"; sourceTree = ""; }; - B6B096451A1D25ED008BFAA6 /* TSStorageManager+PreKeyStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TSStorageManager+PreKeyStore.m"; sourceTree = ""; }; - B6B096461A1D25ED008BFAA6 /* TSStorageManager+SessionStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TSStorageManager+SessionStore.h"; sourceTree = ""; }; - B6B096471A1D25ED008BFAA6 /* TSStorageManager+SessionStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TSStorageManager+SessionStore.m"; sourceTree = ""; }; - B6B096481A1D25ED008BFAA6 /* TSStorageManager+SignedPreKeyStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TSStorageManager+SignedPreKeyStore.h"; sourceTree = ""; }; - B6B096491A1D25ED008BFAA6 /* TSStorageManager+SignedPreKeyStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TSStorageManager+SignedPreKeyStore.m"; sourceTree = ""; }; - B6B0964A1A1D25ED008BFAA6 /* TSDatabaseView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSDatabaseView.h; sourceTree = ""; }; - B6B0964B1A1D25ED008BFAA6 /* TSDatabaseView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSDatabaseView.m; sourceTree = ""; }; - B6B0964C1A1D25ED008BFAA6 /* TSStorageKeys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSStorageKeys.h; sourceTree = ""; }; - B6B0964D1A1D25ED008BFAA6 /* TSStorageManager+keyingMaterial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TSStorageManager+keyingMaterial.h"; sourceTree = ""; }; - B6B0964E1A1D25ED008BFAA6 /* TSStorageManager+keyingMaterial.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TSStorageManager+keyingMaterial.m"; sourceTree = ""; }; - B6B0964F1A1D25ED008BFAA6 /* TSStorageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSStorageManager.h; sourceTree = ""; }; - B6B096501A1D25ED008BFAA6 /* TSStorageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSStorageManager.m; sourceTree = ""; }; - B6B096511A1D25ED008BFAA6 /* TSYapDatabaseObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSYapDatabaseObject.h; sourceTree = ""; }; - B6B096521A1D25ED008BFAA6 /* TSYapDatabaseObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSYapDatabaseObject.m; sourceTree = ""; }; - B6B096531A1D25ED008BFAA6 /* TSConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSConstants.h; sourceTree = ""; }; - B6B096551A1D25ED008BFAA6 /* Cryptography.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Cryptography.h; sourceTree = ""; }; - B6B096561A1D25ED008BFAA6 /* Cryptography.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Cryptography.m; sourceTree = ""; }; - B6B096571A1D25ED008BFAA6 /* NSData+Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+Base64.h"; sourceTree = ""; }; - B6B096581A1D25ED008BFAA6 /* NSData+Base64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+Base64.m"; sourceTree = ""; }; - B6B096591A1D25ED008BFAA6 /* NSData+hexString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+hexString.h"; sourceTree = ""; }; - B6B0965A1A1D25ED008BFAA6 /* NSData+hexString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+hexString.m"; sourceTree = ""; }; - B6B0965B1A1D25ED008BFAA6 /* NSData+messagePadding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+messagePadding.h"; sourceTree = ""; }; - B6B0965C1A1D25ED008BFAA6 /* NSData+messagePadding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+messagePadding.m"; sourceTree = ""; }; - B6B0965F1A1D25ED008BFAA6 /* NSURLSessionDataTask+StatusCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURLSessionDataTask+StatusCode.h"; sourceTree = ""; }; - B6B096601A1D25ED008BFAA6 /* NSURLSessionDataTask+StatusCode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURLSessionDataTask+StatusCode.m"; sourceTree = ""; }; B6B1013A196D213F007E3930 /* SignalKeyingStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SignalKeyingStorage.h; sourceTree = ""; }; B6B1013B196D213F007E3930 /* SignalKeyingStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SignalKeyingStorage.m; sourceTree = ""; }; B6B226961BE4B7D200860F4D /* ContactsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ContactsUI.framework; path = System/Library/Frameworks/ContactsUI.framework; sourceTree = SDKROOT; }; B6B226981BE4C59200860F4D /* APNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APNavigationController.h; sourceTree = ""; }; B6B226991BE4C59200860F4D /* APNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APNavigationController.m; sourceTree = ""; }; - B6B50AA91A4192C500F8F607 /* TSMessagesManager+attachments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TSMessagesManager+attachments.h"; sourceTree = ""; }; - B6B50AAA1A4192C500F8F607 /* TSMessagesManager+attachments.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TSMessagesManager+attachments.m"; sourceTree = ""; }; + B6B3655F1C286AD2009B72FF /* Signal-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Signal-Bridging-Header.h"; sourceTree = ""; }; B6B9ECFA198B31BA00C620D3 /* PushManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PushManager.h; sourceTree = ""; }; B6B9ECFB198B31BA00C620D3 /* PushManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PushManager.m; sourceTree = ""; }; - B6BADBE21B88CB940086A80D /* TSUpdateAttributesRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSUpdateAttributesRequest.h; sourceTree = ""; }; - B6BADBE31B88CB940086A80D /* TSUpdateAttributesRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSUpdateAttributesRequest.m; sourceTree = ""; }; B6BADBE51B88D1AC0086A80D /* LockInteractionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LockInteractionController.h; sourceTree = ""; }; B6BADBE61B88D1AC0086A80D /* LockInteractionController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LockInteractionController.m; sourceTree = ""; }; B6BC3D0C1AA544B100C2907F /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = translations/da.lproj/Localizable.strings; sourceTree = ""; }; B6C6AE531A305ED1006BAF8F /* redphone.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = redphone.cer; sourceTree = ""; }; - B6C6AE541A305ED1006BAF8F /* textsecure.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = textsecure.cer; sourceTree = ""; }; B6C93C4C199567AD00EDF894 /* DebugLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugLogger.h; sourceTree = ""; }; B6C93C4D199567AD00EDF894 /* DebugLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DebugLogger.m; sourceTree = ""; }; + B6D3CBCE1C1376BE00C039DF /* TSContentAdapters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSContentAdapters.h; sourceTree = ""; }; B6DA6B051B8A2F9A00CA6F98 /* AppStoreRating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppStoreRating.h; sourceTree = ""; }; B6DA6B061B8A2F9A00CA6F98 /* AppStoreRating.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppStoreRating.m; sourceTree = ""; }; - B6E314C71A38FAAF00A41AFB /* TSFingerprintGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSFingerprintGenerator.h; sourceTree = ""; }; - B6E314C81A38FAAF00A41AFB /* TSFingerprintGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSFingerprintGenerator.m; sourceTree = ""; }; - B6E4ECF41C0106DF0014E766 /* ContactsManager+updater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ContactsManager+updater.h"; sourceTree = ""; }; - B6E4ECF51C0106DF0014E766 /* ContactsManager+updater.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ContactsManager+updater.m"; sourceTree = ""; }; B6F509961AA53F760068F56A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = translations/en.lproj/Localizable.strings; sourceTree = ""; }; - B6FAAAE61A41BC6C007FEC1D /* TSAttachmentPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSAttachmentPointer.h; path = Attachements/TSAttachmentPointer.h; sourceTree = ""; }; - B6FAAAE71A41BC6C007FEC1D /* TSAttachmentPointer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSAttachmentPointer.m; path = Attachements/TSAttachmentPointer.m; sourceTree = ""; }; - B6FAAAEC1A41C918007FEC1D /* TSAttachmentStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSAttachmentStream.h; path = Attachements/TSAttachmentStream.h; sourceTree = ""; }; - B6FAAAED1A41C918007FEC1D /* TSAttachmentStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSAttachmentStream.m; path = Attachements/TSAttachmentStream.m; sourceTree = ""; }; B6FE7EB61ADD62FA00A6D22F /* PushKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PushKit.framework; path = System/Library/Frameworks/PushKit.framework; sourceTree = SDKROOT; }; - B6FE7EB81ADD63AE00A6D22F /* NSData+ows_StripToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+ows_StripToken.h"; sourceTree = ""; }; - B6FE7EB91ADD63AE00A6D22F /* NSData+ows_StripToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+ows_StripToken.m"; sourceTree = ""; }; B90418E4183E9DD40038554A /* DateUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DateUtil.h; sourceTree = ""; }; B90418E5183E9DD40038554A /* DateUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DateUtil.m; sourceTree = ""; }; B97940251832BD2400BD66CB /* UIUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIUtil.h; sourceTree = ""; }; @@ -1095,13 +899,11 @@ B97CBFA518860EA3008E0DE9 /* CountryCodeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CountryCodeViewController.h; sourceTree = ""; }; B97CBFA618860EA3008E0DE9 /* CountryCodeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CountryCodeViewController.m; sourceTree = ""; }; B9EB5ABC1884C002007CBB57 /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; }; - BF8C3D8219CE3B6A008F644C /* RecentCallTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RecentCallTest.m; sourceTree = ""; }; - BFB074BF19A4BCA400F2947C /* FutureUtilTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FutureUtilTest.m; sourceTree = ""; }; - BFB074C019A4BCA400F2947C /* ObservableTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObservableTest.m; sourceTree = ""; }; BFB074C319A5611000F2947C /* FutureUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FutureUtil.h; sourceTree = ""; }; BFB074C419A5611000F2947C /* FutureUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FutureUtil.m; sourceTree = ""; }; BFB074C519A5611000F2947C /* ObservableValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObservableValue.h; sourceTree = ""; }; BFB074C619A5611000F2947C /* ObservableValue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObservableValue.m; sourceTree = ""; }; + D124A70602BD07D5F1EE5FD8 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; D2179CFB16BB0B3A0006F3AB /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; }; D2179CFD16BB0B480006F3AB /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; D221A089169C9E5E00537ABF /* Signal.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Signal.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1115,14 +917,12 @@ D221A0E7169DFFC500537ABF /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = ../../../../../../System/Library/Frameworks/AVFoundation.framework; sourceTree = ""; }; D24B5BD4169F568C00681372 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = ../../../../../../System/Library/Frameworks/AudioToolbox.framework; sourceTree = ""; }; D2AEACDB16C426DA00C364C0 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - D488327B732CFBE8349C7024 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; E16E5BE818AAC40200B7C403 /* EC25KeyAgreementParticipant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EC25KeyAgreementParticipant.h; sourceTree = ""; }; E16E5BE918AAC40200B7C403 /* EC25KeyAgreementParticipant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EC25KeyAgreementParticipant.m; sourceTree = ""; }; E16E5BEA18AAC40200B7C403 /* EC25KeyAgreementProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EC25KeyAgreementProtocol.h; sourceTree = ""; }; E16E5BEB18AAC40200B7C403 /* EC25KeyAgreementProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EC25KeyAgreementProtocol.m; sourceTree = ""; }; E16E5BEC18AAC40200B7C403 /* EvpKeyAgreement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EvpKeyAgreement.h; sourceTree = ""; }; E16E5BED18AAC40200B7C403 /* EvpKeyAgreement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EvpKeyAgreement.m; sourceTree = ""; }; - E16E5BF818AAF02100B7C403 /* EC25AgreerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EC25AgreerTest.m; sourceTree = ""; }; E18AB40718A05754001A532A /* busy.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = busy.mp3; sourceTree = ""; }; E18AB40818A05754001A532A /* completed.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = completed.mp3; sourceTree = ""; }; E18AB40918A05754001A532A /* failure.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = failure.mp3; sourceTree = ""; }; @@ -1247,7 +1047,7 @@ D221A090169C9E5E00537ABF /* Foundation.framework in Frameworks */, D221A0E8169DFFC500537ABF /* AVFoundation.framework in Frameworks */, D24B5BD5169F568C00681372 /* AudioToolbox.framework in Frameworks */, - 28508611F3DF531CEDF5103D /* libPods.a in Frameworks */, + CF6B0CD2D27A0FE420224EE9 /* libPods.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1255,6 +1055,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B660F6E91C29938A00687D6E /* libTwistedOakCollapsingFutures.a in Frameworks */, B60EDE041A05A01700D73516 /* AudioToolbox.framework in Frameworks */, B69CD25119773E79005CE69A /* XCTest.framework in Frameworks */, E1368CBE18A1C36B00109378 /* MessageUI.framework in Frameworks */, @@ -1270,11 +1071,7 @@ D202868116DBE0E7009068E9 /* CFNetwork.framework in Frameworks */, D221A0AD169C9E5F00537ABF /* UIKit.framework in Frameworks */, D221A0AE169C9E5F00537ABF /* Foundation.framework in Frameworks */, - AA0C8E498E2046B0B81EEE6E /* (null) in Frameworks */, - 53EF5134D8FB5FCBDEDE2A35 /* (null) in Frameworks */, - DE9907A5A8074160B34A8261 /* (null) in Frameworks */, - 7FAA7C04BD50D54101D1BB1A /* (null) in Frameworks */, - 057B54FA6208D8269CFE6146 /* libPods.a in Frameworks */, + 4B552ED26FB6FB54EDDBB7BD /* libPods.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1321,14 +1118,6 @@ path = crypto; sourceTree = ""; }; - 76919BF51805D169008C664A /* contact */ = { - isa = PBXGroup; - children = ( - 76919BF61805D190008C664A /* ContactManagerTest.m */, - ); - name = contact; - sourceTree = ""; - }; 76EB03C118170B33006006FC /* src */ = { isa = PBXGroup; children = ( @@ -1343,7 +1132,6 @@ 76EB041D18170B33006006FC /* network */, 70BAFD5B190584BE00FA5E0B /* NotificationTracker.h */, 70BAFD5C190584BE00FA5E0B /* NotificationTracker.m */, - B6B095EA1A1D25ED008BFAA6 /* textsecure */, 76EB048818170B33006006FC /* phone */, 76EB04B118170B33006006FC /* profiling */, 76EB04C818170B33006006FC /* util */, @@ -1386,12 +1174,8 @@ isa = PBXGroup; children = ( 76EB04A818170B33006006FC /* number directory */, - 76EB040418170B33006006FC /* Contact.h */, - 76EB040518170B33006006FC /* Contact.m */, 76EB040818170B33006006FC /* ContactsManager.h */, 76EB040918170B33006006FC /* ContactsManager.m */, - B6E4ECF41C0106DF0014E766 /* ContactsManager+updater.h */, - B6E4ECF51C0106DF0014E766 /* ContactsManager+updater.m */, ); path = contact; sourceTree = ""; @@ -1399,6 +1183,8 @@ 76EB041118170B33006006FC /* environment */ = { isa = PBXGroup; children = ( + B6258B311C29E2E60014138E /* NotificationsManager.h */, + B6258B321C29E2E60014138E /* NotificationsManager.m */, 76EB041218170B33006006FC /* Environment.h */, 76EB041318170B33006006FC /* Environment.m */, B6C93C4C199567AD00EDF894 /* DebugLogger.h */, @@ -1422,8 +1208,6 @@ 76EB041D18170B33006006FC /* network */ = { isa = PBXGroup; children = ( - B63006411B9631EC00F2FEB5 /* AFSecurityOWSPolicy.h */, - B63006421B9631EC00F2FEB5 /* AFSecurityOWSPolicy.m */, 76EB041E18170B33006006FC /* dns */, 76EB042318170B33006006FC /* failures */, 76EB042818170B33006006FC /* http */, @@ -1634,11 +1418,10 @@ 76EB048818170B33006006FC /* phone */ = { isa = PBXGroup; children = ( + B640BFA51C257823006038B3 /* Account */, 76EB048918170B33006006FC /* callstate */, 76EB049418170B33006006FC /* PhoneManager.h */, 76EB049518170B33006006FC /* PhoneManager.m */, - 76EB049618170B33006006FC /* PhoneNumber.h */, - 76EB049718170B33006006FC /* PhoneNumber.m */, 76EB049818170B33006006FC /* signaling */, ); path = phone; @@ -1746,15 +1529,10 @@ B68EF9B51C0B1E7D009C3DCD /* Animated GIFS */, B6DA6B051B8A2F9A00CA6F98 /* AppStoreRating.h */, B6DA6B061B8A2F9A00CA6F98 /* AppStoreRating.m */, - B6FE7EB81ADD63AE00A6D22F /* NSData+ows_StripToken.h */, - B6FE7EB91ADD63AE00A6D22F /* NSData+ows_StripToken.m */, - A59E6D701A79E5D100D98E2E /* MIMETypeUtil.h */, - A59E6D711A79E5D100D98E2E /* MIMETypeUtil.m */, FCFA64B11A24F29E0007FB87 /* UI Categories */, 76EB04C918170B33006006FC /* ArrayUtil.h */, 76EB04CA18170B33006006FC /* ArrayUtil.m */, 76EB04CF18170B33006006FC /* collections */, - 76EB04D618170B33006006FC /* constraints */, 76EB04E018170B33006006FC /* Conversions.h */, 76EB04E118170B33006006FC /* Conversions.m */, 76EB04E218170B33006006FC /* Crc32.h */, @@ -1775,8 +1553,6 @@ BFB074C619A5611000F2947C /* ObservableValue.m */, 76EB04EE18170B33006006FC /* Operation.h */, 76EB04EF18170B33006006FC /* Operation.m */, - 7095B7AE18F46D35002C66E2 /* PhoneNumberUtil.h */, - 7095B7AF18F46D35002C66E2 /* PhoneNumberUtil.m */, 76EB04F018170B33006006FC /* protocols */, 76EB04F518170B33006006FC /* StringUtil.h */, 76EB04F618170B33006006FC /* StringUtil.m */, @@ -1793,6 +1569,8 @@ FCC81A971A44558300DFEC7D /* UIDevice+TSHardwareVersion.m */, FC7C7A941A581AF40091823B /* TSAdapterCacheManager.h */, FC7C7A951A581AF40091823B /* TSAdapterCacheManager.m */, + B62F5E0E1C2980B4000D370C /* NSData+ows_StripToken.h */, + B62F5E0F1C2980B4000D370C /* NSData+ows_StripToken.m */, ); path = util; sourceTree = ""; @@ -1810,27 +1588,9 @@ path = collections; sourceTree = ""; }; - 76EB04D618170B33006006FC /* constraints */ = { - isa = PBXGroup; - children = ( - 76EB04D718170B33006006FC /* BadArgument.h */, - 76EB04D818170B33006006FC /* BadArgument.m */, - 76EB04D918170B33006006FC /* BadState.h */, - 76EB04DA18170B33006006FC /* BadState.m */, - 76EB04DB18170B33006006FC /* Constraints.h */, - 76EB04DC18170B33006006FC /* OperationFailed.h */, - 76EB04DD18170B33006006FC /* OperationFailed.m */, - 76EB04DE18170B33006006FC /* SecurityFailure.h */, - 76EB04DF18170B33006006FC /* SecurityFailure.m */, - ); - path = constraints; - sourceTree = ""; - }; 76EB04F018170B33006006FC /* protocols */ = { isa = PBXGroup; children = ( - B63885CE1A2685D700A226A6 /* PreKeyBundle+jsonDict.h */, - B63885CF1A2685D700A226A6 /* PreKeyBundle+jsonDict.m */, 76EB04F118170B33006006FC /* Terminable.h */, 76EB04F218170B33006006FC /* utilities */, ); @@ -1888,195 +1648,6 @@ path = xibs; sourceTree = ""; }; - A15706EA17F0CD6D007C2BD6 /* test */ = { - isa = PBXGroup; - children = ( - A15706F217F0CD6D007C2BD6 /* audio */, - BF8C3D8119CE3B6A008F644C /* call */, - 76919BF51805D169008C664A /* contact */, - A157070017F0CD6D007C2BD6 /* network */, - A157072E17F0CD6D007C2BD6 /* phone */, - A157073417F0CD6D007C2BD6 /* profiling */, - A157073917F0CD6D007C2BD6 /* Supporting Files */, - B6B095DD1A1D25C5008BFAA6 /* textsecure */, - A157073D17F0CD6D007C2BD6 /* util */, - B684A46C19C3446200B11029 /* PushManagerTest.m */, - A157073B17F0CD6D007C2BD6 /* TestUtil.h */, - A157073C17F0CD6D007C2BD6 /* TestUtil.m */, - ); - path = test; - sourceTree = ""; - }; - A15706F217F0CD6D007C2BD6 /* audio */ = { - isa = PBXGroup; - children = ( - A15706F417F0CD6D007C2BD6 /* AudioFrameTest.m */, - A15706F617F0CD6D007C2BD6 /* AudioRemoteIOTest.m */, - A15706F817F0CD6D007C2BD6 /* AudioStretcherTest.m */, - A15706FA17F0CD6D007C2BD6 /* JitterQueueTest.m */, - A15706FC17F0CD6D007C2BD6 /* SpeexCodecTest.m */, - ); - path = audio; - sourceTree = ""; - }; - A157070017F0CD6D007C2BD6 /* network */ = { - isa = PBXGroup; - children = ( - A157070117F0CD6D007C2BD6 /* dns */, - A157070417F0CD6D007C2BD6 /* http */, - A157070817F0CD6D007C2BD6 /* IpAddressTest.m */, - A157070A17F0CD6D007C2BD6 /* IpEndPointTest.m */, - A157070B17F0CD6D007C2BD6 /* rtp */, - A157072317F0CD6D007C2BD6 /* tcp */, - A157072B17F0CD6D007C2BD6 /* udp */, - ); - path = network; - sourceTree = ""; - }; - A157070117F0CD6D007C2BD6 /* dns */ = { - isa = PBXGroup; - children = ( - A157070317F0CD6D007C2BD6 /* DnsManagerTest.m */, - ); - path = dns; - sourceTree = ""; - }; - A157070417F0CD6D007C2BD6 /* http */ = { - isa = PBXGroup; - children = ( - A157070617F0CD6D007C2BD6 /* HttpRequestResponseTest.m */, - ); - path = http; - sourceTree = ""; - }; - A157070B17F0CD6D007C2BD6 /* rtp */ = { - isa = PBXGroup; - children = ( - A157070D17F0CD6D007C2BD6 /* RtpPacketTests.m */, - A157070E17F0CD6D007C2BD6 /* srtp */, - A157071317F0CD6D007C2BD6 /* zrtp */, - ); - path = rtp; - sourceTree = ""; - }; - A157070E17F0CD6D007C2BD6 /* srtp */ = { - isa = PBXGroup; - children = ( - A157071017F0CD6D007C2BD6 /* SecureStreamTest.m */, - A157071217F0CD6D007C2BD6 /* SequenceCounterTest.m */, - ); - path = srtp; - sourceTree = ""; - }; - A157071317F0CD6D007C2BD6 /* zrtp */ = { - isa = PBXGroup; - children = ( - A157071717F0CD6D007C2BD6 /* HandshakePacketTest.m */, - A157071917F0CD6D007C2BD6 /* HashChainTest.m */, - A157071B17F0CD6D007C2BD6 /* MasterSecretTest.m */, - A157071D17F0CD6D007C2BD6 /* ShortAuthenticationStringGeneratorTest.m */, - A157071E17F0CD6D007C2BD6 /* utilities */, - A157072217F0CD6D007C2BD6 /* ZrtpTest.m */, - E16E5BF818AAF02100B7C403 /* EC25AgreerTest.m */, - ); - path = zrtp; - sourceTree = ""; - }; - A157071E17F0CD6D007C2BD6 /* utilities */ = { - isa = PBXGroup; - children = ( - A157071F17F0CD6D007C2BD6 /* PregeneratedKeyAgreementParticipantProtocol.h */, - A157072017F0CD6D007C2BD6 /* PregeneratedKeyAgreementParticipantProtocol.m */, - ); - path = utilities; - sourceTree = ""; - }; - A157072317F0CD6D007C2BD6 /* tcp */ = { - isa = PBXGroup; - children = ( - A157072517F0CD6D007C2BD6 /* LowLatencyConnectorTest.m */, - A157072617F0CD6D007C2BD6 /* tls */, - ); - path = tcp; - sourceTree = ""; - }; - A157072617F0CD6D007C2BD6 /* tls */ = { - isa = PBXGroup; - children = ( - A157072817F0CD6D007C2BD6 /* NetworkStreamTest.m */, - A157072A17F0CD6D007C2BD6 /* SecureEndPointTest.m */, - ); - path = tls; - sourceTree = ""; - }; - A157072B17F0CD6D007C2BD6 /* udp */ = { - isa = PBXGroup; - children = ( - A157072D17F0CD6D007C2BD6 /* UdpSocketTest.m */, - ); - path = udp; - sourceTree = ""; - }; - A157072E17F0CD6D007C2BD6 /* phone */ = { - isa = PBXGroup; - children = ( - A157073017F0CD6D007C2BD6 /* PhoneNumberTest.m */, - A157073117F0CD6D007C2BD6 /* signaling */, - ); - path = phone; - sourceTree = ""; - }; - A157073117F0CD6D007C2BD6 /* signaling */ = { - isa = PBXGroup; - children = ( - A157073317F0CD6D007C2BD6 /* SessionDescriptorTest.m */, - ); - path = signaling; - sourceTree = ""; - }; - A157073417F0CD6D007C2BD6 /* profiling */ = { - isa = PBXGroup; - children = ( - A157073617F0CD6D007C2BD6 /* DecayingSampleEstimatorTest.m */, - A157073817F0CD6D007C2BD6 /* EventWindowTest.m */, - ); - path = profiling; - sourceTree = ""; - }; - A157073917F0CD6D007C2BD6 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - B6850E591995A4710068E715 /* whisperFake.cer */, - A157073A17F0CD6D007C2BD6 /* SignalTests-Info.plist */, - ); - path = "Supporting Files"; - sourceTree = ""; - }; - A157073D17F0CD6D007C2BD6 /* util */ = { - isa = PBXGroup; - children = ( - A157074217F0CD6D007C2BD6 /* ConversionsTest.h */, - A157074317F0CD6D007C2BD6 /* ConversionsTest.m */, - A157074417F0CD6D007C2BD6 /* Crc32Test.h */, - A157074517F0CD6D007C2BD6 /* Crc32Test.m */, - A157074717F0CD6D007C2BD6 /* CryptoToolsTest.m */, - A157074817F0CD6D007C2BD6 /* CyclicalBufferTest.h */, - A157074917F0CD6D007C2BD6 /* CyclicalBufferTest.m */, - A157074A17F0CD6D007C2BD6 /* ExceptionsTest.h */, - A157074B17F0CD6D007C2BD6 /* ExceptionsTest.m */, - A157074C17F0CD6D007C2BD6 /* FunctionalUtilTest.h */, - A157074D17F0CD6D007C2BD6 /* FunctionalUtilTest.m */, - BFB074BF19A4BCA400F2947C /* FutureUtilTest.m */, - BFB074C019A4BCA400F2947C /* ObservableTest.m */, - A157074F17F0CD6D007C2BD6 /* PriorityQueueTest.m */, - A157075017F0CD6D007C2BD6 /* QueueTest.h */, - A157075117F0CD6D007C2BD6 /* QueueTest.m */, - A157075217F0CD6D007C2BD6 /* UtilTest.h */, - A157075317F0CD6D007C2BD6 /* UtilTest.m */, - ); - path = util; - sourceTree = ""; - }; B62D53F41A23CC8B009AAF82 /* TSMessageAdapters */ = { isa = PBXGroup; children = ( @@ -2088,23 +1659,11 @@ 4CE0E3761B954546007210CF /* TSAnimatedAdapter.m */, B62D53F51A23CCAD009AAF82 /* TSMessageAdapter.h */, B62D53F61A23CCAD009AAF82 /* TSMessageAdapter.m */, + B6D3CBCE1C1376BE00C039DF /* TSContentAdapters.h */, ); name = TSMessageAdapters; sourceTree = ""; }; - B62EFBE51A91352F0072ADD3 /* InvalidKeyMessages */ = { - isa = PBXGroup; - children = ( - B62EFBE61A91352F0072ADD3 /* TSInvalidIdentityKeyErrorMessage.h */, - B62EFBE71A91352F0072ADD3 /* TSInvalidIdentityKeyErrorMessage.m */, - B62EFBE81A91352F0072ADD3 /* TSInvalidIdentityKeyReceivingErrorMessage.h */, - B62EFBE91A91352F0072ADD3 /* TSInvalidIdentityKeyReceivingErrorMessage.m */, - B62EFBEA1A91352F0072ADD3 /* TSInvalidIdentityKeySendingErrorMessage.h */, - B62EFBEB1A91352F0072ADD3 /* TSInvalidIdentityKeySendingErrorMessage.m */, - ); - path = InvalidKeyMessages; - sourceTree = ""; - }; B633C4FD1A1D190B0059AC12 /* Images */ = { isa = PBXGroup; children = ( @@ -2136,67 +1695,13 @@ path = Images; sourceTree = ""; }; - B63AF5A91A1F757900D01AAD /* Network */ = { + B640BFA51C257823006038B3 /* Account */ = { isa = PBXGroup; children = ( - B63AF5AA1A1F757900D01AAD /* API */, - B63AF5C41A1F757900D01AAD /* WebSockets */, + B640BFA61C257843006038B3 /* RPAccountManager.h */, + B640BFA71C257843006038B3 /* RPAccountManager.m */, ); - path = Network; - sourceTree = ""; - }; - B63AF5AA1A1F757900D01AAD /* API */ = { - isa = PBXGroup; - children = ( - B63AF5AB1A1F757900D01AAD /* Requests */, - B63AF5C21A1F757900D01AAD /* TSNetworkManager.h */, - B63AF5C31A1F757900D01AAD /* TSNetworkManager.m */, - ); - path = API; - sourceTree = ""; - }; - B63AF5AB1A1F757900D01AAD /* Requests */ = { - isa = PBXGroup; - children = ( - B60FB9A51A46F099006A5A66 /* TSAllocAttachmentRequest.h */, - B60FB9A61A46F099006A5A66 /* TSAllocAttachmentRequest.m */, - B6A5D05A1A7827ED0043D837 /* TSAvailablePreKeysCountRequest.h */, - B6A5D05B1A7827ED0043D837 /* TSAvailablePreKeysCountRequest.m */, - B63AF5AC1A1F757900D01AAD /* TSContactsIntersectionRequest.h */, - B63AF5AD1A1F757900D01AAD /* TSContactsIntersectionRequest.m */, - B6A5D0611A7850180043D837 /* TSCurrentSignedPreKeyRequest.h */, - B6A5D0621A7850180043D837 /* TSCurrentSignedPreKeyRequest.m */, - B63AF5B01A1F757900D01AAD /* TSRecipientPrekeyRequest.h */, - B63AF5B11A1F757900D01AAD /* TSRecipientPrekeyRequest.m */, - B63AF5B21A1F757900D01AAD /* TSRegisterForPushRequest.h */, - B63AF5B31A1F757900D01AAD /* TSRegisterForPushRequest.m */, - B63AF5B41A1F757900D01AAD /* TSRegisterPrekeysRequest.h */, - B63AF5B51A1F757900D01AAD /* TSRegisterPrekeysRequest.m */, - B63AF5B61A1F757900D01AAD /* TSRegisterWithTokenRequest.h */, - B63AF5B71A1F757900D01AAD /* TSRegisterWithTokenRequest.m */, - B63AF5B81A1F757900D01AAD /* TSRequest.h */, - B63AF5B91A1F757900D01AAD /* TSRequest.m */, - B63AF5BA1A1F757900D01AAD /* TSAttachmentRequest.h */, - B63AF5BB1A1F757900D01AAD /* TSAttachmentRequest.m */, - B63AF5BE1A1F757900D01AAD /* TSSubmitMessageRequest.h */, - B63AF5BF1A1F757900D01AAD /* TSSubmitMessageRequest.m */, - B63AF5AE1A1F757900D01AAD /* TSUnregisterAccountRequest.h */, - B63AF5AF1A1F757900D01AAD /* TSUnregisterAccountRequest.m */, - B6BADBE21B88CB940086A80D /* TSUpdateAttributesRequest.h */, - B6BADBE31B88CB940086A80D /* TSUpdateAttributesRequest.m */, - ); - path = Requests; - sourceTree = ""; - }; - B63AF5C41A1F757900D01AAD /* WebSockets */ = { - isa = PBXGroup; - children = ( - B63AF5D61A1F889500D01AAD /* SubProtocol.pb.h */, - B63AF5D71A1F889500D01AAD /* SubProtocol.pb.m */, - B63AF5C51A1F757900D01AAD /* TSSocketManager.h */, - B63AF5C61A1F757900D01AAD /* TSSocketManager.m */, - ); - path = WebSockets; + name = Account; sourceTree = ""; }; B65EDA0F19E1BE2200AAA7CB /* Requests */ = { @@ -2208,6 +1713,218 @@ name = Requests; sourceTree = ""; }; + B660F66C1C29867F00687D6E /* test */ = { + isa = PBXGroup; + children = ( + B660F66D1C29867F00687D6E /* audio */, + B660F6731C29867F00687D6E /* call */, + B660F6751C29867F00687D6E /* contact */, + B660F6771C29867F00687D6E /* network */, + B660F6941C29868000687D6E /* phone */, + B660F6981C29868000687D6E /* profiling */, + B660F69B1C29868000687D6E /* push */, + B660F69D1C29868000687D6E /* Supporting Files */, + B660F6A01C29868000687D6E /* TestUtil.h */, + B660F6A11C29868000687D6E /* TestUtil.m */, + B660F6A21C29868000687D6E /* util */, + ); + path = test; + sourceTree = ""; + }; + B660F66D1C29867F00687D6E /* audio */ = { + isa = PBXGroup; + children = ( + B660F66E1C29867F00687D6E /* AudioFrameTest.m */, + B660F66F1C29867F00687D6E /* AudioRemoteIOTest.m */, + B660F6701C29867F00687D6E /* AudioStretcherTest.m */, + B660F6711C29867F00687D6E /* JitterQueueTest.m */, + B660F6721C29867F00687D6E /* SpeexCodecTest.m */, + ); + path = audio; + sourceTree = ""; + }; + B660F6731C29867F00687D6E /* call */ = { + isa = PBXGroup; + children = ( + B660F6741C29867F00687D6E /* RecentCallTest.m */, + ); + path = call; + sourceTree = ""; + }; + B660F6751C29867F00687D6E /* contact */ = { + isa = PBXGroup; + children = ( + B660F6761C29867F00687D6E /* ContactManagerTest.m */, + ); + path = contact; + sourceTree = ""; + }; + B660F6771C29867F00687D6E /* network */ = { + isa = PBXGroup; + children = ( + B660F6781C29867F00687D6E /* dns */, + B660F67A1C29867F00687D6E /* http */, + B660F67C1C29867F00687D6E /* IpAddressTest.m */, + B660F67D1C29867F00687D6E /* IpEndPointTest.m */, + B660F67E1C29867F00687D6E /* rtp */, + B660F68D1C29867F00687D6E /* tcp */, + B660F6921C29868000687D6E /* udp */, + ); + path = network; + sourceTree = ""; + }; + B660F6781C29867F00687D6E /* dns */ = { + isa = PBXGroup; + children = ( + B660F6791C29867F00687D6E /* DnsManagerTest.m */, + ); + path = dns; + sourceTree = ""; + }; + B660F67A1C29867F00687D6E /* http */ = { + isa = PBXGroup; + children = ( + B660F67B1C29867F00687D6E /* HttpRequestResponseTest.m */, + ); + path = http; + sourceTree = ""; + }; + B660F67E1C29867F00687D6E /* rtp */ = { + isa = PBXGroup; + children = ( + B660F67F1C29867F00687D6E /* RtpPacketTests.m */, + B660F6801C29867F00687D6E /* srtp */, + B660F6831C29867F00687D6E /* zrtp */, + ); + path = rtp; + sourceTree = ""; + }; + B660F6801C29867F00687D6E /* srtp */ = { + isa = PBXGroup; + children = ( + B660F6811C29867F00687D6E /* SecureStreamTest.m */, + B660F6821C29867F00687D6E /* SequenceCounterTest.m */, + ); + path = srtp; + sourceTree = ""; + }; + B660F6831C29867F00687D6E /* zrtp */ = { + isa = PBXGroup; + children = ( + B660F6841C29867F00687D6E /* EC25AgreerTest.m */, + B660F6851C29867F00687D6E /* HandshakePacketTest.m */, + B660F6861C29867F00687D6E /* HashChainTest.m */, + B660F6871C29867F00687D6E /* MasterSecretTest.m */, + B660F6881C29867F00687D6E /* ShortAuthenticationStringGeneratorTest.m */, + B660F6891C29867F00687D6E /* utilities */, + B660F68C1C29867F00687D6E /* ZrtpTest.m */, + ); + path = zrtp; + sourceTree = ""; + }; + B660F6891C29867F00687D6E /* utilities */ = { + isa = PBXGroup; + children = ( + B660F68A1C29867F00687D6E /* PregeneratedKeyAgreementParticipantProtocol.h */, + B660F68B1C29867F00687D6E /* PregeneratedKeyAgreementParticipantProtocol.m */, + ); + path = utilities; + sourceTree = ""; + }; + B660F68D1C29867F00687D6E /* tcp */ = { + isa = PBXGroup; + children = ( + B660F68E1C29867F00687D6E /* LowLatencyConnectorTest.m */, + B660F68F1C29867F00687D6E /* tls */, + ); + path = tcp; + sourceTree = ""; + }; + B660F68F1C29867F00687D6E /* tls */ = { + isa = PBXGroup; + children = ( + B660F6901C29868000687D6E /* NetworkStreamTest.m */, + B660F6911C29868000687D6E /* SecureEndPointTest.m */, + ); + path = tls; + sourceTree = ""; + }; + B660F6921C29868000687D6E /* udp */ = { + isa = PBXGroup; + children = ( + B660F6931C29868000687D6E /* UdpSocketTest.m */, + ); + path = udp; + sourceTree = ""; + }; + B660F6941C29868000687D6E /* phone */ = { + isa = PBXGroup; + children = ( + B660F6951C29868000687D6E /* PhoneNumberTest.m */, + B660F6961C29868000687D6E /* signaling */, + ); + path = phone; + sourceTree = ""; + }; + B660F6961C29868000687D6E /* signaling */ = { + isa = PBXGroup; + children = ( + B660F6971C29868000687D6E /* SessionDescriptorTest.m */, + ); + path = signaling; + sourceTree = ""; + }; + B660F6981C29868000687D6E /* profiling */ = { + isa = PBXGroup; + children = ( + B660F6991C29868000687D6E /* DecayingSampleEstimatorTest.m */, + B660F69A1C29868000687D6E /* EventWindowTest.m */, + ); + path = profiling; + sourceTree = ""; + }; + B660F69B1C29868000687D6E /* push */ = { + isa = PBXGroup; + children = ( + B660F69C1C29868000687D6E /* PushManagerTest.m */, + ); + path = push; + sourceTree = ""; + }; + B660F69D1C29868000687D6E /* Supporting Files */ = { + isa = PBXGroup; + children = ( + B660F69E1C29868000687D6E /* SignalTests-Info.plist */, + B660F69F1C29868000687D6E /* whisperFake.cer */, + ); + path = "Supporting Files"; + sourceTree = ""; + }; + B660F6A21C29868000687D6E /* util */ = { + isa = PBXGroup; + children = ( + B660F6A31C29868000687D6E /* ConversionsTest.h */, + B660F6A41C29868000687D6E /* ConversionsTest.m */, + B660F6A51C29868000687D6E /* Crc32Test.h */, + B660F6A61C29868000687D6E /* Crc32Test.m */, + B660F6A71C29868000687D6E /* CryptoToolsTest.m */, + B660F6A81C29868000687D6E /* CyclicalBufferTest.h */, + B660F6A91C29868000687D6E /* CyclicalBufferTest.m */, + B660F6AA1C29868000687D6E /* ExceptionsTest.h */, + B660F6AB1C29868000687D6E /* ExceptionsTest.m */, + B660F6AC1C29868000687D6E /* FunctionalUtilTest.h */, + B660F6AD1C29868000687D6E /* FunctionalUtilTest.m */, + B660F6AE1C29868000687D6E /* FutureUtilTest.m */, + B660F6AF1C29868000687D6E /* ObservableTest.m */, + B660F6B01C29868000687D6E /* PriorityQueueTest.m */, + B660F6B11C29868000687D6E /* QueueTest.h */, + B660F6B21C29868000687D6E /* QueueTest.m */, + B660F6B31C29868000687D6E /* UtilTest.h */, + B660F6B41C29868000687D6E /* UtilTest.m */, + ); + path = util; + sourceTree = ""; + }; B68EF9B51C0B1E7D009C3DCD /* Animated GIFS */ = { isa = PBXGroup; children = ( @@ -2219,182 +1936,6 @@ name = "Animated GIFS"; sourceTree = ""; }; - B6B095DD1A1D25C5008BFAA6 /* textsecure */ = { - isa = PBXGroup; - children = ( - B65031CE1A7862AA002EBBBD /* SignedPreKeyDeletionTests.m */, - B6B095DE1A1D25C5008BFAA6 /* CryptographyTests.mm */, - B6B095DF1A1D25C5008BFAA6 /* TextSecureKitTests.m */, - B6B095E01A1D25C5008BFAA6 /* TSMessageStorageTests.m */, - B6B095E11A1D25C5008BFAA6 /* TSStorageIdentityKeyStoreTests.m */, - B6B095E21A1D25C5008BFAA6 /* TSStoragePreKeyStoreTests.m */, - B6B095E31A1D25C5008BFAA6 /* TSStorageSignedPreKeyStore.m */, - B640C4761A477B0F005C7C8A /* TSAttachementsTest.m */, - B617E9231A9F962600753F00 /* MessagePaddingTests.m */, - ); - path = textsecure; - sourceTree = ""; - }; - B6B095EA1A1D25ED008BFAA6 /* textsecure */ = { - isa = PBXGroup; - children = ( - B6B095EB1A1D25ED008BFAA6 /* Account */, - B6B095F21A1D25ED008BFAA6 /* Contacts */, - B6B096001A1D25ED008BFAA6 /* Messages */, - B63AF5A91A1F757900D01AAD /* Network */, - B6B0963B1A1D25ED008BFAA6 /* Security */, - B6B0963E1A1D25ED008BFAA6 /* Storage */, - B6B096531A1D25ED008BFAA6 /* TSConstants.h */, - B6B096541A1D25ED008BFAA6 /* Util */, - ); - path = textsecure; - sourceTree = ""; - }; - B6B095EB1A1D25ED008BFAA6 /* Account */ = { - isa = PBXGroup; - children = ( - B675C16A1B891B3900A7A87A /* TSAttributes.h */, - B675C16B1B891B3900A7A87A /* TSAttributes.m */, - B6B095EC1A1D25ED008BFAA6 /* TSAccountManager.h */, - B6B095ED1A1D25ED008BFAA6 /* TSAccountManager.m */, - B6B095F01A1D25ED008BFAA6 /* TSPreKeyManager.h */, - B6B095F11A1D25ED008BFAA6 /* TSPreKeyManager.m */, - ); - path = Account; - sourceTree = ""; - }; - B6B095F21A1D25ED008BFAA6 /* Contacts */ = { - isa = PBXGroup; - children = ( - B6B095F31A1D25ED008BFAA6 /* Threads */, - B6B095FC1A1D25ED008BFAA6 /* SignalRecipient.h */, - B6B095FD1A1D25ED008BFAA6 /* SignalRecipient.m */, - ); - path = Contacts; - sourceTree = ""; - }; - B6B095F31A1D25ED008BFAA6 /* Threads */ = { - isa = PBXGroup; - children = ( - B6B095F41A1D25ED008BFAA6 /* TSContactThread.h */, - B6B095F51A1D25ED008BFAA6 /* TSContactThread.m */, - B6B095F61A1D25ED008BFAA6 /* TSGroupThread.h */, - B6B095F71A1D25ED008BFAA6 /* TSGroupThread.m */, - B6B095FE1A1D25ED008BFAA6 /* TSThread.h */, - B6B095FF1A1D25ED008BFAA6 /* TSThread.m */, - ); - path = Threads; - sourceTree = ""; - }; - B6B096001A1D25ED008BFAA6 /* Messages */ = { - isa = PBXGroup; - children = ( - B6FAAAE91A41C7CC007FEC1D /* Attachement */, - B62EFBE51A91352F0072ADD3 /* InvalidKeyMessages */, - B6B096011A1D25ED008BFAA6 /* IncomingPushMessageSignal.pb.h */, - B6B096021A1D25ED008BFAA6 /* IncomingPushMessageSignal.pb.m */, - B6B096051A1D25ED008BFAA6 /* TSCall.h */, - B6B096061A1D25ED008BFAA6 /* TSCall.m */, - B6B096071A1D25ED008BFAA6 /* TSErrorMessage.h */, - B68B0E8D1A542AD700DE8A02 /* TSErrorMessage_privateConstructor.h */, - B6B096081A1D25ED008BFAA6 /* TSErrorMessage.m */, - B6B0960B1A1D25ED008BFAA6 /* TSIncomingMessage.h */, - B6B0960C1A1D25ED008BFAA6 /* TSIncomingMessage.m */, - B6B0960D1A1D25ED008BFAA6 /* TSInfoMessage.h */, - B6B0960E1A1D25ED008BFAA6 /* TSInfoMessage.m */, - B6B0960F1A1D25ED008BFAA6 /* TSInteraction.h */, - B6B096101A1D25ED008BFAA6 /* TSInteraction.m */, - B6AE33BB1A1EB121003DF39D /* TSGroupModel.h */, - B6AE33BC1A1EB121003DF39D /* TSGroupModel.m */, - B6B096111A1D25ED008BFAA6 /* TSMessage.h */, - B6B096121A1D25ED008BFAA6 /* TSMessage.m */, - B6B50AA91A4192C500F8F607 /* TSMessagesManager+attachments.h */, - B6B50AAA1A4192C500F8F607 /* TSMessagesManager+attachments.m */, - B6B096131A1D25ED008BFAA6 /* TSMessagesManager+sendMessages.h */, - B6B096141A1D25ED008BFAA6 /* TSMessagesManager+sendMessages.m */, - B6B096151A1D25ED008BFAA6 /* TSMessagesManager.h */, - B6B096161A1D25ED008BFAA6 /* TSMessagesManager.m */, - B6B096171A1D25ED008BFAA6 /* TSOutgoingMessage.h */, - B6B096181A1D25ED008BFAA6 /* TSOutgoingMessage.m */, - B6B096191A1D25ED008BFAA6 /* TSServerMessage.h */, - B6B0961A1A1D25ED008BFAA6 /* TSServerMessage.m */, - ); - path = Messages; - sourceTree = ""; - }; - B6B0963B1A1D25ED008BFAA6 /* Security */ = { - isa = PBXGroup; - children = ( - B6B0963C1A1D25ED008BFAA6 /* SecurityUtils.h */, - B6B0963D1A1D25ED008BFAA6 /* SecurityUtils.m */, - B6E314C71A38FAAF00A41AFB /* TSFingerprintGenerator.h */, - B6E314C81A38FAAF00A41AFB /* TSFingerprintGenerator.m */, - ); - path = Security; - sourceTree = ""; - }; - B6B0963E1A1D25ED008BFAA6 /* Storage */ = { - isa = PBXGroup; - children = ( - B6B0963F1A1D25ED008BFAA6 /* AxolotlStore */, - B6B0964A1A1D25ED008BFAA6 /* TSDatabaseView.h */, - B6B0964B1A1D25ED008BFAA6 /* TSDatabaseView.m */, - B692BF051A76EF0F002786DA /* TSDatabaseSecondaryIndexes.h */, - B692BF061A76EF0F002786DA /* TSDatabaseSecondaryIndexes.m */, - B6B0964C1A1D25ED008BFAA6 /* TSStorageKeys.h */, - B6B0964D1A1D25ED008BFAA6 /* TSStorageManager+keyingMaterial.h */, - B6B0964E1A1D25ED008BFAA6 /* TSStorageManager+keyingMaterial.m */, - B6B0964F1A1D25ED008BFAA6 /* TSStorageManager.h */, - B6B096501A1D25ED008BFAA6 /* TSStorageManager.m */, - B63BAD6B1A74DA8F00269E74 /* TSStorageManager+messageIDs.h */, - B63BAD6C1A74DA8F00269E74 /* TSStorageManager+messageIDs.m */, - B6B096511A1D25ED008BFAA6 /* TSYapDatabaseObject.h */, - B6B096521A1D25ED008BFAA6 /* TSYapDatabaseObject.m */, - ); - path = Storage; - sourceTree = ""; - }; - B6B0963F1A1D25ED008BFAA6 /* AxolotlStore */ = { - isa = PBXGroup; - children = ( - B675C16F1B891D6800A7A87A /* TSStorageHeaders.h */, - B6B096401A1D25ED008BFAA6 /* TSStorageManager+IdentityKeyStore.h */, - B6B096411A1D25ED008BFAA6 /* TSStorageManager+IdentityKeyStore.m */, - B6B096421A1D25ED008BFAA6 /* TSStorageManager+keyFromIntLong.h */, - B6B096431A1D25ED008BFAA6 /* TSStorageManager+keyFromIntLong.m */, - B6B096441A1D25ED008BFAA6 /* TSStorageManager+PreKeyStore.h */, - B6B096451A1D25ED008BFAA6 /* TSStorageManager+PreKeyStore.m */, - B6B096461A1D25ED008BFAA6 /* TSStorageManager+SessionStore.h */, - B6B096471A1D25ED008BFAA6 /* TSStorageManager+SessionStore.m */, - B6B096481A1D25ED008BFAA6 /* TSStorageManager+SignedPreKeyStore.h */, - B6B096491A1D25ED008BFAA6 /* TSStorageManager+SignedPreKeyStore.m */, - ); - path = AxolotlStore; - sourceTree = ""; - }; - B6B096541A1D25ED008BFAA6 /* Util */ = { - isa = PBXGroup; - children = ( - B6B096551A1D25ED008BFAA6 /* Cryptography.h */, - B6B096561A1D25ED008BFAA6 /* Cryptography.m */, - B6B096571A1D25ED008BFAA6 /* NSData+Base64.h */, - B6B096581A1D25ED008BFAA6 /* NSData+Base64.m */, - B6B096591A1D25ED008BFAA6 /* NSData+hexString.h */, - B6B0965A1A1D25ED008BFAA6 /* NSData+hexString.m */, - B6B0965B1A1D25ED008BFAA6 /* NSData+messagePadding.h */, - B6B0965C1A1D25ED008BFAA6 /* NSData+messagePadding.m */, - B6B0965F1A1D25ED008BFAA6 /* NSURLSessionDataTask+StatusCode.h */, - 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 = ""; - }; B6B6C3C419193F5B00C0B76B /* Translations */ = { isa = PBXGroup; children = ( @@ -2407,32 +1948,10 @@ isa = PBXGroup; children = ( B6C6AE531A305ED1006BAF8F /* redphone.cer */, - B6C6AE541A305ED1006BAF8F /* textsecure.cer */, ); path = Certificates; sourceTree = ""; }; - B6FAAAE91A41C7CC007FEC1D /* Attachement */ = { - isa = PBXGroup; - children = ( - B6B096031A1D25ED008BFAA6 /* TSAttachment.h */, - B6B096041A1D25ED008BFAA6 /* TSAttachment.m */, - B6FAAAEC1A41C918007FEC1D /* TSAttachmentStream.h */, - B6FAAAED1A41C918007FEC1D /* TSAttachmentStream.m */, - B6FAAAE61A41BC6C007FEC1D /* TSAttachmentPointer.h */, - B6FAAAE71A41BC6C007FEC1D /* TSAttachmentPointer.m */, - ); - name = Attachement; - sourceTree = ""; - }; - BF8C3D8119CE3B6A008F644C /* call */ = { - isa = PBXGroup; - children = ( - BF8C3D8219CE3B6A008F644C /* RecentCallTest.m */, - ); - path = call; - sourceTree = ""; - }; D221A07E169C9E5E00537ABF = { isa = PBXGroup; children = ( @@ -2457,6 +1976,8 @@ D221A08C169C9E5E00537ABF /* Frameworks */ = { isa = PBXGroup; children = ( + B660F6E81C29938A00687D6E /* libTwistedOakCollapsingFutures.a */, + B660F6E11C29886700687D6E /* libTwistedOakCollapsingFutures.a */, B6B226961BE4B7D200860F4D /* ContactsUI.framework */, B6FE7EB61ADD62FA00A6D22F /* PushKit.framework */, FC3BD9871A30A790005B96BB /* Social.framework */, @@ -2481,7 +2002,7 @@ D221A08D169C9E5E00537ABF /* UIKit.framework */, D221A08F169C9E5E00537ABF /* Foundation.framework */, D221A091169C9E5E00537ABF /* CoreGraphics.framework */, - D488327B732CFBE8349C7024 /* libPods.a */, + D124A70602BD07D5F1EE5FD8 /* libPods.a */, ); name = Frameworks; sourceTree = ""; @@ -2493,8 +2014,8 @@ B633C4FD1A1D190B0059AC12 /* Images */, B67EBF5C19194AC60084CCFD /* Settings.bundle */, 76EB03C118170B33006006FC /* src */, + B660F66C1C29867F00687D6E /* test */, D221A094169C9E5E00537ABF /* Supporting Files */, - A15706EA17F0CD6D007C2BD6 /* test */, B66DBF4919D5BBC8006EA940 /* Images.xcassets */, ); path = Signal; @@ -2668,6 +2189,7 @@ FCFD25811A154B3800F4C644 /* CodeVerificationViewController.m */, B97CBFA518860EA3008E0DE9 /* CountryCodeViewController.h */, B97CBFA618860EA3008E0DE9 /* CountryCodeViewController.m */, + B6B3655F1C286AD2009B72FF /* Signal-Bridging-Header.h */, ); name = Signup; sourceTree = ""; @@ -2724,8 +2246,9 @@ D221A080169C9E5E00537ABF /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftUpdateCheck = 0720; LastTestingUpgradeCheck = 0600; - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0720; ORGANIZATIONNAME = "Open Whisper Systems"; TargetAttributes = { D221A088169C9E5E00537ABF = { @@ -2844,7 +2367,6 @@ B6F509971AA53F760068F56A /* Localizable.strings in Resources */, AD41D7B51A6F6F0600241130 /* play_button.png in Resources */, B633C59D1A1D190B0059AC12 /* endcall@2x.png in Resources */, - B6C6AE561A305ED1006BAF8F /* textsecure.cer in Resources */, FC5CDF391A3393DD00B47253 /* error_white@2x.png in Resources */, B633C5D21A1D190B0059AC12 /* savephoto@2x.png in Resources */, B10C9B611A7049EC00ECA2BF /* play_icon.png in Resources */, @@ -2880,8 +2402,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + B660F6D41C29868000687D6E /* whisperFake.cer in Resources */, 76EB060118170B33006006FC /* InitiateSignal.proto in Resources */, - B6850E5A1995A4710068E715 /* whisperFake.cer in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2986,7 +2508,7 @@ buildActionMask = 2147483647; files = ( 76EB063E18170B33006006FC /* Operation.m in Sources */, - B60FB9AD1A46F831006A5A66 /* UIImage+contentTypes.m in Sources */, + B640BFA81C257843006038B3 /* RPAccountManager.m in Sources */, A5509ECD1A69B1D600ABA4BC /* CountryCodeTableViewCell.m in Sources */, 76EB05F618170B33006006FC /* CallConnectUtil.m in Sources */, 76EB061218170B33006006FC /* LoggingUtil.m in Sources */, @@ -2999,43 +2521,25 @@ 76EB062418170B33006006FC /* PriorityQueue.m in Sources */, B6BADBE71B88D1AC0086A80D /* LockInteractionController.m in Sources */, 76EB061A18170B33006006FC /* DiscardingLog.m in Sources */, - B63AF5C71A1F757900D01AAD /* TSContactsIntersectionRequest.m in Sources */, - B6B0968B1A1D25ED008BFAA6 /* TSStorageManager+SignedPreKeyStore.m in Sources */, 76EB05AC18170B33006006FC /* SrtpSocket.m in Sources */, - B6FE7EBA1ADD63AE00A6D22F /* NSData+ows_StripToken.m in Sources */, - B6A5D05C1A7827ED0043D837 /* TSAvailablePreKeysCountRequest.m in Sources */, FCB11D931A12A4AA002F93FB /* FullImageViewController.m in Sources */, - B6B096871A1D25ED008BFAA6 /* TSStorageManager+IdentityKeyStore.m in Sources */, B60C16651988999D00E97A6C /* VersionMigrations.m in Sources */, - 76EB062A18170B33006006FC /* BadState.m in Sources */, B97940271832BD2400BD66CB /* UIUtil.m in Sources */, - B62EFBEC1A91352F0072ADD3 /* TSInvalidIdentityKeyErrorMessage.m in Sources */, 4CE0E3771B954546007210CF /* TSAnimatedAdapter.m in Sources */, - B6B096861A1D25ED008BFAA6 /* SecurityUtils.m in Sources */, 76EB05BE18170B33006006FC /* ConfirmPacket.m in Sources */, 76EB058618170B33006006FC /* PreferencesUtil.m in Sources */, 76EB05A818170B33006006FC /* RtpSocket.m in Sources */, - B6B096911A1D25ED008BFAA6 /* NSData+Base64.m in Sources */, - B6B096751A1D25ED008BFAA6 /* TSOutgoingMessage.m in Sources */, E197B61818BBEC1A00F073E5 /* RemoteIOAudio.m in Sources */, B67ADDC41989FF8700E1A773 /* RPServerRequestsManager.m in Sources */, 76EB059418170B33006006FC /* HttpManager.m in Sources */, 76EB05EC18170B33006006FC /* CallState.m in Sources */, 76EB05D218170B33006006FC /* ZrtpInitiator.m in Sources */, 76EB05E018170B33006006FC /* NetworkStream.m in Sources */, - B6E4ECF61C0106DF0014E766 /* ContactsManager+updater.m in Sources */, - B62EFBEE1A91352F0072ADD3 /* TSInvalidIdentityKeySendingErrorMessage.m in Sources */, - B6B0968A1A1D25ED008BFAA6 /* TSStorageManager+SessionStore.m in Sources */, FCFA64B71A24F6730007FB87 /* UIFont+OWS.m in Sources */, - B6B096891A1D25ED008BFAA6 /* TSStorageManager+PreKeyStore.m in Sources */, B6B9ECFC198B31BA00C620D3 /* PushManager.m in Sources */, 76EB05D618170B33006006FC /* ZrtpResponder.m in Sources */, B62D53F71A23CCAD009AAF82 /* TSMessageAdapter.m in Sources */, - B63AF5C91A1F757900D01AAD /* TSRecipientPrekeyRequest.m in Sources */, - B63BAD6D1A74DA8F00269E74 /* TSStorageManager+messageIDs.m in Sources */, A5988A811A8A70D0002AD6BE /* UIButton+OWS.m in Sources */, - 7095B7B018F46D35002C66E2 /* PhoneNumberUtil.m in Sources */, - B63AF5D81A1F889500D01AAD /* SubProtocol.pb.m in Sources */, FCD274EB1A5AFDDB00202277 /* AboutTableViewController.m in Sources */, E197B61618BBEC1A00F073E5 /* StretchFactorController.m in Sources */, FCFD257F1A154B2C00F4C644 /* RegistrationViewController.m in Sources */, @@ -3043,55 +2547,38 @@ 701231B518ECAA4500D456C4 /* EvpMessageDigest.m in Sources */, 76EB062218170B33006006FC /* CyclicalBuffer.m in Sources */, 76EB063C18170B33006006FC /* NumberUtil.m in Sources */, - B6B096691A1D25ED008BFAA6 /* TSThread.m in Sources */, - B6B096641A1D25ED008BFAA6 /* TSContactThread.m in Sources */, B6A3EB4B1A423B3800B2236B /* TSPhotoAdapter.m in Sources */, 76EB063A18170B33006006FC /* FunctionalUtil.m in Sources */, 76EB060A18170B33006006FC /* SignalUtil.m in Sources */, - 76EB062818170B33006006FC /* BadArgument.m in Sources */, - 76EB062E18170B33006006FC /* SecurityFailure.m in Sources */, - 76EB05F218170B33006006FC /* PhoneNumber.m in Sources */, E197B61718BBEC1A00F073E5 /* AnonymousAudioCallbackHandler.m in Sources */, 76EB05BC18170B33006006FC /* ConfirmAckPacket.m in Sources */, 76EB060C18170B33006006FC /* CategorizingLogger.m in Sources */, 76EB058A18170B33006006FC /* Release.m in Sources */, 76EB061018170B33006006FC /* EventWindow.m in Sources */, E197B62718BBF63B00F073E5 /* SoundBoard.m in Sources */, - B63AF5CA1A1F757900D01AAD /* TSRegisterForPushRequest.m in Sources */, 76EB058418170B33006006FC /* LocalizableText.m in Sources */, 76EB057A18170B33006006FC /* ContactsManager.m in Sources */, - B6B096611A1D25ED008BFAA6 /* TSAccountManager.m in Sources */, E197B61918BBEC1A00F073E5 /* RemoteIOBufferListWrapper.m in Sources */, 76EB05A618170B33006006FC /* RtpPacket.m in Sources */, 76EB064218170B33006006FC /* StringUtil.m in Sources */, A547DD741A70A87800103EC7 /* DJWActionSheet+OWS.m in Sources */, - B6BADBE41B88CB940086A80D /* TSUpdateAttributesRequest.m in Sources */, 76EB065A18170B34006006FC /* NextResponderScrollView.m in Sources */, 76EB062618170B33006006FC /* Queue.m in Sources */, D221A09A169C9E5E00537ABF /* main.m in Sources */, - B6AE33BD1A1EB121003DF39D /* TSGroupModel.m in Sources */, 76EB061618170B33006006FC /* AnonymousOccurrenceLogger.m in Sources */, + B6258B331C29E2E60014138E /* NotificationsManager.m in Sources */, 76EB063018170B33006006FC /* Conversions.m in Sources */, 76EB065618170B34006006FC /* InCallViewController.m in Sources */, - B63006431B9631EC00F2FEB5 /* AFSecurityOWSPolicy.m in Sources */, - B6B096681A1D25ED008BFAA6 /* SignalRecipient.m in Sources */, 76EB05FE18170B33006006FC /* InitiateSignal.pb.m in Sources */, 76EB05CA18170B33006006FC /* RecipientUnavailable.m in Sources */, - B692BF071A76EF0F002786DA /* TSDatabaseSecondaryIndexes.m in Sources */, - B6B0968D1A1D25ED008BFAA6 /* TSStorageManager+keyingMaterial.m in Sources */, E197B61418BBEC1A00F073E5 /* DropoutTracker.m in Sources */, - 76EB062C18170B33006006FC /* OperationFailed.m in Sources */, FCAC963C19FEF9280046DFC5 /* SignalsViewController.m in Sources */, 76EB05DA18170B33006006FC /* LowLatencyConnector.m in Sources */, 76EB05EE18170B33006006FC /* CallTermination.m in Sources */, B66B9F7D1AEAF40500E2E609 /* NotificationSettingsOptionsViewController.m in Sources */, E1CD329618BCFF9900B1A496 /* SoundInstance.m in Sources */, - B6FAAAEE1A41C918007FEC1D /* TSAttachmentStream.m in Sources */, 76EB05B418170B33006006FC /* HashChain.m in Sources */, 76EB05E418170B33006006FC /* UdpSocket.m in Sources */, - B6B096931A1D25ED008BFAA6 /* NSData+messagePadding.m in Sources */, - B63AF5CE1A1F757900D01AAD /* TSAttachmentRequest.m in Sources */, - B675C16C1B891B3900A7A87A /* TSAttributes.m in Sources */, 76EB058218170B33006006FC /* Environment.m in Sources */, 76EB064418170B33006006FC /* ThreadManager.m in Sources */, E197B61E18BBEC6D00F073E5 /* AudioRouter.m in Sources */, @@ -3100,30 +2587,19 @@ FC31962D1A06A2190094C78E /* FingerprintViewController.m in Sources */, 76EB061418170B33006006FC /* AnonymousConditionLogger.m in Sources */, 76EB05C018170B33006006FC /* DhPacket.m in Sources */, - B63885D01A2685D700A226A6 /* PreKeyBundle+jsonDict.m in Sources */, FC3196301A0814130094C78E /* SettingsTableViewController.m in Sources */, 7038632818F70C0700D4A43F /* EvpSymetricUtil.m in Sources */, 76EB068618170B34006006FC /* ContactTableViewCell.m in Sources */, - B6B096921A1D25ED008BFAA6 /* NSData+hexString.m in Sources */, - B6019E971A2492AB001118DF /* NSDate+millisecondTimeStamp.mm in Sources */, B63761ED19E1FBE8005735D1 /* HttpRequestOrResponse.m in Sources */, - B63AF5C81A1F757900D01AAD /* TSUnregisterAccountRequest.m in Sources */, 76EB05A018170B33006006FC /* IpAddress.m in Sources */, - B6B096651A1D25ED008BFAA6 /* TSGroupThread.m in Sources */, FCAC965119FF0A6E0046DFC5 /* MessagesViewController.m in Sources */, - B63AF5D01A1F757900D01AAD /* TSSubmitMessageRequest.m in Sources */, - B6A5D0631A7850180043D837 /* TSCurrentSignedPreKeyRequest.m in Sources */, B68EF9BB1C0B1EBD009C3DCD /* FLAnimatedImageView.m in Sources */, - B6B0966B1A1D25ED008BFAA6 /* TSAttachment.m in Sources */, - 76EB057618170B33006006FC /* Contact.m in Sources */, - B6B0968F1A1D25ED008BFAA6 /* TSYapDatabaseObject.m in Sources */, A5E9D4BB1A65FAD800E4481C /* TSVideoAttachmentAdapter.m in Sources */, E197B61118BBEC1A00F073E5 /* AudioProcessor.m in Sources */, FCAC964019FEF99A0046DFC5 /* InboxTableViewCell.m in Sources */, 76EB05EA18170B33006006FC /* CallProgress.m in Sources */, FCFA64B41A24F3880007FB87 /* UIColor+OWS.m in Sources */, 76EB05C218170B33006006FC /* DhPacketSharedSecretHashes.m in Sources */, - B6B096701A1D25ED008BFAA6 /* TSInfoMessage.m in Sources */, B6C93C4E199567AD00EDF894 /* DebugLogger.m in Sources */, 76EB063218170B33006006FC /* Crc32.m in Sources */, E197B62418BBF5BB00F073E5 /* SoundPlayer.m in Sources */, @@ -3135,14 +2611,11 @@ E197B61A18BBEC1A00F073E5 /* SpeexCodec.m in Sources */, 76EB05F018170B33006006FC /* PhoneManager.m in Sources */, E197B60F18BBEC1A00F073E5 /* EncodedAudioFrame.m in Sources */, - B6B0966C1A1D25ED008BFAA6 /* TSCall.m in Sources */, 76EB061818170B33006006FC /* AnonymousValueLogger.m in Sources */, - A59E6D721A79E5D100D98E2E /* MIMETypeUtil.m in Sources */, 76EB05E618170B33006006FC /* CallController.m in Sources */, 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 */, FCD274E81A5AFDC900202277 /* AdvancedSettingsTableViewController.m in Sources */, 76EB05C418170B33006006FC /* HandshakePacket.m in Sources */, @@ -3150,16 +2623,10 @@ 7038632718F70C0700D4A43F /* CryptoTools.m in Sources */, 76EB058C18170B33006006FC /* DnsManager.m in Sources */, B671B2461A93B238002BBD9D /* GroupContactsResult.m in Sources */, - B63AF5CB1A1F757900D01AAD /* TSRegisterPrekeysRequest.m in Sources */, FC7C7A961A581AF40091823B /* TSAdapterCacheManager.m in Sources */, - B6FAAAE81A41BC6C007FEC1D /* TSAttachmentPointer.m in Sources */, - B6B096881A1D25ED008BFAA6 /* TSStorageManager+keyFromIntLong.m in Sources */, - B6B50AAB1A4192C500F8F607 /* TSMessagesManager+attachments.m in Sources */, B66B9F721AEA6D1100E2E609 /* NotificationSettingsViewController.m in Sources */, 76EB059018170B33006006FC /* IgnoredPacketFailure.m in Sources */, - B60FB9B01A4711D4006A5A66 /* TSAttachmentEncryptionResult.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 */, @@ -3169,14 +2636,11 @@ 76EB064618170B33006006FC /* TimeUtil.m in Sources */, 70BAFD5D190584BE00FA5E0B /* NotificationTracker.m in Sources */, 76EB05A418170B33006006FC /* PacketHandler.m in Sources */, - B6B096951A1D25ED008BFAA6 /* NSURLSessionDataTask+StatusCode.m in Sources */, E197B62118BBF12700F073E5 /* AppAudioManager.m in Sources */, FC4FA0261A1B9DC600DA100A /* SignalsNavigationController.m in Sources */, - B63AF5D31A1F757900D01AAD /* TSSocketManager.m in Sources */, 76EB063818170B33006006FC /* DictionaryUtil.m in Sources */, 76EB05CE18170B33006006FC /* ZrtpHandshakeResult.m in Sources */, B63761EE19E1FBE8005735D1 /* HttpRequestUtil.m in Sources */, - B6B096631A1D25ED008BFAA6 /* TSPreKeyManager.m in Sources */, 76EB05B618170B33006006FC /* MasterSecret.m in Sources */, 76EB05F418170B33006006FC /* CallConnectResult.m in Sources */, FCFD256F1A151BCB00F4C644 /* NewGroupViewController.m in Sources */, @@ -3187,53 +2651,39 @@ 76EB05D018170B33006006FC /* ZrtpHandshakeSocket.m in Sources */, B63761EF19E1FBE8005735D1 /* HttpResponse.m in Sources */, E197B61518BBEC1A00F073E5 /* JitterQueue.m in Sources */, - B6B0968C1A1D25ED008BFAA6 /* TSDatabaseView.m in Sources */, - B6B0966A1A1D25ED008BFAA6 /* IncomingPushMessageSignal.pb.m in Sources */, BFB074C919A5611000F2947C /* ObservableValue.m in Sources */, B68EF9BA1C0B1EBD009C3DCD /* FLAnimatedImage.m in Sources */, B68112EA1A4D9EC400BA82FF /* UIImage+normalizeImage.m in Sources */, - B6B0968E1A1D25ED008BFAA6 /* TSStorageManager.m in Sources */, FCB11D8A1A1284BB002F93FB /* SettingsTableViewCell.m in Sources */, 76EB05C818170B33006006FC /* HelloPacket.m in Sources */, BFB074C719A5611000F2947C /* FutureUtil.m in Sources */, FCD274E21A5AFD8000202277 /* PrivacySettingsTableViewController.m in Sources */, 76EB057218170B33006006FC /* RecentCall.m in Sources */, - B62EFBED1A91352F0072ADD3 /* TSInvalidIdentityKeyReceivingErrorMessage.m in Sources */, B97CBFA818860EA3008E0DE9 /* CountryCodeViewController.m in Sources */, B6B1013C196D213F007E3930 /* SignalKeyingStorage.m in Sources */, 76EB059218170B33006006FC /* UnrecognizedRequestFailure.m in Sources */, 76EB05F818170B33006006FC /* CallConnectUtil_Initiator.m in Sources */, + B62F5E101C2980B4000D370C /* NSData+ows_StripToken.m in Sources */, B6B2269A1BE4C59200860F4D /* APNavigationController.m in Sources */, - B6B096761A1D25ED008BFAA6 /* TSServerMessage.m in Sources */, B63761E319E1F487005735D1 /* AFHTTPSessionManager+SignalMethods.m in Sources */, 76EB05CC18170B33006006FC /* ShortAuthenticationStringGenerator.m in Sources */, E16E5BEF18AAC40200B7C403 /* EC25KeyAgreementProtocol.m in Sources */, - B6B096901A1D25ED008BFAA6 /* Cryptography.m in Sources */, 76EB064018170B33006006FC /* AnonymousTerminator.m in Sources */, - B6E314C91A38FAAF00A41AFB /* TSFingerprintGenerator.m in Sources */, - B6B096721A1D25ED008BFAA6 /* TSMessage.m in Sources */, 76EB058818170B33006006FC /* PropertyListPreferences.m in Sources */, 76EB05B218170B33006006FC /* DH3KKeyAgreementProtocol.m in Sources */, B63761EC19E1FBE8005735D1 /* HttpRequest.m in Sources */, 76EB060818170B33006006FC /* ResponderSessionDescriptor.m in Sources */, B90418E6183E9DD40038554A /* DateUtil.m in Sources */, - B63AF5D21A1F757900D01AAD /* TSNetworkManager.m in Sources */, 76EB05C618170B33006006FC /* HelloAckPacket.m in Sources */, 76EB05E818170B33006006FC /* CallFailedServerMessage.m in Sources */, 76EB05FA18170B33006006FC /* CallConnectUtil_Responder.m in Sources */, 76EB05AE18170B33006006FC /* SrtpStream.m in Sources */, - B6B096711A1D25ED008BFAA6 /* TSInteraction.m in Sources */, - B6B0966D1A1D25ED008BFAA6 /* TSErrorMessage.m in Sources */, E197B61318BBEC1A00F073E5 /* DesiredBufferDepthController.m in Sources */, 76EB064818170B33006006FC /* Zid.m in Sources */, - B6B096741A1D25ED008BFAA6 /* TSMessagesManager.m in Sources */, 76EB05E218170B33006006FC /* SecureEndPoint.m in Sources */, - B63AF5CC1A1F757900D01AAD /* TSRegisterWithTokenRequest.m in Sources */, 76EB05DE18170B33006006FC /* Certificate.m in Sources */, 76EB05B818170B33006006FC /* NegotiationFailed.m in Sources */, - B6B096731A1D25ED008BFAA6 /* TSMessagesManager+sendMessages.m in Sources */, 76EB05D818170B33006006FC /* LowLatencyCandidate.m in Sources */, - B6B0966F1A1D25ED008BFAA6 /* TSIncomingMessage.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3241,159 +2691,190 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 76EB05ED18170B33006006FC /* CallState.m in Sources */, - 76EB064918170B33006006FC /* Zid.m in Sources */, - 76EB05AF18170B33006006FC /* SrtpStream.m in Sources */, - 76EB061318170B33006006FC /* LoggingUtil.m in Sources */, - 76EB05A718170B33006006FC /* RtpPacket.m in Sources */, - 76EB05BF18170B33006006FC /* ConfirmPacket.m in Sources */, - 76EB05E518170B33006006FC /* UdpSocket.m in Sources */, - 76EB05BD18170B33006006FC /* ConfirmAckPacket.m in Sources */, - 76EB05DB18170B33006006FC /* LowLatencyConnector.m in Sources */, - 76EB060F18170B33006006FC /* DecayingSampleEstimator.m in Sources */, - 76EB057718170B33006006FC /* Contact.m in Sources */, - 76EB05FB18170B33006006FC /* CallConnectUtil_Responder.m in Sources */, - B6B095E61A1D25C5008BFAA6 /* TSMessageStorageTests.m in Sources */, - 76EB063718170B33006006FC /* DataUtil.m in Sources */, - 76EB05C918170B33006006FC /* HelloPacket.m in Sources */, - B90418E7183E9DD40038554A /* DateUtil.m in Sources */, - 76EB05CB18170B33006006FC /* RecipientUnavailable.m in Sources */, - 76EB061B18170B33006006FC /* DiscardingLog.m in Sources */, - 76EB05FD18170B33006006FC /* CallConnectUtil_Server.m in Sources */, - 76EB058B18170B33006006FC /* Release.m in Sources */, - 76EB05D318170B33006006FC /* ZrtpInitiator.m in Sources */, - 76EB061518170B33006006FC /* AnonymousConditionLogger.m in Sources */, - 76EB05A118170B33006006FC /* IpAddress.m in Sources */, - 76EB05CD18170B33006006FC /* ShortAuthenticationStringGenerator.m in Sources */, - 76EB05B718170B33006006FC /* MasterSecret.m in Sources */, - 76EB05DF18170B33006006FC /* Certificate.m in Sources */, - 76EB05D918170B33006006FC /* LowLatencyCandidate.m in Sources */, - A157075717F0CD6D007C2BD6 /* AudioFrameTest.m in Sources */, - 76EB063F18170B33006006FC /* Operation.m in Sources */, - 76EB05AB18170B33006006FC /* SequenceCounter.m in Sources */, - 76EB061D18170B33006006FC /* ArrayUtil.m in Sources */, - 76EB05E318170B33006006FC /* SecureEndPoint.m in Sources */, - 76EB060D18170B33006006FC /* CategorizingLogger.m in Sources */, - A157075817F0CD6D007C2BD6 /* AudioRemoteIOTest.m in Sources */, - 76EB05DD18170B33006006FC /* StreamPair.m in Sources */, - 76EB059518170B33006006FC /* HttpManager.m in Sources */, - 76EB05A318170B33006006FC /* IpEndPoint.m in Sources */, - 76EB054118170B33006006FC /* AppDelegate.m in Sources */, - A157075917F0CD6D007C2BD6 /* AudioStretcherTest.m in Sources */, - 76EB05B918170B33006006FC /* NegotiationFailed.m in Sources */, - A157075A17F0CD6D007C2BD6 /* JitterQueueTest.m in Sources */, - 76EB060318170B33006006FC /* InitiatorSessionDescriptor.m in Sources */, - A157075B17F0CD6D007C2BD6 /* SpeexCodecTest.m in Sources */, - A157075D17F0CD6D007C2BD6 /* DnsManagerTest.m in Sources */, - A157075E17F0CD6D007C2BD6 /* HttpRequestResponseTest.m in Sources */, - 76919BF71805D190008C664A /* ContactManagerTest.m in Sources */, - 76EB05D118170B33006006FC /* ZrtpHandshakeSocket.m in Sources */, - A157075F17F0CD6D007C2BD6 /* IpAddressTest.m in Sources */, - 76EB05F518170B33006006FC /* CallConnectResult.m in Sources */, - BFB074C219A4BCA400F2947C /* ObservableTest.m in Sources */, - A157076017F0CD6D007C2BD6 /* IpEndPointTest.m in Sources */, - A157076117F0CD6D007C2BD6 /* RtpPacketTests.m in Sources */, - 76EB05C518170B33006006FC /* HandshakePacket.m in Sources */, - 76EB058F18170B33006006FC /* HostNameEndPoint.m in Sources */, - B640C4771A477B0F005C7C8A /* TSAttachementsTest.m in Sources */, - 76EB064518170B33006006FC /* ThreadManager.m in Sources */, - 76EB068718170B34006006FC /* ContactTableViewCell.m in Sources */, - 76EB063B18170B33006006FC /* FunctionalUtil.m in Sources */, - A157076217F0CD6D007C2BD6 /* SecureStreamTest.m in Sources */, - A157076317F0CD6D007C2BD6 /* SequenceCounterTest.m in Sources */, - 76EB062318170B33006006FC /* CyclicalBuffer.m in Sources */, - A157076517F0CD6D007C2BD6 /* HandshakePacketTest.m in Sources */, - B6B095E81A1D25C5008BFAA6 /* TSStoragePreKeyStoreTests.m in Sources */, - A157076617F0CD6D007C2BD6 /* HashChainTest.m in Sources */, - 76EB063118170B33006006FC /* Conversions.m in Sources */, - 76EB05F918170B33006006FC /* CallConnectUtil_Initiator.m in Sources */, - A157076717F0CD6D007C2BD6 /* MasterSecretTest.m in Sources */, - 76EB05CF18170B33006006FC /* ZrtpHandshakeResult.m in Sources */, - A157076817F0CD6D007C2BD6 /* ShortAuthenticationStringGeneratorTest.m in Sources */, - 76EB065718170B34006006FC /* InCallViewController.m in Sources */, - A157076917F0CD6D007C2BD6 /* PregeneratedKeyAgreementParticipantProtocol.m in Sources */, - 76EB062918170B33006006FC /* BadArgument.m in Sources */, - A157076A17F0CD6D007C2BD6 /* ZrtpTest.m in Sources */, - A157076B17F0CD6D007C2BD6 /* LowLatencyConnectorTest.m in Sources */, - B617E9241A9F962600753F00 /* MessagePaddingTests.m in Sources */, - B65031CF1A7862AA002EBBBD /* SignedPreKeyDeletionTests.m in Sources */, - 76EB061718170B33006006FC /* AnonymousOccurrenceLogger.m in Sources */, - 76EB05F118170B33006006FC /* PhoneManager.m in Sources */, - 76EB05F718170B33006006FC /* CallConnectUtil.m in Sources */, - B6B095E51A1D25C5008BFAA6 /* TextSecureKitTests.m in Sources */, - 76EB063318170B33006006FC /* Crc32.m in Sources */, - BFB074C819A5611000F2947C /* FutureUtil.m in Sources */, - 76EB062718170B33006006FC /* Queue.m in Sources */, - 76EB05C118170B33006006FC /* DhPacket.m in Sources */, - 76EB060B18170B33006006FC /* SignalUtil.m in Sources */, - A157076C17F0CD6D007C2BD6 /* NetworkStreamTest.m in Sources */, - 76EB065B18170B34006006FC /* NextResponderScrollView.m in Sources */, - 76EB05BB18170B33006006FC /* CommitPacket.m in Sources */, - B6B095E41A1D25C5008BFAA6 /* CryptographyTests.mm in Sources */, - A157076D17F0CD6D007C2BD6 /* SecureEndPointTest.m in Sources */, - A157076E17F0CD6D007C2BD6 /* UdpSocketTest.m in Sources */, - 76EB05C318170B33006006FC /* DhPacketSharedSecretHashes.m in Sources */, - BF8C3D8319CE3B6A008F644C /* RecentCallTest.m in Sources */, - 76EB05C718170B33006006FC /* HelloAckPacket.m in Sources */, - A157076F17F0CD6D007C2BD6 /* PhoneNumberTest.m in Sources */, - 76EB05B518170B33006006FC /* HashChain.m in Sources */, - A157077017F0CD6D007C2BD6 /* SessionDescriptorTest.m in Sources */, - 76EB05B318170B33006006FC /* DH3KKeyAgreementProtocol.m in Sources */, - 76EB05AD18170B33006006FC /* SrtpSocket.m in Sources */, - 76EB058D18170B33006006FC /* DnsManager.m in Sources */, - A157077117F0CD6D007C2BD6 /* DecayingSampleEstimatorTest.m in Sources */, - A157077217F0CD6D007C2BD6 /* EventWindowTest.m in Sources */, - A157077417F0CD6D007C2BD6 /* TestUtil.m in Sources */, - 76EB05E918170B33006006FC /* CallFailedServerMessage.m in Sources */, - 76EB058718170B33006006FC /* PreferencesUtil.m in Sources */, - 76EB064118170B33006006FC /* AnonymousTerminator.m in Sources */, - A157077717F0CD6D007C2BD6 /* ConversionsTest.m in Sources */, - 76EB058318170B33006006FC /* Environment.m in Sources */, - A157077817F0CD6D007C2BD6 /* Crc32Test.m in Sources */, - 76EB059318170B33006006FC /* UnrecognizedRequestFailure.m in Sources */, - B97CBFA918860EA3008E0DE9 /* CountryCodeViewController.m in Sources */, - 76EB060918170B33006006FC /* ResponderSessionDescriptor.m in Sources */, - 76EB062518170B33006006FC /* PriorityQueue.m in Sources */, - A157077917F0CD6D007C2BD6 /* CryptoToolsTest.m in Sources */, - BFB074C119A4BCA400F2947C /* FutureUtilTest.m in Sources */, - B684A46D19C3446200B11029 /* PushManagerTest.m in Sources */, - 76EB05A918170B33006006FC /* RtpSocket.m in Sources */, - 76EB062B18170B33006006FC /* BadState.m in Sources */, - 76EB062F18170B33006006FC /* SecurityFailure.m in Sources */, - 76EB064318170B33006006FC /* StringUtil.m in Sources */, - 76EB057B18170B33006006FC /* ContactsManager.m in Sources */, - 76EB05E718170B33006006FC /* CallController.m in Sources */, - 76EB05A518170B33006006FC /* PacketHandler.m in Sources */, - A157077A17F0CD6D007C2BD6 /* CyclicalBufferTest.m in Sources */, - 76EB05D518170B33006006FC /* ZrtpManager.m in Sources */, - 76EB061118170B33006006FC /* EventWindow.m in Sources */, - 76EB05FF18170B33006006FC /* InitiateSignal.pb.m in Sources */, - 76EB057518170B33006006FC /* RecentCallManager.m in Sources */, - 76EB059F18170B33006006FC /* HttpSocket.m in Sources */, - B6B095E91A1D25C5008BFAA6 /* TSStorageSignedPreKeyStore.m in Sources */, - 76EB062D18170B33006006FC /* OperationFailed.m in Sources */, - 76EB05EB18170B33006006FC /* CallProgress.m in Sources */, - 76EB063918170B33006006FC /* DictionaryUtil.m in Sources */, - 76EB059118170B33006006FC /* IgnoredPacketFailure.m in Sources */, - 76EB05F318170B33006006FC /* PhoneNumber.m in Sources */, - A157077B17F0CD6D007C2BD6 /* ExceptionsTest.m in Sources */, - 76EB057318170B33006006FC /* RecentCall.m in Sources */, - 76EB058518170B33006006FC /* LocalizableText.m in Sources */, - 76EB061918170B33006006FC /* AnonymousValueLogger.m in Sources */, - 76EB058918170B33006006FC /* PropertyListPreferences.m in Sources */, - 76EB063D18170B33006006FC /* NumberUtil.m in Sources */, - 76EB05E118170B33006006FC /* NetworkStream.m in Sources */, - A157077C17F0CD6D007C2BD6 /* FunctionalUtilTest.m in Sources */, - A157077D17F0CD6D007C2BD6 /* PriorityQueueTest.m in Sources */, - B6B095E71A1D25C5008BFAA6 /* TSStorageIdentityKeyStoreTests.m in Sources */, - 76EB064718170B33006006FC /* TimeUtil.m in Sources */, - A157077E17F0CD6D007C2BD6 /* QueueTest.m in Sources */, - E16E5BF918AAF02100B7C403 /* EC25AgreerTest.m in Sources */, - A157077F17F0CD6D007C2BD6 /* UtilTest.m in Sources */, - 76EB05D718170B33006006FC /* ZrtpResponder.m in Sources */, - 76EB05EF18170B33006006FC /* CallTermination.m in Sources */, - BFB074CA19A5611000F2947C /* ObservableValue.m in Sources */, - B97940281832BD2400BD66CB /* UIUtil.m in Sources */, + B660F7001C29988E00687D6E /* AppAudioManager.m in Sources */, + B660F7011C29988E00687D6E /* AudioRouter.m in Sources */, + B660F7021C29988E00687D6E /* AudioPacker.m in Sources */, + B660F7031C29988E00687D6E /* AudioSocket.m in Sources */, + B660F7041C29988E00687D6E /* CallAudioManager.m in Sources */, + B660F7051C29988E00687D6E /* EncodedAudioFrame.m in Sources */, + B660F7061C29988E00687D6E /* EncodedAudioPacket.m in Sources */, + B660F7071C29988E00687D6E /* AudioProcessor.m in Sources */, + B660F7081C29988E00687D6E /* AudioStretcher.m in Sources */, + B660F7091C29988E00687D6E /* DesiredBufferDepthController.m in Sources */, + B660F70A1C29988E00687D6E /* DropoutTracker.m in Sources */, + B660F70B1C29988E00687D6E /* JitterQueue.m in Sources */, + B660F70C1C29988E00687D6E /* StretchFactorController.m in Sources */, + B660F70D1C29988E00687D6E /* AnonymousAudioCallbackHandler.m in Sources */, + B660F70E1C29988E00687D6E /* RemoteIOAudio.m in Sources */, + B660F70F1C29988E00687D6E /* RemoteIOBufferListWrapper.m in Sources */, + B660F7101C29988E00687D6E /* SpeexCodec.m in Sources */, + B660F7111C29988E00687D6E /* SoundBoard.m in Sources */, + B660F7121C29988E00687D6E /* SoundInstance.m in Sources */, + B660F7131C29988E00687D6E /* SoundPlayer.m in Sources */, + B660F7141C29988E00687D6E /* RecentCall.m in Sources */, + B660F7151C29988E00687D6E /* RecentCallManager.m in Sources */, + B660F7161C29988E00687D6E /* GroupContactsResult.m in Sources */, + B660F7171C29988E00687D6E /* ContactsManager.m in Sources */, + B660F7181C29988E00687D6E /* CryptoTools.m in Sources */, + B660F7191C29988E00687D6E /* EvpMessageDigest.m in Sources */, + B660F71A1C29988E00687D6E /* EvpSymetricUtil.m in Sources */, + B660F71B1C29988E00687D6E /* Environment.m in Sources */, + B660F71C1C29988E00687D6E /* DebugLogger.m in Sources */, + B660F71D1C29988E00687D6E /* LocalizableText.m in Sources */, + B660F71E1C29988E00687D6E /* PreferencesUtil.m in Sources */, + B660F71F1C29988E00687D6E /* PropertyListPreferences.m in Sources */, + B660F7201C29988E00687D6E /* Release.m in Sources */, + B660F7211C29988E00687D6E /* SignalKeyingStorage.m in Sources */, + B660F7221C29988E00687D6E /* VersionMigrations.m in Sources */, + B660F7231C29988E00687D6E /* DnsManager.m in Sources */, + B660F7241C29988E00687D6E /* HostNameEndPoint.m in Sources */, + B660F7251C29988E00687D6E /* IgnoredPacketFailure.m in Sources */, + B660F7261C29988E00687D6E /* UnrecognizedRequestFailure.m in Sources */, + B660F7271C29988E00687D6E /* RPAPICall.m in Sources */, + B660F7281C29988E00687D6E /* RPServerRequestsManager.m in Sources */, + B660F7291C29988E00687D6E /* AFHTTPSessionManager+SignalMethods.m in Sources */, + B660F72A1C29988E00687D6E /* HttpRequest.m in Sources */, + B660F72B1C29988E00687D6E /* HttpRequestOrResponse.m in Sources */, + B660F72C1C29988E00687D6E /* HttpRequestUtil.m in Sources */, + B660F72D1C29988E00687D6E /* HttpResponse.m in Sources */, + B660F72E1C29988E00687D6E /* HttpManager.m in Sources */, + B660F72F1C29988E00687D6E /* HttpSocket.m in Sources */, + B660F7301C29988E00687D6E /* IpAddress.m in Sources */, + B660F7311C29988E00687D6E /* IpEndPoint.m in Sources */, + B660F7321C29988E00687D6E /* PacketHandler.m in Sources */, + B660F7331C29988E00687D6E /* RtpPacket.m in Sources */, + B660F7341C29988E00687D6E /* RtpSocket.m in Sources */, + B660F7351C29988E00687D6E /* SequenceCounter.m in Sources */, + B660F7361C29988E00687D6E /* SrtpSocket.m in Sources */, + B660F7371C29988E00687D6E /* SrtpStream.m in Sources */, + B660F7381C29988E00687D6E /* DH3KKeyAgreementParticipant.m in Sources */, + B660F7391C29988E00687D6E /* DH3KKeyAgreementProtocol.m in Sources */, + B660F73A1C29988E00687D6E /* EC25KeyAgreementParticipant.m in Sources */, + B660F73B1C29988E00687D6E /* EC25KeyAgreementProtocol.m in Sources */, + B660F73C1C29988E00687D6E /* EvpKeyAgreement.m in Sources */, + B660F73D1C29988E00687D6E /* HashChain.m in Sources */, + B660F73E1C29988E00687D6E /* MasterSecret.m in Sources */, + B660F73F1C29988E00687D6E /* NegotiationFailed.m in Sources */, + B660F7401C29988E00687D6E /* CommitPacket.m in Sources */, + B660F7411C29988E00687D6E /* ConfirmAckPacket.m in Sources */, + B660F7421C29988E00687D6E /* ConfirmPacket.m in Sources */, + B660F7431C29988E00687D6E /* DhPacket.m in Sources */, + B660F7441C29988E00687D6E /* DhPacketSharedSecretHashes.m in Sources */, + B660F7451C29988E00687D6E /* HandshakePacket.m in Sources */, + B660F7461C29988E00687D6E /* HelloAckPacket.m in Sources */, + B660F7471C29988E00687D6E /* HelloPacket.m in Sources */, + B660F7481C29988E00687D6E /* RecipientUnavailable.m in Sources */, + B660F7491C29988E00687D6E /* ShortAuthenticationStringGenerator.m in Sources */, + B660F74A1C29988E00687D6E /* ZrtpHandshakeResult.m in Sources */, + B660F74B1C29988E00687D6E /* ZrtpHandshakeSocket.m in Sources */, + B660F74C1C29988E00687D6E /* ZrtpInitiator.m in Sources */, + B660F74D1C29988E00687D6E /* ZrtpManager.m in Sources */, + B660F74E1C29988E00687D6E /* ZrtpResponder.m in Sources */, + B660F74F1C29988E00687D6E /* LowLatencyCandidate.m in Sources */, + B660F7501C29988E00687D6E /* LowLatencyConnector.m in Sources */, + B660F7511C29988E00687D6E /* StreamPair.m in Sources */, + B660F7521C29988E00687D6E /* Certificate.m in Sources */, + B660F7531C29988E00687D6E /* NetworkStream.m in Sources */, + B660F7541C29988E00687D6E /* SecureEndPoint.m in Sources */, + B660F7551C29988E00687D6E /* UdpSocket.m in Sources */, + B660F7561C29988E00687D6E /* PushManager.m in Sources */, + B660F7571C29988E00687D6E /* NotificationTracker.m in Sources */, + B660F7581C29988E00687D6E /* RPAccountManager.m in Sources */, + B660F7591C29988E00687D6E /* CallController.m in Sources */, + B660F75A1C29988E00687D6E /* CallFailedServerMessage.m in Sources */, + B660F75B1C29988E00687D6E /* CallProgress.m in Sources */, + B660F75C1C29988E00687D6E /* CallState.m in Sources */, + B660F75D1C29988E00687D6E /* CallTermination.m in Sources */, + B660F75E1C29988E00687D6E /* PhoneManager.m in Sources */, + B660F75F1C29988E00687D6E /* CallConnectResult.m in Sources */, + B660F7601C29988E00687D6E /* CallConnectUtil.m in Sources */, + B660F7611C29988E00687D6E /* CallConnectUtil_Initiator.m in Sources */, + B660F7621C29988E00687D6E /* CallConnectUtil_Responder.m in Sources */, + B660F7631C29988E00687D6E /* CallConnectUtil_Server.m in Sources */, + B660F7641C29988E00687D6E /* InitiateSignal.pb.m in Sources */, + B660F7651C29988E00687D6E /* InitiatorSessionDescriptor.m in Sources */, + B660F7661C29988E00687D6E /* ResponderSessionDescriptor.m in Sources */, + B660F7671C29988E00687D6E /* SignalUtil.m in Sources */, + B660F7681C29988E00687D6E /* CategorizingLogger.m in Sources */, + B660F7691C29988E00687D6E /* DecayingSampleEstimator.m in Sources */, + B660F76A1C29988E00687D6E /* EventWindow.m in Sources */, + B660F76B1C29988E00687D6E /* LoggingUtil.m in Sources */, + B660F76C1C29988E00687D6E /* AnonymousConditionLogger.m in Sources */, + B660F76D1C29988E00687D6E /* AnonymousOccurrenceLogger.m in Sources */, + B660F76E1C29988E00687D6E /* AnonymousValueLogger.m in Sources */, + B660F76F1C29988E00687D6E /* DiscardingLog.m in Sources */, + B660F7701C29988E00687D6E /* FLAnimatedImage.m in Sources */, + B660F7711C29988E00687D6E /* FLAnimatedImageView.m in Sources */, + B660F7721C29988E00687D6E /* AppStoreRating.m in Sources */, + B660F7731C29988E00687D6E /* UIButton+OWS.m in Sources */, + B660F7741C29988E00687D6E /* DJWActionSheet+OWS.m in Sources */, + B660F7751C29988E00687D6E /* UIColor+OWS.m in Sources */, + B660F7761C29988E00687D6E /* UIFont+OWS.m in Sources */, + B660F7771C29988E00687D6E /* UIImage+normalizeImage.m in Sources */, + B660F7781C29988E00687D6E /* ArrayUtil.m in Sources */, + B660F7791C29988E00687D6E /* CyclicalBuffer.m in Sources */, + B660F77A1C29988E00687D6E /* PriorityQueue.m in Sources */, + B660F77B1C29988E00687D6E /* Queue.m in Sources */, + B660F77C1C29988E00687D6E /* Conversions.m in Sources */, + B660F77D1C29988E00687D6E /* Crc32.m in Sources */, + B660F77E1C29988E00687D6E /* DataUtil.m in Sources */, + B660F77F1C29988E00687D6E /* DateUtil.m in Sources */, + B660F7801C29988E00687D6E /* DictionaryUtil.m in Sources */, + B660F7811C29988E00687D6E /* FunctionalUtil.m in Sources */, + B660F7821C29988E00687D6E /* FutureUtil.m in Sources */, + B660F7831C29988E00687D6E /* NumberUtil.m in Sources */, + B660F7841C29988E00687D6E /* ObservableValue.m in Sources */, + B660F7851C29988E00687D6E /* Operation.m in Sources */, + B660F7861C29988E00687D6E /* AnonymousTerminator.m in Sources */, + B660F7871C29988E00687D6E /* StringUtil.m in Sources */, + B660F7881C29988E00687D6E /* ThreadManager.m in Sources */, + B660F7891C29988E00687D6E /* TimeUtil.m in Sources */, + B660F78A1C29988E00687D6E /* UIUtil.m in Sources */, + B660F78B1C29988E00687D6E /* Zid.m in Sources */, + B660F78C1C29988E00687D6E /* UIDevice+TSHardwareVersion.m in Sources */, + B660F78D1C29988E00687D6E /* TSAdapterCacheManager.m in Sources */, + B660F6C31C29868000687D6E /* EC25AgreerTest.m in Sources */, + B660F6B91C29868000687D6E /* SpeexCodecTest.m in Sources */, + B660F6D81C29868000687D6E /* CryptoToolsTest.m in Sources */, + B660F6BD1C29868000687D6E /* HttpRequestResponseTest.m in Sources */, + B660F6B71C29868000687D6E /* AudioStretcherTest.m in Sources */, + B660F6DE1C29868000687D6E /* PriorityQueueTest.m in Sources */, + B660F6BE1C29868000687D6E /* IpAddressTest.m in Sources */, + B660F6E01C29868000687D6E /* UtilTest.m in Sources */, + B660F6D61C29868000687D6E /* ConversionsTest.m in Sources */, + B660F6C01C29868000687D6E /* RtpPacketTests.m in Sources */, + B660F6C71C29868000687D6E /* ShortAuthenticationStringGeneratorTest.m in Sources */, + B660F6DA1C29868000687D6E /* ExceptionsTest.m in Sources */, + B660F6CC1C29868000687D6E /* SecureEndPointTest.m in Sources */, + B660F6BA1C29868000687D6E /* RecentCallTest.m in Sources */, + B660F6DB1C29868000687D6E /* FunctionalUtilTest.m in Sources */, + B660F6CF1C29868000687D6E /* SessionDescriptorTest.m in Sources */, + B660F6C81C29868000687D6E /* PregeneratedKeyAgreementParticipantProtocol.m in Sources */, + B660F6BC1C29868000687D6E /* DnsManagerTest.m in Sources */, + B660F6B61C29868000687D6E /* AudioRemoteIOTest.m in Sources */, + B660F6D71C29868000687D6E /* Crc32Test.m in Sources */, + B660F6C51C29868000687D6E /* HashChainTest.m in Sources */, + B660F6D01C29868000687D6E /* DecayingSampleEstimatorTest.m in Sources */, + B660F6C91C29868000687D6E /* ZrtpTest.m in Sources */, + B660F6D11C29868000687D6E /* EventWindowTest.m in Sources */, + B660F6BF1C29868000687D6E /* IpEndPointTest.m in Sources */, + B660F6C11C29868000687D6E /* SecureStreamTest.m in Sources */, + B660F6CB1C29868000687D6E /* NetworkStreamTest.m in Sources */, + B660F6B51C29868000687D6E /* AudioFrameTest.m in Sources */, + B660F6C21C29868000687D6E /* SequenceCounterTest.m in Sources */, + B660F6D51C29868000687D6E /* TestUtil.m in Sources */, + B660F6B81C29868000687D6E /* JitterQueueTest.m in Sources */, + B660F6DF1C29868000687D6E /* QueueTest.m in Sources */, + B660F6BB1C29868000687D6E /* ContactManagerTest.m in Sources */, + B660F6CE1C29868000687D6E /* PhoneNumberTest.m in Sources */, + B660F6C41C29868000687D6E /* HandshakePacketTest.m in Sources */, + B660F6CD1C29868000687D6E /* UdpSocketTest.m in Sources */, + B660F6DD1C29868000687D6E /* ObservableTest.m in Sources */, + B660F6D21C29868000687D6E /* PushManagerTest.m in Sources */, + B660F6C61C29868000687D6E /* MasterSecretTest.m in Sources */, + B660F6D91C29868000687D6E /* CyclicalBufferTest.m in Sources */, + B660F6DC1C29868000687D6E /* FutureUtilTest.m in Sources */, + B660F6CA1C29868000687D6E /* LowLatencyConnectorTest.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3463,11 +2944,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; - CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; - CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "compiler-default"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -3481,19 +2958,12 @@ CLANG_WARN__ARC_BRIDGE_CAST_NONARC = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; ENABLE_BITCODE = NO; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_GENERATE_TEST_COVERAGE_FILES = NO; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; - GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -3533,11 +3003,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES; - CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES; - CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "compiler-default"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; @@ -3551,12 +3017,7 @@ CLANG_WARN__ARC_BRIDGE_CAST_NONARC = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Distribution"; - COPY_PHASE_STRIP = YES; ENABLE_BITCODE = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_GENERATE_TEST_COVERAGE_FILES = NO; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; - GCC_OPTIMIZATION_LEVEL = 3; GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -3632,6 +3093,7 @@ ); INFOPLIST_FILE = "$(SRCROOT)/Signal/Signal-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)", @@ -3641,6 +3103,8 @@ PRODUCT_BUNDLE_IDENTIFIER = org.whispersystems.signal; PRODUCT_NAME = Signal; SDKROOT = iphoneos; + SWIFT_OBJC_BRIDGING_HEADER = "Signal/src/view controllers/Signal-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; TEST_AFTER_BUILD = YES; VALID_ARCHS = "arm64 armv7 armv7s i386"; WRAPPER_EXTENSION = app; @@ -3684,6 +3148,7 @@ ); INFOPLIST_FILE = "$(SRCROOT)/Signal/Signal-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)", @@ -3692,7 +3157,9 @@ OTHER_LDFLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = org.whispersystems.signal; PRODUCT_NAME = Signal; + PROVISIONING_PROFILE = ""; SDKROOT = iphoneos; + SWIFT_OBJC_BRIDGING_HEADER = "Signal/src/view controllers/Signal-Bridging-Header.h"; TEST_AFTER_BUILD = YES; VALID_ARCHS = "arm64 armv7 armv7s i386"; WRAPPER_EXTENSION = app; @@ -3714,7 +3181,6 @@ "$(DEVELOPER_FRAMEWORKS_DIR)", ); GCC_GENERATE_TEST_COVERAGE_FILES = NO; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Signal/Signal-Prefix.pch"; @@ -3734,12 +3200,14 @@ "\"$(SRCROOT)/Libraries\"/**", ); INFOPLIST_FILE = "Signal/test/Supporting Files/SignalTests-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)", + "$(PROJECT_DIR)/build/Debug-iphoneos", ); OTHER_LDFLAGS = ( + "-all_load", "-ObjC", "$(inherited)", ); @@ -3766,7 +3234,6 @@ "$(DEVELOPER_FRAMEWORKS_DIR)", ); GCC_GENERATE_TEST_COVERAGE_FILES = NO; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Signal/Signal-Prefix.pch"; @@ -3786,18 +3253,20 @@ "\"$(SRCROOT)/Libraries\"/**", ); INFOPLIST_FILE = "Signal/test/Supporting Files/SignalTests-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)", + "$(PROJECT_DIR)/build/Debug-iphoneos", ); OTHER_LDFLAGS = ( + "-all_load", "-ObjC", "$(inherited)", ); PRODUCT_BUNDLE_IDENTIFIER = "org.whispersystems.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = SignalTests; - PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE = "c15eac58-5aa7-4660-b874-b9f7ed3dab70"; TEST_HOST = "$(BUNDLE_LOADER)"; VALID_ARCHS = "arm64 armv7s armv7 i386 x86_64"; }; diff --git a/Signal.xcodeproj/xcshareddata/xcschemes/Signal.xcscheme b/Signal.xcodeproj/xcshareddata/xcschemes/Signal.xcscheme index b7415917d..a3b6da25e 100644 --- a/Signal.xcodeproj/xcshareddata/xcschemes/Signal.xcscheme +++ b/Signal.xcodeproj/xcshareddata/xcschemes/Signal.xcscheme @@ -67,7 +67,8 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" - allowLocationSimulation = "YES"> + allowLocationSimulation = "YES" + showNonLocalizedStrings = "YES"> CFBundleVersion - 2.3.0 + 2.3.0.1 LOGS_EMAIL support@whispersystems.org LOGS_URL diff --git a/Signal/Signal-Prefix.pch b/Signal/Signal-Prefix.pch index e7039f31a..99d0a7868 100644 --- a/Signal/Signal-Prefix.pch +++ b/Signal/Signal-Prefix.pch @@ -19,7 +19,4 @@ #define SignalAlertView(title,msg) [[[UIAlertView alloc] initWithTitle:title message:msg delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"") otherButtonTitles:nil, nil] show] #define SignalReportError [Pastelog reportErrorAndSubmitLogsWithAlertTitle:NSLocalizedString(@"ERROR_WAS_DETECTED_TITLE", @"") alertBody:NSLocalizedString(@"ERROR_WAS_DETECTED_SUBMIT", @"")]; - - #define BLOCK_SAFE_RUN(block, ...) block ? dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{block(__VA_ARGS__);}) : nil - #define SYNC_BLOCK_SAFE_RUN(block, ...) block ? block(__VA_ARGS__): nil #endif diff --git a/Signal/src/AppDelegate.h b/Signal/src/AppDelegate.h index a3f15e79d..351edddf9 100644 --- a/Signal/src/AppDelegate.h +++ b/Signal/src/AppDelegate.h @@ -2,7 +2,7 @@ #import "SignalsViewController.h" -@interface AppDelegate : UIResponder +@interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @property (strong, nonatomic) SignalsViewController *signalVC; diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index bba6ba3e7..44d5f576c 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -1,23 +1,25 @@ #import "AppDelegate.h" #import "AppStoreRating.h" #import "CategorizingLogger.h" +#import "CodeVerificationViewController.h" #import "ContactsManager.h" #import "DebugLogger.h" #import "Environment.h" +#import "NotificationsManager.h" #import "PreferencesUtil.h" #import "PushManager.h" #import "Release.h" #import "TSAccountManager.h" -#import "TSPreKeyManager.h" #import "TSMessagesManager.h" +#import "TSPreKeyManager.h" #import "TSSocketManager.h" +#import "TextSecureKitEnv.h" #import "VersionMigrations.h" -#import "CodeVerificationViewController.h" -static NSString * const kStoryboardName = @"Storyboard"; -static NSString * const kInitialViewControllerIdentifier = @"UserInitialViewController"; -static NSString * const kURLSchemeSGNLKey = @"sgnl"; -static NSString * const kURLHostVerifyPrefix = @"verify"; +static NSString *const kStoryboardName = @"Storyboard"; +static NSString *const kInitialViewControllerIdentifier = @"UserInitialViewController"; +static NSString *const kURLSchemeSGNLKey = @"sgnl"; +static NSString *const kURLHostVerifyPrefix = @"verify"; @interface AppDelegate () @@ -29,7 +31,7 @@ static NSString * const kURLHostVerifyPrefix = @"verify"; #pragma mark Detect updates - perform migrations -+ (void)initialize{ ++ (void)initialize { [AppStoreRating setupRatingLibrary]; } @@ -40,58 +42,63 @@ static NSString * const kURLHostVerifyPrefix = @"verify"; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [self setupAppearance]; [[PushManager sharedManager] registerPushKitNotificationFuture]; - + if (getenv("runningTests_dontStartApp")) { return YES; } - - CategorizingLogger* logger = [CategorizingLogger categorizingLogger]; - [logger addLoggingCallback:^(NSString *category, id details, NSUInteger index) {}]; + + // Initializing logger + CategorizingLogger *logger = [CategorizingLogger categorizingLogger]; + [logger addLoggingCallback:^(NSString *category, id details, NSUInteger index){ + }]; + + // Setting up environment [Environment setCurrent:[Release releaseEnvironmentWithLogging:logger]]; - + if ([TSAccountManager isRegistered]) { [Environment.getCurrent.contactsManager doAfterEnvironmentInitSetup]; } - [Environment.getCurrent initCallListener]; - - [[TSStorageManager sharedManager] setupDatabase]; - + + [self setupTSKitEnv]; + BOOL loggingIsEnabled; - + #ifdef DEBUG // Specified at Product -> Scheme -> Edit Scheme -> Test -> Arguments -> Environment to avoid things like // the phone directory being looked up during tests. loggingIsEnabled = TRUE; - [DebugLogger.sharedInstance enableTTYLogging]; + [DebugLogger.sharedLogger enableTTYLogging]; #elif RELEASE loggingIsEnabled = Environment.preferences.loggingIsEnabled; #endif [self verifyBackgroundBeforeKeysAvailableLaunch]; - + if (loggingIsEnabled) { - [DebugLogger.sharedInstance enableFileLogging]; + [DebugLogger.sharedLogger enableFileLogging]; } - + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:kStoryboardName bundle:[NSBundle mainBundle]]; - UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:kInitialViewControllerIdentifier]; - - self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + UIViewController *viewController = + [storyboard instantiateViewControllerWithIdentifier:kInitialViewControllerIdentifier]; + + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.rootViewController = viewController; - + [self.window makeKeyAndVisible]; - - [VersionMigrations performUpdateCheck]; // this call must be made after environment has been initialized because in general upgrade may depend on environment - - //Accept push notification when app is not open + + [VersionMigrations performUpdateCheck]; // this call must be made after environment has been initialized because in + // general upgrade may depend on environment + + // Accept push notification when app is not open NSDictionary *remoteNotif = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]; if (remoteNotif) { DDLogInfo(@"Application was launched by tapping a push notification."); - [self application:application didReceiveRemoteNotification:remoteNotif ]; + [self application:application didReceiveRemoteNotification:remoteNotif]; } - + [self prepareScreenshotProtection]; - + if ([TSAccountManager isRegistered]) { if (application.applicationState == UIApplicationStateInactive) { [TSSocketManager becomeActiveFromForeground]; @@ -100,50 +107,61 @@ static NSString * const kURLHostVerifyPrefix = @"verify"; } else { DDLogWarn(@"The app was launched in an unknown way"); } - + [[PushManager sharedManager] validateUserNotificationSettings]; [TSPreKeyManager refreshPreKeys]; } - + return YES; } -- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken { +- (void)setupTSKitEnv { + [TextSecureKitEnv sharedEnv].contactsManager = [Environment getCurrent].contactsManager; + [[TSStorageManager sharedManager] setupDatabase]; + [TextSecureKitEnv sharedEnv].notificationsManager = [[NotificationsManager alloc] init]; +} + +- (void)application:(UIApplication *)application + didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { [PushManager.sharedManager.pushNotificationFutureSource trySetResult:deviceToken]; } -- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error { +- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { #ifdef DEBUG DDLogWarn(@"We're in debug mode, and registered a fake push identifier"); - [PushManager.sharedManager.pushNotificationFutureSource trySetResult:[@"aFakePushIdentifier" dataUsingEncoding:NSUTF8StringEncoding]]; + [PushManager.sharedManager.pushNotificationFutureSource trySetResult:@"aFakePushIdentifier"]; #else [PushManager.sharedManager.pushNotificationFutureSource trySetFailure:error]; #endif } -- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings{ +- (void)application:(UIApplication *)application + didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings { [PushManager.sharedManager.userNotificationFutureSource trySetResult:notificationSettings]; } --(BOOL) application:(UIApplication*)application openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation { +- (BOOL)application:(UIApplication *)application + openURL:(NSURL *)url + sourceApplication:(NSString *)sourceApplication + annotation:(id)annotation { if ([url.scheme isEqualToString:kURLSchemeSGNLKey]) { if ([url.host hasPrefix:kURLHostVerifyPrefix] && ![TSAccountManager isRegistered]) { - id signupController = [Environment getCurrent].signUpFlowNavigationController; + id signupController = [Environment getCurrent].signUpFlowNavigationController; if ([signupController isKindOfClass:[UINavigationController class]]) { - UINavigationController *navController = (UINavigationController*)signupController; + UINavigationController *navController = (UINavigationController *)signupController; UIViewController *controller = [navController.childViewControllers lastObject]; if ([controller isKindOfClass:[CodeVerificationViewController class]]) { - CodeVerificationViewController *cvvc = (CodeVerificationViewController*)controller; - NSString *verificationCode = [url.path substringFromIndex:1]; - - cvvc.challengeTextField.text = verificationCode; + CodeVerificationViewController *cvvc = (CodeVerificationViewController *)controller; + NSString *verificationCode = [url.path substringFromIndex:1]; + + cvvc.challengeTextField.text = verificationCode; [cvvc verifyChallengeAction:nil]; - } else{ - DDLogWarn(@"Not the verification view controller we expected. Got %@ instead", NSStringFromClass(controller.class)); + } else { + DDLogWarn(@"Not the verification view controller we expected. Got %@ instead", + NSStringFromClass(controller.class)); } - } - } else{ + } else { DDLogWarn(@"Application opened with an unknown URL action: %@", url.host); } } else { @@ -152,9 +170,10 @@ static NSString * const kURLHostVerifyPrefix = @"verify"; return NO; } --(void)applicationDidBecomeActive:(UIApplication *)application { +- (void)applicationDidBecomeActive:(UIApplication *)application { if ([TSAccountManager isRegistered]) { - // We're double checking that the app is active, to be sure since we can't verify in production env due to code signing. + // We're double checking that the app is active, to be sure since we can't verify in production env due to code + // signing. [TSSocketManager becomeActiveFromForeground]; [[Environment getCurrent].contactsManager verifyABPermission]; } @@ -164,56 +183,63 @@ static NSString * const kURLHostVerifyPrefix = @"verify"; - (void)applicationWillResignActive:(UIApplication *)application { UIBackgroundTaskIdentifier __block bgTask = UIBackgroundTaskInvalid; - bgTask = [application beginBackgroundTaskWithExpirationHandler:^{ - + bgTask = [application beginBackgroundTaskWithExpirationHandler:^{ + }]; - + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - if ([TSAccountManager isRegistered]) { - dispatch_sync(dispatch_get_main_queue(), ^{ - [self protectScreen]; - [[[Environment getCurrent] signalsViewController] updateInboxCountLabel]; - }); - [TSSocketManager resignActivity]; - } - - [application endBackgroundTask:bgTask]; - bgTask = UIBackgroundTaskInvalid; + if ([TSAccountManager isRegistered]) { + dispatch_sync(dispatch_get_main_queue(), ^{ + [self protectScreen]; + [[[Environment getCurrent] signalsViewController] updateInboxCountLabel]; + }); + [TSSocketManager resignActivity]; + } + + [application endBackgroundTask:bgTask]; + bgTask = UIBackgroundTaskInvalid; }); - } - (void)application:(UIApplication *)application -performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem - completionHandler:(void (^)(BOOL succeeded))completionHandler { + performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem + completionHandler:(void (^)(BOOL succeeded))completionHandler { if ([TSAccountManager isRegistered]) { [[Environment getCurrent].signalsViewController composeNew]; } else { - UIAlertController *controller = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"REGISTER_CONTACTS_WELCOME", nil) - message:@"Someone's exited to send his first message! Register now to send your first message." - preferredStyle:UIAlertControllerStyleAlert]; + UIAlertController *controller = [UIAlertController + alertControllerWithTitle:NSLocalizedString(@"REGISTER_CONTACTS_WELCOME", nil) + message: + @"Someone's exited to send his first message! Register now to send your first message." + preferredStyle:UIAlertControllerStyleAlert]; completionHandler(YES); - [self.window.rootViewController presentViewController:controller animated:YES completion:^{ - completionHandler(NO); - }]; + [self.window.rootViewController presentViewController:controller + animated:YES + completion:^{ + completionHandler(NO); + }]; } } -- (void)prepareScreenshotProtection{ +- (void)prepareScreenshotProtection { self.blankWindow = ({ UIWindow *window = [[UIWindow alloc] initWithFrame:self.window.bounds]; window.hidden = YES; window.opaque = YES; window.userInteractionEnabled = NO; window.windowLevel = CGFLOAT_MAX; - + // There appears to be no more reliable way to get the launchscreen image from an asset bundle - NSDictionary *dict = @{@"320x480" : @"LaunchImage-700", - @"320x568" : @"LaunchImage-700-568h", - @"375x667" : @"LaunchImage-800-667h", - @"414x736" : @"LaunchImage-800-Portrait-736h"}; - - NSString *key = [NSString stringWithFormat:@"%dx%d", (int)[UIScreen mainScreen].bounds.size.width, (int)[UIScreen mainScreen].bounds.size.height]; + NSDictionary *dict = @{ + @"320x480" : @"LaunchImage-700", + @"320x568" : @"LaunchImage-700-568h", + @"375x667" : @"LaunchImage-800-667h", + @"414x736" : @"LaunchImage-800-Portrait-736h" + }; + + NSString *key = [NSString stringWithFormat:@"%dx%d", + (int)[UIScreen mainScreen].bounds.size.width, + (int)[UIScreen mainScreen].bounds.size.height]; UIImage *launchImage = [UIImage imageNamed:dict[key]]; UIImageView *imgView = [[UIImageView alloc] initWithImage:launchImage]; UIViewController *vc = [[UIViewController alloc] initWithNibName:nil bundle:nil]; @@ -222,46 +248,45 @@ performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem [vc.view addSubview:imgView]; [vc.view setBackgroundColor:[UIColor ows_blackColor]]; window.rootViewController = vc; - + window; }); } -- (void)protectScreen{ - if (Environment.preferences.screenSecurityIsEnabled){ +- (void)protectScreen { + if (Environment.preferences.screenSecurityIsEnabled) { self.blankWindow.hidden = NO; } } -- (void)removeScreenProtection{ +- (void)removeScreenProtection { if (Environment.preferences.screenSecurityIsEnabled) { self.blankWindow.hidden = YES; } } --(void)setupAppearance { +- (void)setupAppearance { [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; [[UINavigationBar appearance] setBarTintColor:[UIColor ows_materialBlueColor]]; [[UINavigationBar appearance] setTintColor:[UIColor whiteColor]]; - - [[UIBarButtonItem appearanceWhenContainedIn: [UISearchBar class], nil] setTintColor:[UIColor ows_materialBlueColor]]; + + [[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil] setTintColor:[UIColor ows_materialBlueColor]]; [[UIToolbar appearance] setTintColor:[UIColor ows_materialBlueColor]]; [[UIBarButtonItem appearance] setTintColor:[UIColor whiteColor]]; - + NSShadow *shadow = [NSShadow new]; [shadow setShadowColor:[UIColor clearColor]]; - - NSDictionary *navbarTitleTextAttributes = @{ - NSForegroundColorAttributeName:[UIColor whiteColor], - NSShadowAttributeName:shadow, - }; - - [[UISwitch appearance] setOnTintColor:[UIColor ows_materialBlueColor]]; - - [[UINavigationBar appearance] setTitleTextAttributes:navbarTitleTextAttributes]; + NSDictionary *navbarTitleTextAttributes = @{ + NSForegroundColorAttributeName : [UIColor whiteColor], + NSShadowAttributeName : shadow, + }; + + [[UISwitch appearance] setOnTintColor:[UIColor ows_materialBlueColor]]; + + [[UINavigationBar appearance] setTitleTextAttributes:navbarTitleTextAttributes]; } #pragma mark Push Notifications Delegate Methods @@ -269,20 +294,38 @@ performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { [[PushManager sharedManager] application:application didReceiveRemoteNotification:userInfo]; } -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { - [[PushManager sharedManager] application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler]; +- (void)application:(UIApplication *)application + didReceiveRemoteNotification:(NSDictionary *)userInfo + fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { + [[PushManager sharedManager] application:application + didReceiveRemoteNotification:userInfo + fetchCompletionHandler:completionHandler]; } -- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{ +- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { [[PushManager sharedManager] application:application didReceiveLocalNotification:notification]; } -- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler { - [[PushManager sharedManager] application:application handleActionWithIdentifier:identifier forLocalNotification:notification completionHandler:completionHandler]; +- (void)application:(UIApplication *)application + handleActionWithIdentifier:(NSString *)identifier + forLocalNotification:(UILocalNotification *)notification + completionHandler:(void (^)())completionHandler { + [[PushManager sharedManager] application:application + handleActionWithIdentifier:identifier + forLocalNotification:notification + completionHandler:completionHandler]; } -- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler { - [[PushManager sharedManager] application:application handleActionWithIdentifier:identifier forLocalNotification:notification withResponseInfo:responseInfo completionHandler:completionHandler]; +- (void)application:(UIApplication *)application + handleActionWithIdentifier:(NSString *)identifier + forLocalNotification:(UILocalNotification *)notification + withResponseInfo:(NSDictionary *)responseInfo + completionHandler:(void (^)())completionHandler { + [[PushManager sharedManager] application:application + handleActionWithIdentifier:identifier + forLocalNotification:notification + withResponseInfo:responseInfo + completionHandler:completionHandler]; } /** @@ -292,10 +335,10 @@ performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem if ([self applicationIsActive]) { return; } - + if (![[TSStorageManager sharedManager] databasePasswordAccessible]) { UILocalNotification *notification = [[UILocalNotification alloc] init]; - notification.alertBody = NSLocalizedString(@"PHONE_NEEDS_UNLOCK", nil); + notification.alertBody = NSLocalizedString(@"PHONE_NEEDS_UNLOCK", nil); [[UIApplication sharedApplication] presentLocalNotificationNow:notification]; exit(0); } @@ -303,11 +346,11 @@ performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem - (BOOL)applicationIsActive { UIApplication *app = [UIApplication sharedApplication]; - + if (app.applicationState == UIApplicationStateActive) { return YES; } - + return NO; } diff --git a/Signal/src/NotificationTracker.h b/Signal/src/NotificationTracker.h index ba7ebd57a..e02228dd1 100644 --- a/Signal/src/NotificationTracker.h +++ b/Signal/src/NotificationTracker.h @@ -1,12 +1,12 @@ #import /** - * Tracks which notifications have already been processed, and which are are seen for the first time. + * Tracks which notifications have already been processed, and which are are seen for the first time. **/ @interface NotificationTracker : NSObject -+(NotificationTracker*) notificationTracker; --(BOOL) shouldProcessNotification:(NSDictionary*) notification; ++ (NotificationTracker *)notificationTracker; +- (BOOL)shouldProcessNotification:(NSDictionary *)notification; @end diff --git a/Signal/src/NotificationTracker.m b/Signal/src/NotificationTracker.m index e1a52402a..706ea7a47 100644 --- a/Signal/src/NotificationTracker.m +++ b/Signal/src/NotificationTracker.m @@ -1,21 +1,21 @@ -#import "NotificationTracker.h" #import "CryptoTools.h" #import "FunctionalUtil.h" +#import "NotificationTracker.h" #define MAX_NOTIFICATIONS_TO_TRACK 100 #define NOTIFICATION_PAYLOAD_KEY @"m" @implementation NotificationTracker { - NSMutableArray* _witnessedNotifications; + NSMutableArray *_witnessedNotifications; } -+(NotificationTracker*) notificationTracker { - NotificationTracker* notificationTracker = [NotificationTracker new]; ++ (NotificationTracker *)notificationTracker { + NotificationTracker *notificationTracker = [NotificationTracker new]; notificationTracker->_witnessedNotifications = [NSMutableArray new]; return notificationTracker; } --(BOOL) shouldProcessNotification:(NSDictionary*) notification { +- (BOOL)shouldProcessNotification:(NSDictionary *)notification { BOOL should = ![self wasNotificationProcessed:notification]; if (should) { [self markNotificationAsProcessed:notification]; @@ -23,27 +23,27 @@ return should; } --(void) markNotificationAsProcessed:(NSDictionary*) notification { - NSData* data = [self getIdForNotification:notification]; +- (void)markNotificationAsProcessed:(NSDictionary *)notification { + NSData *data = [self getIdForNotification:notification]; [_witnessedNotifications insertObject:data atIndex:0]; - - while(MAX_NOTIFICATIONS_TO_TRACK < _witnessedNotifications.count){ + + while (MAX_NOTIFICATIONS_TO_TRACK < _witnessedNotifications.count) { [_witnessedNotifications removeLastObject]; } } --(BOOL) wasNotificationProcessed:(NSDictionary*) notification { - NSData* data = [self getIdForNotification:notification]; - - return [_witnessedNotifications any:^int(NSData* previousData) { - return [data isEqualToData:previousData]; +- (BOOL)wasNotificationProcessed:(NSDictionary *)notification { + NSData *data = [self getIdForNotification:notification]; + + return [_witnessedNotifications any:^int(NSData *previousData) { + return [data isEqualToData:previousData]; }]; } // Uniquely Identify a notification by the hash of the message payload. --(NSData*) getIdForNotification:(NSDictionary*) notification { - NSData* data = [notification[NOTIFICATION_PAYLOAD_KEY] dataUsingEncoding:NSUTF8StringEncoding]; - NSData* notificationHash = [data hashWithSha256]; +- (NSData *)getIdForNotification:(NSDictionary *)notification { + NSData *data = [notification[NOTIFICATION_PAYLOAD_KEY] dataUsingEncoding:NSUTF8StringEncoding]; + NSData *notificationHash = [data hashWithSha256]; return notificationHash; } diff --git a/Signal/src/Storyboard/Storyboard.storyboard b/Signal/src/Storyboard/Storyboard.storyboard index 23e981aa0..f19e9e699 100755 --- a/Signal/src/Storyboard/Storyboard.storyboard +++ b/Signal/src/Storyboard/Storyboard.storyboard @@ -1,10 +1,9 @@ - + - + - @@ -19,12 +18,11 @@ - + - @@ -43,26 +40,7 @@ - @@ -105,6 +82,7 @@ + @@ -122,7 +100,6 @@ - @@ -168,7 +145,6 @@ - @@ -176,7 +152,6 @@ - @@ -184,7 +159,6 @@ - @@ -243,7 +214,6 @@ A0 09 9A FF A8 8A 09 99 diff --git a/Signal/src/UIColor+OWS.h b/Signal/src/UIColor+OWS.h index d148e9585..4df424fa6 100644 --- a/Signal/src/UIColor+OWS.h +++ b/Signal/src/UIColor+OWS.h @@ -10,22 +10,22 @@ @interface UIColor (OWS) -+ (UIColor*) ows_materialBlueColor; ++ (UIColor *)ows_materialBlueColor; -+ (UIColor *) ows_fadedBlueColor; ++ (UIColor *)ows_fadedBlueColor; -+ (UIColor *) ows_darkBackgroundColor; ++ (UIColor *)ows_darkBackgroundColor; -+ (UIColor *) ows_darkGrayColor; ++ (UIColor *)ows_darkGrayColor; -+ (UIColor *) ows_yellowColor; ++ (UIColor *)ows_yellowColor; -+ (UIColor *) ows_greenColor; ++ (UIColor *)ows_greenColor; -+ (UIColor *) ows_redColor; ++ (UIColor *)ows_redColor; -+ (UIColor*) ows_blackColor; ++ (UIColor *)ows_blackColor; -+ (UIColor*) backgroundColorForContact:(NSString*)contactIdentifier; ++ (UIColor *)backgroundColorForContact:(NSString *)contactIdentifier; @end diff --git a/Signal/src/UIColor+OWS.m b/Signal/src/UIColor+OWS.m index d93a46529..c77496644 100644 --- a/Signal/src/UIColor+OWS.m +++ b/Signal/src/UIColor+OWS.m @@ -6,79 +6,81 @@ // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // -#import "UIColor+OWS.h" #import "Cryptography.h" +#import "UIColor+OWS.h" @implementation UIColor (OWS) -+ (UIColor*) ows_materialBlueColor { ++ (UIColor *)ows_materialBlueColor { // blue: #2090EA - return [UIColor colorWithRed:32.f/255.f green:144.f/255.f blue:234.f/255.f alpha:1.f]; + return [UIColor colorWithRed:32.f / 255.f green:144.f / 255.f blue:234.f / 255.f alpha:1.f]; } -+ (UIColor*) ows_blackColor { ++ (UIColor *)ows_blackColor { // black: #080A00 - return [UIColor colorWithRed:8.f/255.f green:10.f/255.f blue:0./255.f alpha:1.f]; + return [UIColor colorWithRed:8.f / 255.f green:10.f / 255.f blue:0. / 255.f alpha:1.f]; } -+ (UIColor*) ows_darkGrayColor { - return [UIColor colorWithRed:81.f/255.f green:81.f/255.f blue:81.f/255.f alpha:1.f]; ++ (UIColor *)ows_darkGrayColor { + return [UIColor colorWithRed:81.f / 255.f green:81.f / 255.f blue:81.f / 255.f alpha:1.f]; } -+ (UIColor*) ows_darkBackgroundColor { - return [UIColor colorWithRed:35.f/255.f green:31.f/255.f blue:32.f/255.f alpha:1.f]; ++ (UIColor *)ows_darkBackgroundColor { + return [UIColor colorWithRed:35.f / 255.f green:31.f / 255.f blue:32.f / 255.f alpha:1.f]; } -+ (UIColor *) ows_fadedBlueColor { ++ (UIColor *)ows_fadedBlueColor { // blue: #B6DEF4 - return [UIColor colorWithRed:182.f/255.f green:222.f/255.f blue:244.f/255.f alpha:1.f]; + return [UIColor colorWithRed:182.f / 255.f green:222.f / 255.f blue:244.f / 255.f alpha:1.f]; } -+ (UIColor *) ows_yellowColor { ++ (UIColor *)ows_yellowColor { // gold: #FFBB5C - return [UIColor colorWithRed:245.f/255.f green:186.f/255.f blue:98.f/255.f alpha:1.f]; + return [UIColor colorWithRed:245.f / 255.f green:186.f / 255.f blue:98.f / 255.f alpha:1.f]; } -+ (UIColor *) ows_greenColor { ++ (UIColor *)ows_greenColor { // green: #BF4240 - return [UIColor colorWithRed:66.f/255.f green:191.f/255.f blue:64.f/255.f alpha:1.f]; + return [UIColor colorWithRed:66.f / 255.f green:191.f / 255.f blue:64.f / 255.f alpha:1.f]; } -+ (UIColor *) ows_redColor { ++ (UIColor *)ows_redColor { // red: #FF3867 - return [UIColor colorWithRed:255./255.f green:56.f/255.f blue:103.f/255.f alpha:1.f]; + return [UIColor colorWithRed:255. / 255.f green:56.f / 255.f blue:103.f / 255.f alpha:1.f]; } -+ (UIColor *) ows_lightBackgroundColor { - return [UIColor colorWithRed:242.f/255.f green:242.f/255.f blue:242.f/255.f alpha:1.f]; ++ (UIColor *)ows_lightBackgroundColor { + return [UIColor colorWithRed:242.f / 255.f green:242.f / 255.f blue:242.f / 255.f alpha:1.f]; } -+ (UIColor*) backgroundColorForContact:(NSString*)contactIdentifier { - NSArray *colors = @[[UIColor colorWithRed:204.f/255.f green:148.f/255.f blue:102.f/255.f alpha:1.f], - [UIColor colorWithRed:187.f/255.f green:104.f/255.f blue:62.f/255.f alpha:1.f], - [UIColor colorWithRed:145.f/255.f green:78.f/255.f blue:48.f/255.f alpha:1.f], - [UIColor colorWithRed:122.f/255.f green:63.f/255.f blue:41.f/255.f alpha:1.f], - [UIColor colorWithRed:80.f/255.f green:46.f/255.f blue:27.f/255.f alpha:1.f], - [UIColor colorWithRed:57.f/255.f green:45.f/255.f blue:19.f/255.f alpha:1.f], - [UIColor colorWithRed:37.f/255.f green:38.f/255.f blue:13.f/255.f alpha:1.f], - [UIColor colorWithRed:23.f/255.f green:31.f/255.f blue:10.f/255.f alpha:1.f], - [UIColor colorWithRed:6.f/255.f green:19.f/255.f blue:10.f/255.f alpha:1.f], - [UIColor colorWithRed:13.f/255.f green:4.f/255.f blue:16.f/255.f alpha:1.f], - [UIColor colorWithRed:27.f/255.f green:12.f/255.f blue:44.f/255.f alpha:1.f], - [UIColor colorWithRed:18.f/255.f green:17.f/255.f blue:64.f/255.f alpha:1.f], - [UIColor colorWithRed:20.f/255.f green:42.f/255.f blue:77.f/255.f alpha:1.f], - [UIColor colorWithRed:18.f/255.f green:55.f/255.f blue:68.f/255.f alpha:1.f], - [UIColor colorWithRed:18.f/255.f green:68.f/255.f blue:61.f/255.f alpha:1.f], - [UIColor colorWithRed:19.f/255.f green:73.f/255.f blue:26.f/255.f alpha:1.f], - [UIColor colorWithRed:13.f/255.f green:48.f/255.f blue:15.f/255.f alpha:1.f], - [UIColor colorWithRed:44.f/255.f green:165.f/255.f blue:137.f/255.f alpha:1.f], - [UIColor colorWithRed:137.f/255.f green:181.f/255.f blue:48.f/255.f alpha:1.f], - [UIColor colorWithRed:208.f/255.f green:204.f/255.f blue:78.f/255.f alpha:1.f], - [UIColor colorWithRed:227.f/255.f green:162.f/255.f blue:150.f/255.f alpha:1.f]]; ++ (UIColor *)backgroundColorForContact:(NSString *)contactIdentifier { + NSArray *colors = @[ + [UIColor colorWithRed:204.f / 255.f green:148.f / 255.f blue:102.f / 255.f alpha:1.f], + [UIColor colorWithRed:187.f / 255.f green:104.f / 255.f blue:62.f / 255.f alpha:1.f], + [UIColor colorWithRed:145.f / 255.f green:78.f / 255.f blue:48.f / 255.f alpha:1.f], + [UIColor colorWithRed:122.f / 255.f green:63.f / 255.f blue:41.f / 255.f alpha:1.f], + [UIColor colorWithRed:80.f / 255.f green:46.f / 255.f blue:27.f / 255.f alpha:1.f], + [UIColor colorWithRed:57.f / 255.f green:45.f / 255.f blue:19.f / 255.f alpha:1.f], + [UIColor colorWithRed:37.f / 255.f green:38.f / 255.f blue:13.f / 255.f alpha:1.f], + [UIColor colorWithRed:23.f / 255.f green:31.f / 255.f blue:10.f / 255.f alpha:1.f], + [UIColor colorWithRed:6.f / 255.f green:19.f / 255.f blue:10.f / 255.f alpha:1.f], + [UIColor colorWithRed:13.f / 255.f green:4.f / 255.f blue:16.f / 255.f alpha:1.f], + [UIColor colorWithRed:27.f / 255.f green:12.f / 255.f blue:44.f / 255.f alpha:1.f], + [UIColor colorWithRed:18.f / 255.f green:17.f / 255.f blue:64.f / 255.f alpha:1.f], + [UIColor colorWithRed:20.f / 255.f green:42.f / 255.f blue:77.f / 255.f alpha:1.f], + [UIColor colorWithRed:18.f / 255.f green:55.f / 255.f blue:68.f / 255.f alpha:1.f], + [UIColor colorWithRed:18.f / 255.f green:68.f / 255.f blue:61.f / 255.f alpha:1.f], + [UIColor colorWithRed:19.f / 255.f green:73.f / 255.f blue:26.f / 255.f alpha:1.f], + [UIColor colorWithRed:13.f / 255.f green:48.f / 255.f blue:15.f / 255.f alpha:1.f], + [UIColor colorWithRed:44.f / 255.f green:165.f / 255.f blue:137.f / 255.f alpha:1.f], + [UIColor colorWithRed:137.f / 255.f green:181.f / 255.f blue:48.f / 255.f alpha:1.f], + [UIColor colorWithRed:208.f / 255.f green:204.f / 255.f blue:78.f / 255.f alpha:1.f], + [UIColor colorWithRed:227.f / 255.f green:162.f / 255.f blue:150.f / 255.f alpha:1.f] + ]; NSData *contactData = [contactIdentifier dataUsingEncoding:NSUTF8StringEncoding]; - + NSUInteger hashingLength = 8; unsigned long long choose; NSData *hashData = [Cryptography computeSHA256:contactData truncatedToBytes:hashingLength]; @@ -88,4 +90,3 @@ @end - diff --git a/Signal/src/audio/AppAudioManager.h b/Signal/src/audio/AppAudioManager.h index aff1bf7b3..de53a778a 100644 --- a/Signal/src/audio/AppAudioManager.h +++ b/Signal/src/audio/AppAudioManager.h @@ -11,7 +11,7 @@ * Audio Settings, and interfacing with the OS. The Call Audio Pipeline it self is delegated * to the RemoteIOAudio Class. * - * The Audio Profile determines which preset of logic to use for playing sounds, Such as + * The Audio Profile determines which preset of logic to use for playing sounds, Such as * which speaker to use or if all sounds should be muted. **/ @@ -22,24 +22,24 @@ enum AudioProfile { AudioProfile_ExternalSpeaker, }; -+(AppAudioManager*) sharedInstance; ++ (AppAudioManager *)sharedInstance; --(void) setAudioProfile:(enum AudioProfile) profile; --(enum AudioProfile) getCurrentAudioProfile; --(void) updateAudioRouter; +- (void)setAudioProfile:(enum AudioProfile)profile; +- (enum AudioProfile)getCurrentAudioProfile; +- (void)updateAudioRouter; --(void) respondToProgressChange:(enum CallProgressType) progressType forLocallyInitiatedCall:(BOOL) initiatedLocally; --(void) respondToTerminationType:(enum CallTerminationType) terminationType; +- (void)respondToProgressChange:(enum CallProgressType)progressType forLocallyInitiatedCall:(BOOL)initiatedLocally; +- (void)respondToTerminationType:(enum CallTerminationType)terminationType; --(BOOL) toggleSpeakerPhone; --(void) cancellAllAudio; +- (BOOL)toggleSpeakerPhone; +- (void)cancellAllAudio; --(void) requestRequiredPermissionsIfNeededWithCompletion:(PermissionBlock)permissionBlock incoming:(BOOL)isIncoming; --(BOOL) requestRecordingPrivilege; --(BOOL) releaseRecordingPrivilege; +- (void)requestRequiredPermissionsIfNeededWithCompletion:(PermissionBlock)permissionBlock incoming:(BOOL)isIncoming; +- (BOOL)requestRecordingPrivilege; +- (BOOL)releaseRecordingPrivilege; --(BOOL) setAudioEnabled:(BOOL) enable; --(void) awake; +- (BOOL)setAudioEnabled:(BOOL)enable; +- (void)awake; - (void)didCompleteSoundInstanceOfType:(SoundInstanceType)instanceType; diff --git a/Signal/src/audio/AppAudioManager.m b/Signal/src/audio/AppAudioManager.m index 9bf6c2856..90f5635e3 100644 --- a/Signal/src/audio/AppAudioManager.m +++ b/Signal/src/audio/AppAudioManager.m @@ -8,9 +8,9 @@ #define RECORDING_CATEGORY AVAudioSessionCategoryPlayAndRecord -AppAudioManager* sharedAppAudioManager; +AppAudioManager *sharedAppAudioManager; -@interface AppAudioManager () { +@interface AppAudioManager () { enum AudioProfile _audioProfile; BOOL isSpeakerphoneActive; } @@ -20,10 +20,10 @@ AppAudioManager* sharedAppAudioManager; @implementation AppAudioManager -+(AppAudioManager*) sharedInstance { - @synchronized(self){ - if( nil == sharedAppAudioManager){ - sharedAppAudioManager = [AppAudioManager new]; ++ (AppAudioManager *)sharedInstance { + @synchronized(self) { + if (nil == sharedAppAudioManager) { + sharedAppAudioManager = [AppAudioManager new]; sharedAppAudioManager.soundPlayer = [SoundPlayer new]; [[sharedAppAudioManager soundPlayer] setDelegate:sharedAppAudioManager]; } @@ -33,15 +33,15 @@ AppAudioManager* sharedAppAudioManager; #pragma mark AudioState Management --(void) setAudioProfile:(enum AudioProfile) profile { +- (void)setAudioProfile:(enum AudioProfile)profile { [self updateAudioRouter]; - _audioProfile = profile; + _audioProfile = profile; } --(void) updateAudioRouter{ - if (isSpeakerphoneActive){ +- (void)updateAudioRouter { + if (isSpeakerphoneActive) { [AudioRouter routeAllAudioToExternalSpeaker]; - }else{ + } else { switch (_audioProfile) { case AudioProfile_Default: [AudioRouter routeAllAudioToInteralSpeaker]; @@ -56,24 +56,23 @@ AppAudioManager* sharedAppAudioManager; } --(void) overrideAudioProfile{ +- (void)overrideAudioProfile { isSpeakerphoneActive = YES; [self updateAudioRouter]; } --(void) resetOverride{ +- (void)resetOverride { isSpeakerphoneActive = NO; [self updateAudioRouter]; } --(enum AudioProfile) getCurrentAudioProfile{ +- (enum AudioProfile)getCurrentAudioProfile { return (isSpeakerphoneActive) ? AudioProfile_ExternalSpeaker : _audioProfile; } #pragma mark AudioControl; --(void) respondToProgressChange:(enum CallProgressType) progressType - forLocallyInitiatedCall:(BOOL) initiatedLocally { - switch (progressType){ +- (void)respondToProgressChange:(enum CallProgressType)progressType forLocallyInitiatedCall:(BOOL)initiatedLocally { + switch (progressType) { case CallProgressType_Connecting: [sharedAppAudioManager setAudioEnabled:YES]; case CallProgressType_Ringing: @@ -90,101 +89,102 @@ AppAudioManager* sharedAppAudioManager; } } --(void) respondToTerminationType:(enum CallTerminationType) terminationType { - if(terminationType == CallTerminationType_ResponderIsBusy) { +- (void)respondToTerminationType:(enum CallTerminationType)terminationType { + if (terminationType == CallTerminationType_ResponderIsBusy) { [_soundPlayer playSound:[SoundBoard instanceOfBusySound]]; - } - else if([self shouldErrorSoundBePlayedForCallTerminationType:terminationType]){ + } else if ([self shouldErrorSoundBePlayedForCallTerminationType:terminationType]) { [_soundPlayer playSound:[SoundBoard instanceOfErrorAlert]]; - } - else { + } else { [_soundPlayer playSound:[SoundBoard instanceOfAlert]]; } } --(BOOL) shouldErrorSoundBePlayedForCallTerminationType:(enum CallTerminationType) type{ +- (BOOL)shouldErrorSoundBePlayedForCallTerminationType:(enum CallTerminationType)type { [_soundPlayer stopAllAudio]; - if (type == CallTerminationType_RejectedLocal || - type == CallTerminationType_RejectedRemote || - type == CallTerminationType_HangupLocal || - type == CallTerminationType_HangupRemote || + if (type == CallTerminationType_RejectedLocal || type == CallTerminationType_RejectedRemote || + type == CallTerminationType_HangupLocal || type == CallTerminationType_HangupRemote || type == CallTerminationType_RecipientUnavailable) { return NO; } return YES; } --(void) handleInboundRing { +- (void)handleInboundRing { [_soundPlayer playSound:[SoundBoard instanceOfInboundRingtone]]; } --(void) handleOutboundRing { +- (void)handleOutboundRing { [self setAudioProfile:AudioProfile_Default]; [_soundPlayer playSound:[SoundBoard instanceOfOutboundRingtone]]; } --(void) handleSecuring { +- (void)handleSecuring { [_soundPlayer stopAllAudio]; [self setAudioProfile:AudioProfile_Default]; [_soundPlayer playSound:[SoundBoard instanceOfHandshakeSound]]; } --(void) handleCallEstablished { +- (void)handleCallEstablished { [_soundPlayer stopAllAudio]; [self setAudioProfile:AudioProfile_Default]; [_soundPlayer playSound:[SoundBoard instanceOfCompletedSound]]; } --(BOOL) toggleSpeakerPhone { - isSpeakerphoneActive=!isSpeakerphoneActive; +- (BOOL)toggleSpeakerPhone { + isSpeakerphoneActive = !isSpeakerphoneActive; [self updateAudioRouter]; - + return isSpeakerphoneActive; } #pragma mark Audio Control --(void) cancellAllAudio { +- (void)cancellAllAudio { [_soundPlayer stopAllAudio]; } --(BOOL) requestRecordingPrivilege { +- (BOOL)requestRecordingPrivilege { return [self changeAudioSessionCategoryTo:RECORDING_CATEGORY]; } --(BOOL) releaseRecordingPrivilege{ +- (BOOL)releaseRecordingPrivilege { return [self changeAudioSessionCategoryTo:DEFAULT_CATEGORY]; } --(void) requestRequiredPermissionsIfNeededWithCompletion:(PermissionBlock)permissionBlock incoming:(BOOL)isIncoming { +- (void)requestRequiredPermissionsIfNeededWithCompletion:(PermissionBlock)permissionBlock incoming:(BOOL)isIncoming { [AVAudioSession.sharedInstance requestRecordPermission:^(BOOL granted) { - if (!granted) { - UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"ACTION_REQUIRED_TITLE", @"") message:NSLocalizedString(@"AUDIO_PERMISSION_MESSAGE", @"") delegate:nil cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") otherButtonTitles:NSLocalizedString(@"SETTINGS_NAV_BAR_TITLE",nil), nil]; - - [alertView setDelegate:self]; - - [alertView show]; - } - - permissionBlock(granted); + if (!granted) { + UIAlertView *alertView = + [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"ACTION_REQUIRED_TITLE", @"") + message:NSLocalizedString(@"AUDIO_PERMISSION_MESSAGE", @"") + delegate:nil + cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") + otherButtonTitles:NSLocalizedString(@"SETTINGS_NAV_BAR_TITLE", nil), nil]; + + [alertView setDelegate:self]; + + [alertView show]; + } + + permissionBlock(granted); }]; } -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { if (buttonIndex == 1) { // Tapped the Settings button NSURL *appSettings = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; [[UIApplication sharedApplication] openURL:appSettings]; } } --(BOOL) changeAudioSessionCategoryTo:(NSString*) category { - NSError* e; +- (BOOL)changeAudioSessionCategoryTo:(NSString *)category { + NSError *e; [AVAudioSession.sharedInstance setCategory:category error:&e]; return (nil != e); } --(BOOL) setAudioEnabled:(BOOL) enable { - NSError* e; +- (BOOL)setAudioEnabled:(BOOL)enable { + NSError *e; if (enable) { [[AVAudioSession sharedInstance] setActive:enable error:&e]; [_soundPlayer awake]; @@ -193,22 +193,21 @@ AppAudioManager* sharedAppAudioManager; withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&e]; } - return ( nil !=e ); + return (nil != e); } --(void) awake { +- (void)awake { [_soundPlayer awake]; } #pragma mark Sound Player Delegate - (void)didCompleteSoundInstanceOfType:(SoundInstanceType)instanceType { - if (instanceType == SoundInstanceTypeBusySound || - instanceType == SoundInstanceTypeErrorAlert || + if (instanceType == SoundInstanceTypeBusySound || instanceType == SoundInstanceTypeErrorAlert || instanceType == SoundInstanceTypeAlert) { [sharedAppAudioManager setAudioEnabled:NO]; } } - + @end diff --git a/Signal/src/audio/AudioRouter.h b/Signal/src/audio/AudioRouter.h index 154a0cabb..ab849e841 100644 --- a/Signal/src/audio/AudioRouter.h +++ b/Signal/src/audio/AudioRouter.h @@ -3,14 +3,14 @@ /** * Interfaces with OS to control which hardware devices audio is routed to **/ - + @interface AudioRouter : NSObject -+(void) restoreDefaults; -+(void) routeAllAudioToInteralSpeaker; -+(void) routeAllAudioToExternalSpeaker; ++ (void)restoreDefaults; ++ (void)routeAllAudioToInteralSpeaker; ++ (void)routeAllAudioToExternalSpeaker; -+(BOOL) isOutputRoutedToSpeaker; -+(BOOL) isOutputRoutedToReciever; ++ (BOOL)isOutputRoutedToSpeaker; ++ (BOOL)isOutputRoutedToReciever; @end diff --git a/Signal/src/audio/AudioRouter.m b/Signal/src/audio/AudioRouter.m index e798f0210..04e2bd72e 100644 --- a/Signal/src/audio/AudioRouter.m +++ b/Signal/src/audio/AudioRouter.m @@ -6,40 +6,40 @@ @implementation AudioRouter -+(void) restoreDefaults { - AVAudioSession* session = AVAudioSession.sharedInstance; ++ (void)restoreDefaults { + AVAudioSession *session = AVAudioSession.sharedInstance; [session setActive:YES error:nil]; [AudioRouter routeAllAudioToExternalSpeaker]; } -+(void) routeAllAudioToInteralSpeaker { - AVAudioSession* session = AVAudioSession.sharedInstance; ++ (void)routeAllAudioToInteralSpeaker { + AVAudioSession *session = AVAudioSession.sharedInstance; [session setCategory:DEFAULT_CATAGORY error:nil]; } -+(void) routeAllAudioToExternalSpeaker { - AVAudioSession* session = AVAudioSession.sharedInstance; ++ (void)routeAllAudioToExternalSpeaker { + AVAudioSession *session = AVAudioSession.sharedInstance; [session setCategory:DEFAULT_CATAGORY withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil]; } -+(BOOL) isOutputRoutedToSpeaker{ - AVAudioSession* session = AVAudioSession.sharedInstance; - AVAudioSessionRouteDescription* routeDesc = session.currentRoute; - - for( AVAudioSessionPortDescription* portDesc in routeDesc.outputs){ - if (AVAudioSessionPortBuiltInSpeaker == [portDesc portType]){ ++ (BOOL)isOutputRoutedToSpeaker { + AVAudioSession *session = AVAudioSession.sharedInstance; + AVAudioSessionRouteDescription *routeDesc = session.currentRoute; + + for (AVAudioSessionPortDescription *portDesc in routeDesc.outputs) { + if (AVAudioSessionPortBuiltInSpeaker == [portDesc portType]) { return YES; } } return NO; } -+(BOOL) isOutputRoutedToReciever{ - AVAudioSession* session = AVAudioSession.sharedInstance; - AVAudioSessionRouteDescription* routeDesc = session.currentRoute; - - for( AVAudioSessionPortDescription* portDesc in routeDesc.outputs){ - if (AVAudioSessionPortBuiltInReceiver == [portDesc portType]){ ++ (BOOL)isOutputRoutedToReciever { + AVAudioSession *session = AVAudioSession.sharedInstance; + AVAudioSessionRouteDescription *routeDesc = session.currentRoute; + + for (AVAudioSessionPortDescription *portDesc in routeDesc.outputs) { + if (AVAudioSessionPortBuiltInReceiver == [portDesc portType]) { return YES; } } diff --git a/Signal/src/audio/SoundBoard.h b/Signal/src/audio/SoundBoard.h index 6fdb21373..809d7eb91 100644 --- a/Signal/src/audio/SoundBoard.h +++ b/Signal/src/audio/SoundBoard.h @@ -3,19 +3,19 @@ #import "SoundInstance.h" /** - * Factory class for generating Instances of specific Sound files. These are then maintained + * Factory class for generating Instances of specific Sound files. These are then maintained * and controlled from the SoundPlayer class. This class should mask the use of any specific * soundFiles. **/ @interface SoundBoard : NSObject -+(SoundInstance*) instanceOfInboundRingtone; -+(SoundInstance*) instanceOfOutboundRingtone; -+(SoundInstance*) instanceOfHandshakeSound; -+(SoundInstance*) instanceOfCompletedSound; -+(SoundInstance*) instanceOfBusySound; -+(SoundInstance*) instanceOfErrorAlert; -+(SoundInstance*) instanceOfAlert; ++ (SoundInstance *)instanceOfInboundRingtone; ++ (SoundInstance *)instanceOfOutboundRingtone; ++ (SoundInstance *)instanceOfHandshakeSound; ++ (SoundInstance *)instanceOfCompletedSound; ++ (SoundInstance *)instanceOfBusySound; ++ (SoundInstance *)instanceOfErrorAlert; ++ (SoundInstance *)instanceOfAlert; @end diff --git a/Signal/src/audio/SoundBoard.m b/Signal/src/audio/SoundBoard.m index d6ede786e..dfa5a43c3 100644 --- a/Signal/src/audio/SoundBoard.m +++ b/Signal/src/audio/SoundBoard.m @@ -1,61 +1,60 @@ #import "SoundBoard.h" -static NSString* SoundFile_Alert =@"171756__nenadsimic__picked-coin-echo-2.wav"; -static NSString* SoundFile_Busy =@"busy.mp3"; -static NSString* SoundFile_Completed =@"completed.mp3"; -static NSString* SoundFile_Failure =@"failure.mp3"; -static NSString* SoundFile_Handshake =@"handshake.mp3"; -static NSString* SoundFile_Outbound =@"outring.mp3"; -static NSString* SoundFile_Ringtone =@"r.caf"; +static NSString *SoundFile_Alert = @"171756__nenadsimic__picked-coin-echo-2.wav"; +static NSString *SoundFile_Busy = @"busy.mp3"; +static NSString *SoundFile_Completed = @"completed.mp3"; +static NSString *SoundFile_Failure = @"failure.mp3"; +static NSString *SoundFile_Handshake = @"handshake.mp3"; +static NSString *SoundFile_Outbound = @"outring.mp3"; +static NSString *SoundFile_Ringtone = @"r.caf"; @implementation SoundBoard -+(SoundInstance*) instanceOfInboundRingtone { - SoundInstance* soundInstance = [SoundInstance soundInstanceForFile:SoundFile_Ringtone]; ++ (SoundInstance *)instanceOfInboundRingtone { + SoundInstance *soundInstance = [SoundInstance soundInstanceForFile:SoundFile_Ringtone]; [soundInstance setAudioToLoopIndefinitely]; [soundInstance setInstanceType:SoundInstanceTypeInboundRingtone]; return soundInstance; } -+(SoundInstance*) instanceOfOutboundRingtone { - SoundInstance* soundInstance = [SoundInstance soundInstanceForFile:SoundFile_Outbound]; ++ (SoundInstance *)instanceOfOutboundRingtone { + SoundInstance *soundInstance = [SoundInstance soundInstanceForFile:SoundFile_Outbound]; [soundInstance setAudioToLoopIndefinitely]; [soundInstance setInstanceType:SoundInstanceTypeOutboundRingtone]; return soundInstance; } -+(SoundInstance*) instanceOfHandshakeSound { - SoundInstance* soundInstance = [SoundInstance soundInstanceForFile:SoundFile_Handshake]; ++ (SoundInstance *)instanceOfHandshakeSound { + SoundInstance *soundInstance = [SoundInstance soundInstanceForFile:SoundFile_Handshake]; [soundInstance setAudioToLoopIndefinitely]; [soundInstance setInstanceType:SoundInstanceTypeHandshakeSound]; return soundInstance; } -+(SoundInstance*) instanceOfCompletedSound { - SoundInstance* soundInstance = [SoundInstance soundInstanceForFile:SoundFile_Completed]; ++ (SoundInstance *)instanceOfCompletedSound { + SoundInstance *soundInstance = [SoundInstance soundInstanceForFile:SoundFile_Completed]; [soundInstance setInstanceType:SoundInstanceTypeCompletedSound]; return soundInstance; } -+(SoundInstance*) instanceOfBusySound { - SoundInstance* soundInstance = [SoundInstance soundInstanceForFile:SoundFile_Busy]; ++ (SoundInstance *)instanceOfBusySound { + SoundInstance *soundInstance = [SoundInstance soundInstanceForFile:SoundFile_Busy]; [soundInstance setAudioLoopCount:10]; [soundInstance setInstanceType:SoundInstanceTypeBusySound]; return soundInstance; } -+(SoundInstance*) instanceOfErrorAlert { - SoundInstance* soundInstance = [SoundInstance soundInstanceForFile:SoundFile_Failure]; ++ (SoundInstance *)instanceOfErrorAlert { + SoundInstance *soundInstance = [SoundInstance soundInstanceForFile:SoundFile_Failure]; [soundInstance setInstanceType:SoundInstanceTypeErrorAlert]; return soundInstance; } -+(SoundInstance*) instanceOfAlert { - SoundInstance* soundInstance = [SoundInstance soundInstanceForFile:SoundFile_Alert]; ++ (SoundInstance *)instanceOfAlert { + SoundInstance *soundInstance = [SoundInstance soundInstanceForFile:SoundFile_Alert]; [soundInstance setInstanceType:SoundInstanceTypeAlert]; return soundInstance; } - @end diff --git a/Signal/src/audio/SoundInstance.h b/Signal/src/audio/SoundInstance.h index 80299e552..4a3e90df4 100644 --- a/Signal/src/audio/SoundInstance.h +++ b/Signal/src/audio/SoundInstance.h @@ -19,13 +19,12 @@ typedef enum { @property (nonatomic) SoundInstanceType instanceType; -+(SoundInstance*) soundInstanceForFile:(NSString*) audioFile; --(NSString*) getId; ++ (SoundInstance *)soundInstanceForFile:(NSString *)audioFile; +- (NSString *)getId; --(void) setAudioToLoopIndefinitely; --(void) setAudioLoopCount:(NSInteger) loopCount; --(void) setCompeletionBlock:(void (^)(SoundInstance*)) block; +- (void)setAudioToLoopIndefinitely; +- (void)setAudioLoopCount:(NSInteger)loopCount; +- (void)setCompeletionBlock:(void (^)(SoundInstance *))block; -- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player - successfully:(BOOL)flag; +- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag; @end diff --git a/Signal/src/audio/SoundInstance.m b/Signal/src/audio/SoundInstance.m index 87caf0ee4..d1531beb7 100644 --- a/Signal/src/audio/SoundInstance.m +++ b/Signal/src/audio/SoundInstance.m @@ -1,7 +1,7 @@ #import "SoundInstance.h" -@interface SoundInstance (){ - void (^completionBlock)(SoundInstance*); +@interface SoundInstance () { + void (^completionBlock)(SoundInstance *); } @property (retain) AVAudioPlayer *audioPlayer; @@ -10,31 +10,31 @@ @implementation SoundInstance -+(SoundInstance*) soundInstanceForFile:(NSString*) audioFile { - SoundInstance* soundInstance = [SoundInstance new]; - soundInstance.audioPlayer = [soundInstance.class createAudioPlayerForFile:audioFile]; ++ (SoundInstance *)soundInstanceForFile:(NSString *)audioFile { + SoundInstance *soundInstance = [SoundInstance new]; + soundInstance.audioPlayer = [soundInstance.class createAudioPlayerForFile:audioFile]; [soundInstance.audioPlayer setDelegate:soundInstance]; return soundInstance; } --(NSString*) getId{ +- (NSString *)getId { return [[self.audioPlayer url] absoluteString]; } --(void) play { +- (void)play { [self.audioPlayer play]; } --(void) stop { +- (void)stop { [self.audioPlayer stop]; [self audioPlayerDidFinishPlaying:self.audioPlayer successfully:YES]; } --(void) setAudioToLoopIndefinitely { +- (void)setAudioToLoopIndefinitely { self.audioPlayer.numberOfLoops = -1; } --(void) setAudioLoopCount:(NSInteger) loopCount { +- (void)setAudioLoopCount:(NSInteger)loopCount { self.audioPlayer.numberOfLoops = loopCount; } @@ -45,25 +45,26 @@ return _instanceType; } -+(NSURL*) urlToFile:(NSString*) file { - return [NSURL fileURLWithPath: - [NSString stringWithFormat:@"%@/%@", NSBundle.mainBundle.resourcePath,file]]; ++ (NSURL *)urlToFile:(NSString *)file { + return [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@", NSBundle.mainBundle.resourcePath, file]]; } -+(AVAudioPlayer*) createAudioPlayerForFile:(NSString*) audioFile { - NSURL* url = [self urlToFile:audioFile]; - ++ (AVAudioPlayer *)createAudioPlayerForFile:(NSString *)audioFile { + NSURL *url = [self urlToFile:audioFile]; + NSError *error; - AVAudioPlayer* audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error]; - if (nil == audioPlayer){ NSLog(@" %@",[error description]);} + AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error]; + if (nil == audioPlayer) { + NSLog(@" %@", [error description]); + } return audioPlayer; } --(void) setCompeletionBlock:(void (^)(SoundInstance* )) block { +- (void)setCompeletionBlock:(void (^)(SoundInstance *))block { completionBlock = block; } --(void) audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { +- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { completionBlock(self); } @end diff --git a/Signal/src/audio/SoundPlayer.h b/Signal/src/audio/SoundPlayer.h index b5ca76921..55c78feea 100644 --- a/Signal/src/audio/SoundPlayer.h +++ b/Signal/src/audio/SoundPlayer.h @@ -2,7 +2,7 @@ #import "SoundInstance.h" /** - * SoundPlayer tracks and controls all Audiofiles being played. Currently only one instance + * SoundPlayer tracks and controls all Audiofiles being played. Currently only one instance * of a given sound can be played at a given time. Attemping to play multiple intances of a * sound is ignored. Multiple different sound instances can be played concurrently. */ @@ -13,11 +13,11 @@ @property (strong, nonatomic) id delegate; --(void) playSound:(SoundInstance*) player; --(void) stopSound:(SoundInstance*) player; +- (void)playSound:(SoundInstance *)player; +- (void)stopSound:(SoundInstance *)player; --(void) stopAllAudio; --(void) awake; +- (void)stopAllAudio; +- (void)awake; @end diff --git a/Signal/src/audio/SoundPlayer.m b/Signal/src/audio/SoundPlayer.m index 8bedc2b45..38bb9ca01 100644 --- a/Signal/src/audio/SoundPlayer.m +++ b/Signal/src/audio/SoundPlayer.m @@ -1,15 +1,15 @@ #import "SoundPlayer.h" @interface SoundInstance () --(void) play; --(void) stop; +- (void)play; +- (void)stop; @end @implementation SoundPlayer -NSMutableDictionary* currentActiveAudioPlayers; +NSMutableDictionary *currentActiveAudioPlayers; --(SoundPlayer*) init{ +- (SoundPlayer *)init { currentActiveAudioPlayers = [NSMutableDictionary dictionary]; return self; } @@ -17,52 +17,52 @@ NSMutableDictionary* currentActiveAudioPlayers; #pragma mark Delegate Implementations --(void) addSoundToManifest:(SoundInstance*) sound { - @synchronized(currentActiveAudioPlayers){ - [sound setCompeletionBlock:^(SoundInstance* soundInst) { - [self removeSoundFromManifest:soundInst]; - if (self.delegate) { - [self.delegate didCompleteSoundInstanceOfType:soundInst.instanceType]; - } +- (void)addSoundToManifest:(SoundInstance *)sound { + @synchronized(currentActiveAudioPlayers) { + [sound setCompeletionBlock:^(SoundInstance *soundInst) { + [self removeSoundFromManifest:soundInst]; + if (self.delegate) { + [self.delegate didCompleteSoundInstanceOfType:soundInst.instanceType]; + } }]; [currentActiveAudioPlayers setValue:sound forKey:sound.getId]; } } --(void) removeSoundFromManifest:(SoundInstance*) sound { +- (void)removeSoundFromManifest:(SoundInstance *)sound { [self removeSoundFromMainifestById:sound.getId]; } --(void) removeSoundFromMainifestById:(NSString*) soundId { - @synchronized(currentActiveAudioPlayers){ +- (void)removeSoundFromMainifestById:(NSString *)soundId { + @synchronized(currentActiveAudioPlayers) { [currentActiveAudioPlayers removeObjectForKey:soundId]; } } --(void) playSound:(SoundInstance*) sound { - if (![self isSoundPlaying:sound]){ +- (void)playSound:(SoundInstance *)sound { + if (![self isSoundPlaying:sound]) { [self addSoundToManifest:sound]; [sound play]; } } --(void) stopSound:(SoundInstance*) sound { - SoundInstance* playingSoundInstance = currentActiveAudioPlayers[sound.getId]; +- (void)stopSound:(SoundInstance *)sound { + SoundInstance *playingSoundInstance = currentActiveAudioPlayers[sound.getId]; [self removeSoundFromManifest:sound]; [playingSoundInstance stop]; } --(void) stopAllAudio{ - for( SoundInstance* sound in currentActiveAudioPlayers.allValues){ +- (void)stopAllAudio { + for (SoundInstance *sound in currentActiveAudioPlayers.allValues) { [self stopSound:sound]; } } --(BOOL) isSoundPlaying:(SoundInstance*) sound { +- (BOOL)isSoundPlaying:(SoundInstance *)sound { return nil != currentActiveAudioPlayers[sound.getId]; } --(void) awake { - for( SoundInstance* sound in currentActiveAudioPlayers.allValues){ +- (void)awake { + for (SoundInstance *sound in currentActiveAudioPlayers.allValues) { [sound play]; } } diff --git a/Signal/src/audio/incall_audio/AudioPacker.h b/Signal/src/audio/incall_audio/AudioPacker.h index ddf1dbc00..e1e6b5739 100644 --- a/Signal/src/audio/incall_audio/AudioPacker.h +++ b/Signal/src/audio/incall_audio/AudioPacker.h @@ -1,7 +1,7 @@ #import -#import "Queue.h" #import "EncodedAudioFrame.h" #import "EncodedAudioPacket.h" +#import "Queue.h" #define AUDIO_FRAMES_PER_PACKET 2 @@ -18,17 +18,20 @@ * */ @interface AudioPacker : NSObject { -@private NSMutableArray* framesToSend; -@private uint16_t nextSequenceNumber; -@private Queue* audioFrameToReceiveQueue; + @private + NSMutableArray *framesToSend; + @private + uint16_t nextSequenceNumber; + @private + Queue *audioFrameToReceiveQueue; } -+(AudioPacker*) audioPacker; ++ (AudioPacker *)audioPacker; --(void)packFrame:(EncodedAudioFrame*)frame; --(EncodedAudioPacket*) tryGetFinishedAudioPacket; +- (void)packFrame:(EncodedAudioFrame *)frame; +- (EncodedAudioPacket *)tryGetFinishedAudioPacket; --(void)unpackPotentiallyMissingAudioPacket:(EncodedAudioPacket*)potentiallyMissingPacket; --(EncodedAudioFrame*) tryGetReceivedFrame; +- (void)unpackPotentiallyMissingAudioPacket:(EncodedAudioPacket *)potentiallyMissingPacket; +- (EncodedAudioFrame *)tryGetReceivedFrame; @end diff --git a/Signal/src/audio/incall_audio/AudioPacker.m b/Signal/src/audio/incall_audio/AudioPacker.m index a08468a16..54d05ac8b 100644 --- a/Signal/src/audio/incall_audio/AudioPacker.m +++ b/Signal/src/audio/incall_audio/AudioPacker.m @@ -1,42 +1,43 @@ #import "AudioPacker.h" -#import "CryptoTools.h" #import "Conversions.h" +#import "CryptoTools.h" #import "Util.h" @implementation AudioPacker -+(AudioPacker*) audioPacker { - AudioPacker* newAudioPackerInstance = [AudioPacker new]; ++ (AudioPacker *)audioPacker { + AudioPacker *newAudioPackerInstance = [AudioPacker new]; newAudioPackerInstance->audioFrameToReceiveQueue = [Queue new]; - newAudioPackerInstance->framesToSend = [NSMutableArray array]; - newAudioPackerInstance->nextSequenceNumber = [CryptoTools generateSecureRandomUInt16]; - + newAudioPackerInstance->framesToSend = [NSMutableArray array]; + newAudioPackerInstance->nextSequenceNumber = [CryptoTools generateSecureRandomUInt16]; + // interop fix: // cut off the high bit (the sign bit), to avoid confusion over signed-ness when peer receives the initial number - // also cut off the next bit, so that at least 2^14 packets (instead of 1) must fail to arrive before confusion can be caused + // also cut off the next bit, so that at least 2^14 packets (instead of 1) must fail to arrive before confusion can + // be caused newAudioPackerInstance->nextSequenceNumber &= 0x3FFF; - + return newAudioPackerInstance; } --(void)packFrame:(EncodedAudioFrame*)frame{ - require(frame != nil); - require(!frame.isMissingAudioData); +- (void)packFrame:(EncodedAudioFrame *)frame { + ows_require(frame != nil); + ows_require(!frame.isMissingAudioData); [framesToSend addObject:frame.tryGetAudioData]; } --(EncodedAudioPacket*) tryGetFinishedAudioPacket{ - if (framesToSend.count < AUDIO_FRAMES_PER_PACKET) return nil; - +- (EncodedAudioPacket *)tryGetFinishedAudioPacket { + if (framesToSend.count < AUDIO_FRAMES_PER_PACKET) + return nil; + uint16_t sequenceNumber = nextSequenceNumber++; - NSData* payload = [framesToSend ows_concatDatas]; - + NSData *payload = [framesToSend ows_concatDatas]; + [framesToSend removeAllObjects]; - return [EncodedAudioPacket encodedAudioPacketWithAudioData:payload - andSequenceNumber:sequenceNumber]; + return [EncodedAudioPacket encodedAudioPacketWithAudioData:payload andSequenceNumber:sequenceNumber]; } --(void)unpackPotentiallyMissingAudioPacket:(EncodedAudioPacket*)potentiallyMissingPacket{ +- (void)unpackPotentiallyMissingAudioPacket:(EncodedAudioPacket *)potentiallyMissingPacket { if (potentiallyMissingPacket != nil) { [self enqueueFramesForPacket:potentiallyMissingPacket]; } else { @@ -44,26 +45,26 @@ } } --(EncodedAudioFrame*) tryGetReceivedFrame{ +- (EncodedAudioFrame *)tryGetReceivedFrame { return [audioFrameToReceiveQueue tryDequeue]; } #pragma mark - #pragma mark Private Methods --(void) enqueueFramesForPacket:(EncodedAudioPacket*)packet { - require(packet != nil); - - NSData* audioData = [packet audioData]; +- (void)enqueueFramesForPacket:(EncodedAudioPacket *)packet { + ows_require(packet != nil); + + NSData *audioData = [packet audioData]; requireState(audioData.length % AUDIO_FRAMES_PER_PACKET == 0); - + NSUInteger frameSize = audioData.length / AUDIO_FRAMES_PER_PACKET; for (NSUInteger i = 0; i < AUDIO_FRAMES_PER_PACKET; i++) { - NSData* frameData = [audioData subdataWithRange:NSMakeRange(frameSize*i, frameSize)]; + NSData *frameData = [audioData subdataWithRange:NSMakeRange(frameSize * i, frameSize)]; [audioFrameToReceiveQueue enqueue:[EncodedAudioFrame encodedAudioFrameWithData:frameData]]; } } --(void) enqueueFramesForMissingPacket { +- (void)enqueueFramesForMissingPacket { for (NSUInteger i = 0; i < AUDIO_FRAMES_PER_PACKET; i++) { [audioFrameToReceiveQueue enqueue:[EncodedAudioFrame encodedAudioFrameWithoutData]]; } diff --git a/Signal/src/audio/incall_audio/AudioSocket.h b/Signal/src/audio/incall_audio/AudioSocket.h index efd0a6b03..c253eb74e 100644 --- a/Signal/src/audio/incall_audio/AudioSocket.h +++ b/Signal/src/audio/incall_audio/AudioSocket.h @@ -9,12 +9,14 @@ * **/ @interface AudioSocket : NSObject { -@private SrtpSocket* srtpSocket; -@private bool started; + @private + SrtpSocket *srtpSocket; + @private + bool started; } -+(AudioSocket*) audioSocketOver:(SrtpSocket*)srtpSocket; --(void) startWithHandler:(PacketHandler*)handler untilCancelled:(TOCCancelToken*)untilCancelledToken; --(void) send:(EncodedAudioPacket*)audioPacket; ++ (AudioSocket *)audioSocketOver:(SrtpSocket *)srtpSocket; +- (void)startWithHandler:(PacketHandler *)handler untilCancelled:(TOCCancelToken *)untilCancelledToken; +- (void)send:(EncodedAudioPacket *)audioPacket; @end diff --git a/Signal/src/audio/incall_audio/AudioSocket.m b/Signal/src/audio/incall_audio/AudioSocket.m index 54922b5e8..1b67e5c73 100644 --- a/Signal/src/audio/incall_audio/AudioSocket.m +++ b/Signal/src/audio/incall_audio/AudioSocket.m @@ -2,33 +2,32 @@ @implementation AudioSocket -+(AudioSocket*) audioSocketOver:(SrtpSocket*)srtpSocket { - require(srtpSocket != nil); - AudioSocket* p = [AudioSocket new]; - p->srtpSocket = srtpSocket; ++ (AudioSocket *)audioSocketOver:(SrtpSocket *)srtpSocket { + ows_require(srtpSocket != nil); + AudioSocket *p = [AudioSocket new]; + p->srtpSocket = srtpSocket; return p; } --(void) startWithHandler:(PacketHandler*)handler untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(handler != nil); +- (void)startWithHandler:(PacketHandler *)handler untilCancelled:(TOCCancelToken *)untilCancelledToken { + ows_require(handler != nil); requireState(!started); started = true; - - PacketHandlerBlock valueHandler = ^(RtpPacket* rtpPacket) { - require(rtpPacket != nil); - require([rtpPacket isKindOfClass:[RtpPacket class]]); - [handler handlePacket:[EncodedAudioPacket encodedAudioPacketWithAudioData:[rtpPacket payload] - andSequenceNumber:[rtpPacket sequenceNumber]]]; + + PacketHandlerBlock valueHandler = ^(RtpPacket *rtpPacket) { + ows_require(rtpPacket != nil); + ows_require([rtpPacket isKindOfClass:[RtpPacket class]]); + [handler handlePacket:[EncodedAudioPacket encodedAudioPacketWithAudioData:[rtpPacket payload] + andSequenceNumber:[rtpPacket sequenceNumber]]]; }; - - [srtpSocket startWithHandler:[PacketHandler packetHandler:valueHandler - withErrorHandler:[handler errorHandler]] + + [srtpSocket startWithHandler:[PacketHandler packetHandler:valueHandler withErrorHandler:[handler errorHandler]] untilCancelled:untilCancelledToken]; } --(void) send:(EncodedAudioPacket*)audioPacket { - require(audioPacket != nil); - - RtpPacket* rtpPacket = [RtpPacket rtpPacketWithDefaultsAndSequenceNumber:[audioPacket sequenceNumber] +- (void)send:(EncodedAudioPacket *)audioPacket { + ows_require(audioPacket != nil); + + RtpPacket *rtpPacket = [RtpPacket rtpPacketWithDefaultsAndSequenceNumber:[audioPacket sequenceNumber] andPayload:[audioPacket audioData]]; [srtpSocket secureAndSendRtpPacket:rtpPacket]; } diff --git a/Signal/src/audio/incall_audio/CallAudioManager.h b/Signal/src/audio/incall_audio/CallAudioManager.h index 28290bbb1..d8d1bfaeb 100644 --- a/Signal/src/audio/incall_audio/CallAudioManager.h +++ b/Signal/src/audio/incall_audio/CallAudioManager.h @@ -7,22 +7,28 @@ /** * - * CallAudioManager is responsible for creating and managing components related to playing real time audio communicated over a network. + * CallAudioManager is responsible for creating and managing components related to playing real time audio communicated + *over a network. * * The components are for playing/recording, processing, and transporting audio data. * **/ -@interface CallAudioManager : NSObject { -@private RemoteIOAudio* audioInterface; -@private AudioProcessor* audioProcessor; -@private AudioSocket* audioSocket; -@private bool started; -@private NSUInteger bytesInPlaybackBuffer; +@interface CallAudioManager : NSObject { + @private + RemoteIOAudio *audioInterface; + @private + AudioProcessor *audioProcessor; + @private + AudioSocket *audioSocket; + @private + bool started; + @private + NSUInteger bytesInPlaybackBuffer; } -+(CallAudioManager*) callAudioManagerStartedWithAudioSocket:(AudioSocket*)audioSocket - andErrorHandler:(ErrorHandlerBlock)errorHandler - untilCancelled:(TOCCancelToken*)untilCancelledToken; --(BOOL) toggleMute; ++ (CallAudioManager *)callAudioManagerStartedWithAudioSocket:(AudioSocket *)audioSocket + andErrorHandler:(ErrorHandlerBlock)errorHandler + untilCancelled:(TOCCancelToken *)untilCancelledToken; +- (BOOL)toggleMute; @end diff --git a/Signal/src/audio/incall_audio/CallAudioManager.m b/Signal/src/audio/incall_audio/CallAudioManager.m index 833f5a742..24e47051b 100644 --- a/Signal/src/audio/incall_audio/CallAudioManager.m +++ b/Signal/src/audio/incall_audio/CallAudioManager.m @@ -5,63 +5,64 @@ @implementation CallAudioManager -+(CallAudioManager*) callAudioManagerStartedWithAudioSocket:(AudioSocket*)audioSocket - andErrorHandler:(ErrorHandlerBlock)errorHandler - untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(audioSocket != nil); - - AudioProcessor* processor = [AudioProcessor audioProcessor]; - - CallAudioManager* newCallAudioManagerInstance = [CallAudioManager new]; - newCallAudioManagerInstance->audioProcessor = processor; - newCallAudioManagerInstance->audioSocket = audioSocket; - ++ (CallAudioManager *)callAudioManagerStartedWithAudioSocket:(AudioSocket *)audioSocket + andErrorHandler:(ErrorHandlerBlock)errorHandler + untilCancelled:(TOCCancelToken *)untilCancelledToken { + ows_require(audioSocket != nil); + + AudioProcessor *processor = [AudioProcessor audioProcessor]; + + CallAudioManager *newCallAudioManagerInstance = [CallAudioManager new]; + newCallAudioManagerInstance->audioProcessor = processor; + newCallAudioManagerInstance->audioSocket = audioSocket; + [newCallAudioManagerInstance startWithErrorHandler:errorHandler untilCancelled:untilCancelledToken]; - + return newCallAudioManagerInstance; } --(void) startWithErrorHandler:(ErrorHandlerBlock)errorHandler untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(errorHandler != nil); - require(untilCancelledToken != nil); +- (void)startWithErrorHandler:(ErrorHandlerBlock)errorHandler untilCancelled:(TOCCancelToken *)untilCancelledToken { + ows_require(errorHandler != nil); + ows_require(untilCancelledToken != nil); @synchronized(self) { requireState(!started); started = true; - if (untilCancelledToken.isAlreadyCancelled) return; + if (untilCancelledToken.isAlreadyCancelled) + return; audioInterface = [RemoteIOAudio remoteIOInterfaceStartedWithDelegate:self untilCancelled:untilCancelledToken]; - PacketHandlerBlock handler = ^(EncodedAudioPacket* packet) { - [audioProcessor receivedPacket:packet]; + PacketHandlerBlock handler = ^(EncodedAudioPacket *packet) { + [audioProcessor receivedPacket:packet]; }; - [audioSocket startWithHandler:[PacketHandler packetHandler:handler - withErrorHandler:errorHandler] + [audioSocket startWithHandler:[PacketHandler packetHandler:handler withErrorHandler:errorHandler] untilCancelled:untilCancelledToken]; } } --(void) handlePlaybackOccurredWithBytesRequested:(NSUInteger)requested andBytesRemaining:(NSUInteger)bytesRemaining { +- (void)handlePlaybackOccurredWithBytesRequested:(NSUInteger)requested andBytesRemaining:(NSUInteger)bytesRemaining { if (bytesInPlaybackBuffer >= requested) { bytesInPlaybackBuffer -= requested; } - + NSUInteger bytesAddedIfPullMore = [audioProcessor.codec decodedFrameSizeInBytes]; - double minSafeBufferSize = MAX(requested, bytesAddedIfPullMore)*SAFETY_FACTOR_FOR_COMPUTE_DELAY; + double minSafeBufferSize = MAX(requested, bytesAddedIfPullMore) * SAFETY_FACTOR_FOR_COMPUTE_DELAY; while (bytesInPlaybackBuffer < minSafeBufferSize) { - NSData* decodedAudioData = [audioProcessor tryDecodeOrInferFrame]; - if (decodedAudioData == nil) break; + NSData *decodedAudioData = [audioProcessor tryDecodeOrInferFrame]; + if (decodedAudioData == nil) + break; [audioInterface populatePlaybackQueueWithData:decodedAudioData]; bytesInPlaybackBuffer += decodedAudioData.length; } } --(void) handleNewDataRecorded:(CyclicalBuffer*)recordingQueue { - NSArray* encodedPackets = [audioProcessor encodeAudioPacketsFromBuffer:recordingQueue]; - for (EncodedAudioPacket* packet in encodedPackets) { +- (void)handleNewDataRecorded:(CyclicalBuffer *)recordingQueue { + NSArray *encodedPackets = [audioProcessor encodeAudioPacketsFromBuffer:recordingQueue]; + for (EncodedAudioPacket *packet in encodedPackets) { [audioSocket send:packet]; } } --(BOOL) toggleMute { - return [audioInterface toggleMute]; +- (BOOL)toggleMute { + return [audioInterface toggleMute]; } @end diff --git a/Signal/src/audio/incall_audio/EncodedAudioFrame.h b/Signal/src/audio/incall_audio/EncodedAudioFrame.h index d319ba040..436547b50 100644 --- a/Signal/src/audio/incall_audio/EncodedAudioFrame.h +++ b/Signal/src/audio/incall_audio/EncodedAudioFrame.h @@ -8,13 +8,14 @@ **/ @interface EncodedAudioFrame : NSObject { -@private NSData* audioData; + @private + NSData *audioData; } -+(EncodedAudioFrame*) encodedAudioFrameWithData:(NSData*)audioData; -+(EncodedAudioFrame*) encodedAudioFrameWithoutData; ++ (EncodedAudioFrame *)encodedAudioFrameWithData:(NSData *)audioData; ++ (EncodedAudioFrame *)encodedAudioFrameWithoutData; --(bool) isMissingAudioData; --(NSData*) tryGetAudioData; +- (bool)isMissingAudioData; +- (NSData *)tryGetAudioData; @end diff --git a/Signal/src/audio/incall_audio/EncodedAudioFrame.m b/Signal/src/audio/incall_audio/EncodedAudioFrame.m index 8cfff96c8..266f76b77 100644 --- a/Signal/src/audio/incall_audio/EncodedAudioFrame.m +++ b/Signal/src/audio/incall_audio/EncodedAudioFrame.m @@ -1,22 +1,22 @@ -#import "EncodedAudioFrame.h" #import "Constraints.h" +#import "EncodedAudioFrame.h" @implementation EncodedAudioFrame -+(EncodedAudioFrame*) encodedAudioFrameWithData:(NSData*)audioData { - require(audioData != nil); - EncodedAudioFrame* frame = [EncodedAudioFrame new]; - frame->audioData = audioData; ++ (EncodedAudioFrame *)encodedAudioFrameWithData:(NSData *)audioData { + ows_require(audioData != nil); + EncodedAudioFrame *frame = [EncodedAudioFrame new]; + frame->audioData = audioData; return frame; } -+(EncodedAudioFrame*) encodedAudioFrameWithoutData { ++ (EncodedAudioFrame *)encodedAudioFrameWithoutData { return [EncodedAudioFrame new]; } --(bool) isMissingAudioData { +- (bool)isMissingAudioData { return audioData == nil; } --(NSData*) tryGetAudioData { +- (NSData *)tryGetAudioData { return audioData; } diff --git a/Signal/src/audio/incall_audio/EncodedAudioPacket.h b/Signal/src/audio/incall_audio/EncodedAudioPacket.h index 21e89e8dd..002a01409 100644 --- a/Signal/src/audio/incall_audio/EncodedAudioPacket.h +++ b/Signal/src/audio/incall_audio/EncodedAudioPacket.h @@ -11,9 +11,9 @@ **/ @interface EncodedAudioPacket : NSObject -@property (readonly,nonatomic) NSData* audioData; -@property (readonly,nonatomic) uint16_t sequenceNumber; +@property (readonly, nonatomic) NSData *audioData; +@property (readonly, nonatomic) uint16_t sequenceNumber; -+(EncodedAudioPacket*) encodedAudioPacketWithAudioData:(NSData*)audioData andSequenceNumber:(uint16_t)sequenceNumber; ++ (EncodedAudioPacket *)encodedAudioPacketWithAudioData:(NSData *)audioData andSequenceNumber:(uint16_t)sequenceNumber; @end diff --git a/Signal/src/audio/incall_audio/EncodedAudioPacket.m b/Signal/src/audio/incall_audio/EncodedAudioPacket.m index 3cc063217..421aa18f5 100644 --- a/Signal/src/audio/incall_audio/EncodedAudioPacket.m +++ b/Signal/src/audio/incall_audio/EncodedAudioPacket.m @@ -1,15 +1,15 @@ -#import "EncodedAudioPacket.h" #import "Constraints.h" +#import "EncodedAudioPacket.h" @implementation EncodedAudioPacket @synthesize audioData, sequenceNumber; -+(EncodedAudioPacket*) encodedAudioPacketWithAudioData:(NSData*)audioData andSequenceNumber:(uint16_t)sequenceNumber { - require(audioData != nil); - EncodedAudioPacket* p = [EncodedAudioPacket new]; - p->audioData = audioData; - p->sequenceNumber = sequenceNumber; ++ (EncodedAudioPacket *)encodedAudioPacketWithAudioData:(NSData *)audioData andSequenceNumber:(uint16_t)sequenceNumber { + ows_require(audioData != nil); + EncodedAudioPacket *p = [EncodedAudioPacket new]; + p->audioData = audioData; + p->sequenceNumber = sequenceNumber; return p; } diff --git a/Signal/src/audio/incall_audio/RemoteIOAudio.h b/Signal/src/audio/incall_audio/RemoteIOAudio.h index 2ed807f3d..61bb0e59e 100644 --- a/Signal/src/audio/incall_audio/RemoteIOAudio.h +++ b/Signal/src/audio/incall_audio/RemoteIOAudio.h @@ -1,21 +1,17 @@ -#import -#import #import +#import +#import #import "AudioCallbackHandler.h" #import "CyclicalBuffer.h" #import "Environment.h" #import "RemoteIOBufferListWrapper.h" #import "Terminable.h" -enum State { - NOT_STARTED, - STARTED, - TERMINATED -}; +enum State { NOT_STARTED, STARTED, TERMINATED }; /** * - * RemoteIOAudio is responsible for playing audio through the speakers and + * RemoteIOAudio is responsible for playing audio through the speakers and * recording audio through the microphone. It sends/receives this information * to/from its AudioCallbackHandler delegate. * @@ -25,30 +21,29 @@ enum State { * */ @interface RemoteIOAudio : NSObject { - - AudioUnit rioAudioUnit; - - BOOL isStreaming; - - id delegate; - - NSMutableSet * unusedBuffers; - - id starveLogger; - id conditionLogger; - id playbackBufferSizeLogger; - id recordingQueueSizeLogger; + AudioUnit rioAudioUnit; + + BOOL isStreaming; + + id delegate; + + NSMutableSet *unusedBuffers; + + id starveLogger; + id conditionLogger; + id playbackBufferSizeLogger; + id recordingQueueSizeLogger; } -@property (nonatomic,readonly) enum State state; -@property (strong) CyclicalBuffer* recordingQueue; -@property (strong) CyclicalBuffer* playbackQueue; -@property (assign) AudioUnit rioAudioUnit; +@property (nonatomic, readonly) enum State state; +@property (strong) CyclicalBuffer *recordingQueue; +@property (strong) CyclicalBuffer *playbackQueue; +@property (assign) AudioUnit rioAudioUnit; -+(RemoteIOAudio*) remoteIOInterfaceStartedWithDelegate:(id)delegateIn untilCancelled:(TOCCancelToken*)untilCancelledToken; --(void) populatePlaybackQueueWithData:(NSData*)data; --(NSUInteger)getSampleRateInHertz; --(BOOL) toggleMute; ++ (RemoteIOAudio *)remoteIOInterfaceStartedWithDelegate:(id)delegateIn + untilCancelled:(TOCCancelToken *)untilCancelledToken; +- (void)populatePlaybackQueueWithData:(NSData *)data; +- (NSUInteger)getSampleRateInHertz; +- (BOOL)toggleMute; @end - diff --git a/Signal/src/audio/incall_audio/RemoteIOAudio.m b/Signal/src/audio/incall_audio/RemoteIOAudio.m index dcff09c2e..63c56be89 100644 --- a/Signal/src/audio/incall_audio/RemoteIOAudio.m +++ b/Signal/src/audio/incall_audio/RemoteIOAudio.m @@ -1,6 +1,6 @@ #import "AppAudioManager.h" -#import "Environment.h" #import "Constraints.h" +#import "Environment.h" #import "RemoteIOAudio.h" #import "ThreadManager.h" #import "Util.h" @@ -12,8 +12,8 @@ #define BUFFER_SIZE 8000 -#define FLAG_MUTED 1 -#define FLAG_UNMUTED 0 +#define FLAG_MUTED 1 +#define FLAG_UNMUTED 0 @implementation RemoteIOAudio @@ -21,32 +21,37 @@ static bool doesActiveInstanceExist; -+(RemoteIOAudio*) remoteIOInterfaceStartedWithDelegate:(id)delegateIn untilCancelled:(TOCCancelToken*)untilCancelledToken { - - checkOperationDescribe(!doesActiveInstanceExist, @"Only one RemoteIOInterfance instance can exist at a time. Adding more will break previous instances."); ++ (RemoteIOAudio *)remoteIOInterfaceStartedWithDelegate:(id)delegateIn + untilCancelled:(TOCCancelToken *)untilCancelledToken { + checkOperationDescribe( + !doesActiveInstanceExist, + @"Only one RemoteIOInterfance instance can exist at a time. Adding more will break previous instances."); doesActiveInstanceExist = true; - - RemoteIOAudio* newRemoteIoInterface = [RemoteIOAudio new]; - newRemoteIoInterface->starveLogger = [Environment.logging getOccurrenceLoggerForSender:newRemoteIoInterface withKey:@"starve"]; + + RemoteIOAudio *newRemoteIoInterface = [RemoteIOAudio new]; + newRemoteIoInterface->starveLogger = + [Environment.logging getOccurrenceLoggerForSender:newRemoteIoInterface withKey:@"starve"]; newRemoteIoInterface->conditionLogger = [Environment.logging getConditionLoggerForSender:newRemoteIoInterface]; - newRemoteIoInterface->recordingQueue = [CyclicalBuffer new]; - newRemoteIoInterface->playbackQueue = [CyclicalBuffer new]; - newRemoteIoInterface->unusedBuffers = [NSMutableSet set]; - newRemoteIoInterface->state = NOT_STARTED; - newRemoteIoInterface->playbackBufferSizeLogger = [Environment.logging getValueLoggerForValue:@"|playback queue|" from:newRemoteIoInterface]; - newRemoteIoInterface->recordingQueueSizeLogger = [Environment.logging getValueLoggerForValue:@"|recording queue|" from:newRemoteIoInterface]; - + newRemoteIoInterface->recordingQueue = [CyclicalBuffer new]; + newRemoteIoInterface->playbackQueue = [CyclicalBuffer new]; + newRemoteIoInterface->unusedBuffers = [NSMutableSet set]; + newRemoteIoInterface->state = NOT_STARTED; + newRemoteIoInterface->playbackBufferSizeLogger = + [Environment.logging getValueLoggerForValue:@"|playback queue|" from:newRemoteIoInterface]; + newRemoteIoInterface->recordingQueueSizeLogger = + [Environment.logging getValueLoggerForValue:@"|recording queue|" from:newRemoteIoInterface]; + while (newRemoteIoInterface->unusedBuffers.count < INITIAL_NUMBER_OF_BUFFERS) { [newRemoteIoInterface addUnusedBuffer]; } [newRemoteIoInterface setupAudio]; - + [newRemoteIoInterface startWithDelegate:delegateIn untilCancelled:untilCancelledToken]; - + return newRemoteIoInterface; } --(void)setupAudio { +- (void)setupAudio { [AppAudioManager.sharedInstance requestRecordingPrivilege]; rioAudioUnit = [self makeAudioUnit]; [self setAudioEnabled]; @@ -56,15 +61,15 @@ static bool doesActiveInstanceExist; [self checkDone:AudioUnitInitialize(rioAudioUnit)]; [[AppAudioManager sharedInstance] updateAudioRouter]; } --(AudioUnit)makeAudioUnit { +- (AudioUnit)makeAudioUnit { AudioComponentDescription audioUnitDescription = [self makeAudioComponentDescription]; - AudioComponent component = AudioComponentFindNext(NULL, &audioUnitDescription); - + AudioComponent component = AudioComponentFindNext(NULL, &audioUnitDescription); + AudioUnit unit; [self checkDone:AudioComponentInstanceNew(component, &unit)]; return unit; } --(AudioComponentDescription) makeAudioComponentDescription { +- (AudioComponentDescription)makeAudioComponentDescription { AudioComponentDescription d; d.componentType = kAudioUnitType_Output; d.componentSubType = kAudioUnitSubType_VoiceProcessingIO; @@ -73,7 +78,7 @@ static bool doesActiveInstanceExist; d.componentFlagsMask = 0; return d; } --(void)setAudioEnabled { +- (void)setAudioEnabled { const UInt32 enable = 1; [self checkDone:AudioUnitSetProperty(rioAudioUnit, kAudioOutputUnitProperty_EnableIO, @@ -88,7 +93,7 @@ static bool doesActiveInstanceExist; &enable, sizeof(enable))]; } --(void)setAudioStreamFormat { +- (void)setAudioStreamFormat { const AudioStreamBasicDescription streamDesc = [self makeAudioStreamBasicDescription]; [self checkDone:AudioUnitSetProperty(rioAudioUnit, kAudioUnitProperty_StreamFormat, @@ -103,7 +108,7 @@ static bool doesActiveInstanceExist; &streamDesc, sizeof(streamDesc))]; } --(AudioStreamBasicDescription) makeAudioStreamBasicDescription { +- (AudioStreamBasicDescription)makeAudioStreamBasicDescription { const UInt32 framesPerPacket = 1; AudioStreamBasicDescription d; d.mSampleRate = SAMPLE_RATE; @@ -112,14 +117,12 @@ static bool doesActiveInstanceExist; d.mChannelsPerFrame = 1; d.mBitsPerChannel = 16; d.mBytesPerPacket = SAMPLE_SIZE_IN_BYTES; - d.mBytesPerFrame = framesPerPacket*SAMPLE_SIZE_IN_BYTES; + d.mBytesPerFrame = framesPerPacket * SAMPLE_SIZE_IN_BYTES; d.mReserved = 0; - d.mFormatFlags = kAudioFormatFlagIsSignedInteger - | kAudioFormatFlagsNativeEndian - | kAudioFormatFlagIsPacked; + d.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked; return d; } --(void)setAudioCallbacks { +- (void)setAudioCallbacks { const AURenderCallbackStruct recordingCallbackStruct = {recordingCallback, (__bridge void *)(self)}; [self checkDone:AudioUnitSetProperty(rioAudioUnit, kAudioOutputUnitProperty_SetInputCallback, @@ -127,7 +130,7 @@ static bool doesActiveInstanceExist; INPUT_BUS, &recordingCallbackStruct, sizeof(recordingCallbackStruct))]; - + const AURenderCallbackStruct playbackCallbackStruct = {playbackCallback, (__bridge void *)(self)}; [self checkDone:AudioUnitSetProperty(rioAudioUnit, kAudioUnitProperty_SetRenderCallback, @@ -136,7 +139,7 @@ static bool doesActiveInstanceExist; &playbackCallbackStruct, sizeof(playbackCallbackStruct))]; } --(void)unsetAudioShouldAllocateBuffer { +- (void)unsetAudioShouldAllocateBuffer { const UInt32 shouldAllocateBuffer = 0; [self checkDone:AudioUnitSetProperty(rioAudioUnit, kAudioUnitProperty_ShouldAllocateBuffer, @@ -146,41 +149,43 @@ static bool doesActiveInstanceExist; sizeof(shouldAllocateBuffer))]; } --(RemoteIOBufferListWrapper*) addUnusedBuffer { - RemoteIOBufferListWrapper* buf = [RemoteIOBufferListWrapper remoteIOBufferListWithMonoBufferSize:BUFFER_SIZE]; +- (RemoteIOBufferListWrapper *)addUnusedBuffer { + RemoteIOBufferListWrapper *buf = [RemoteIOBufferListWrapper remoteIOBufferListWithMonoBufferSize:BUFFER_SIZE]; [unusedBuffers addObject:buf]; return buf; } --(RemoteIOBufferListWrapper*) tryTakeUnusedBuffer { - RemoteIOBufferListWrapper* buffer = (RemoteIOBufferListWrapper*)[unusedBuffers anyObject]; - if (buffer == nil) return nil; +- (RemoteIOBufferListWrapper *)tryTakeUnusedBuffer { + RemoteIOBufferListWrapper *buffer = (RemoteIOBufferListWrapper *)[unusedBuffers anyObject]; + if (buffer == nil) + return nil; [unusedBuffers removeObject:buffer]; return buffer; } --(void) returnUsedBuffer:(RemoteIOBufferListWrapper*)buffer { - require(buffer != nil); - if (state == TERMINATED) return; // in case a buffer was in use as termination occurred +- (void)returnUsedBuffer:(RemoteIOBufferListWrapper *)buffer { + ows_require(buffer != nil); + if (state == TERMINATED) + return; // in case a buffer was in use as termination occurred [unusedBuffers addObject:buffer]; } --(void) startWithDelegate:(id)delegateIn untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(delegateIn != nil); - @synchronized(self){ +- (void)startWithDelegate:(id)delegateIn untilCancelled:(TOCCancelToken *)untilCancelledToken { + ows_require(delegateIn != nil); + @synchronized(self) { requireState(state == NOT_STARTED); - + delegate = delegateIn; [self checkDone:AudioOutputUnitStart(rioAudioUnit)]; state = STARTED; } [untilCancelledToken whenCancelledDo:^{ - @synchronized(self) { - state = TERMINATED; - doesActiveInstanceExist = false; - [self checkDone:AudioOutputUnitStop(rioAudioUnit)]; - [AppAudioManager.sharedInstance releaseRecordingPrivilege]; - [unusedBuffers removeAllObjects]; - } + @synchronized(self) { + state = TERMINATED; + doesActiveInstanceExist = false; + [self checkDone:AudioOutputUnitStop(rioAudioUnit)]; + [AppAudioManager.sharedInstance releaseRecordingPrivilege]; + [unusedBuffers removeAllObjects]; + } }]; } @@ -190,13 +195,10 @@ static OSStatus recordingCallback(void *inRefCon, UInt32 inBusNumber, UInt32 inNumberSamples, AudioBufferList *ioData) { - - @autoreleasepool { - - RemoteIOAudio *instance = (__bridge RemoteIOAudio*)inRefCon; - - RemoteIOBufferListWrapper* buffer; + RemoteIOAudio *instance = (__bridge RemoteIOAudio *)inRefCon; + + RemoteIOBufferListWrapper *buffer; @synchronized(instance) { buffer = [instance tryTakeUnusedBuffer]; } @@ -212,33 +214,34 @@ static OSStatus recordingCallback(void *inRefCon, inNumberSamples, &bufferList)]; buffer.sampleCount = inNumberSamples; - + [instance performSelector:@selector(onRecordedDataIntoBuffer:) onThread:[ThreadManager lowLatencyThread] withObject:buffer waitUntilDone:NO]; - } return noErr; } --(void) onRecordedDataIntoBuffer:(RemoteIOBufferListWrapper*)buffer { - @synchronized(self){ - if (state == TERMINATED) return; - NSData* recordedAudioVolatile = [NSData dataWithBytesNoCopy:[buffer audioBufferList]->mBuffers[0].mData - length:[buffer sampleCount]*SAMPLE_SIZE_IN_BYTES +- (void)onRecordedDataIntoBuffer:(RemoteIOBufferListWrapper *)buffer { + @synchronized(self) { + if (state == TERMINATED) + return; + NSData *recordedAudioVolatile = [NSData dataWithBytesNoCopy:[buffer audioBufferList]->mBuffers[0].mData + length:[buffer sampleCount] * SAMPLE_SIZE_IN_BYTES freeWhenDone:NO]; [recordingQueue enqueueData:recordedAudioVolatile]; [self returnUsedBuffer:buffer]; } - + [recordingQueueSizeLogger logValue:[recordingQueue enqueuedLength]]; [delegate handleNewDataRecorded:recordingQueue]; } --(void)populatePlaybackQueueWithData:(NSData*)data { - require(data != nil); - if (data.length == 0) return; - @synchronized(self){ +- (void)populatePlaybackQueueWithData:(NSData *)data { + ows_require(data != nil); + if (data.length == 0) + return; + @synchronized(self) { [playbackQueue enqueueData:data]; } } @@ -248,55 +251,60 @@ static OSStatus playbackCallback(void *inRefCon, UInt32 inBusNumber, UInt32 inNumberSamples, AudioBufferList *ioData) { - RemoteIOAudio* instance = (__bridge RemoteIOAudio*)inRefCon; + RemoteIOAudio *instance = (__bridge RemoteIOAudio *)inRefCon; NSUInteger requestedByteCount = inNumberSamples * SAMPLE_SIZE_IN_BYTES; NSUInteger availableByteCount; @synchronized(instance) { availableByteCount = [[instance playbackQueue] enqueuedLength]; - + if (availableByteCount < requestedByteCount) { NSUInteger starveAmount = requestedByteCount - availableByteCount; [instance->starveLogger markOccurrence:@(starveAmount)]; } else { - NSData* audioToCopyVolatile = [[instance playbackQueue] dequeuePotentialyVolatileDataWithLength:requestedByteCount]; + NSData *audioToCopyVolatile = + [[instance playbackQueue] dequeuePotentialyVolatileDataWithLength:requestedByteCount]; memcpy(ioData->mBuffers[0].mData, [audioToCopyVolatile bytes], audioToCopyVolatile.length); } } - - [Operation asyncRun:^{[instance onRequestedPlaybackDataAmount:requestedByteCount - andHadAvailableAmount:availableByteCount];} + + [Operation asyncRun:^{ + [instance onRequestedPlaybackDataAmount:requestedByteCount andHadAvailableAmount:availableByteCount]; + } onThread:[ThreadManager lowLatencyThread]]; - + if (availableByteCount < requestedByteCount) { return 1; // arbitrary error code } - + return noErr; } --(void) onRequestedPlaybackDataAmount:(NSUInteger)requestedByteCount andHadAvailableAmount:(NSUInteger)availableByteCount { +- (void)onRequestedPlaybackDataAmount:(NSUInteger)requestedByteCount + andHadAvailableAmount:(NSUInteger)availableByteCount { @synchronized(self) { - if (state == TERMINATED) return; + if (state == TERMINATED) + return; } - NSUInteger consumedByteCount = availableByteCount >= requestedByteCount ? requestedByteCount : 0; + NSUInteger consumedByteCount = availableByteCount >= requestedByteCount ? requestedByteCount : 0; NSUInteger remainingByteCount = availableByteCount - consumedByteCount; [playbackBufferSizeLogger logValue:remainingByteCount]; [delegate handlePlaybackOccurredWithBytesRequested:requestedByteCount andBytesRemaining:remainingByteCount]; } --(void) dealloc{ +- (void)dealloc { if (state != TERMINATED) { doesActiveInstanceExist = false; } } --(NSUInteger)getSampleRateInHertz { +- (NSUInteger)getSampleRateInHertz { return SAMPLE_RATE; } --(void)checkDone:(OSStatus)resultCode { - if (resultCode == kAudioSessionNoError) return; - - NSString* failure; +- (void)checkDone:(OSStatus)resultCode { + if (resultCode == kAudioSessionNoError) + return; + + NSString *failure; if (resultCode == kAudioServicesUnsupportedPropertyError) { failure = @"unsupportedPropertyError"; } else if (resultCode == kAudioServicesBadPropertySizeError) { @@ -307,38 +315,38 @@ static OSStatus playbackCallback(void *inRefCon, failure = @"systemSoundUnspecifiedError"; } else if (resultCode == kAudioServicesSystemSoundClientTimedOutError) { failure = @"systemSoundClientTimedOutError"; - } else if (resultCode == errSecParam){ + } else if (resultCode == errSecParam) { failure = @"oneOrMoreNonValidParameter"; - }else { + } else { failure = [@(resultCode) description]; } [conditionLogger logError:[NSString stringWithFormat:@"StatusCheck failed: %@", failure]]; } --(bool) isAudioMuted { - UInt32 currentMuteFlag; - UInt32 propertyByteSize; - [self checkDone:AudioUnitGetProperty(rioAudioUnit, - kAUVoiceIOProperty_MuteOutput, +- (bool)isAudioMuted { + UInt32 currentMuteFlag; + UInt32 propertyByteSize; + [self checkDone:AudioUnitGetProperty(rioAudioUnit, + kAUVoiceIOProperty_MuteOutput, kAudioUnitScope_Global, OUTPUT_BUS, ¤tMuteFlag, - &propertyByteSize)]; - return (FLAG_MUTED == currentMuteFlag); + &propertyByteSize)]; + return (FLAG_MUTED == currentMuteFlag); } --(BOOL) toggleMute { - BOOL shouldBeMuted = !self.isAudioMuted; - UInt32 newValue = shouldBeMuted ? FLAG_MUTED : FLAG_UNMUTED; - - [self checkDone:AudioUnitSetProperty(rioAudioUnit, - kAUVoiceIOProperty_MuteOutput, +- (BOOL)toggleMute { + BOOL shouldBeMuted = !self.isAudioMuted; + UInt32 newValue = shouldBeMuted ? FLAG_MUTED : FLAG_UNMUTED; + + [self checkDone:AudioUnitSetProperty(rioAudioUnit, + kAUVoiceIOProperty_MuteOutput, kAudioUnitScope_Global, OUTPUT_BUS, &newValue, - sizeof(newValue))]; - - return shouldBeMuted; + sizeof(newValue))]; + + return shouldBeMuted; } diff --git a/Signal/src/audio/incall_audio/RemoteIOBufferListWrapper.h b/Signal/src/audio/incall_audio/RemoteIOBufferListWrapper.h index d9401b600..f6c4b77c5 100644 --- a/Signal/src/audio/incall_audio/RemoteIOBufferListWrapper.h +++ b/Signal/src/audio/incall_audio/RemoteIOBufferListWrapper.h @@ -1,6 +1,6 @@ -#import -#import #import +#import +#import /** * @@ -10,9 +10,9 @@ @interface RemoteIOBufferListWrapper : NSObject @property (nonatomic, assign) NSUInteger sampleCount; -@property (nonatomic, readonly) AudioBufferList* audioBufferList; +@property (nonatomic, readonly) AudioBufferList *audioBufferList; -+(RemoteIOBufferListWrapper*) remoteIOBufferListWithMonoBufferSize:(NSUInteger)bufferSize; ++ (RemoteIOBufferListWrapper *)remoteIOBufferListWithMonoBufferSize:(NSUInteger)bufferSize; @end diff --git a/Signal/src/audio/incall_audio/RemoteIOBufferListWrapper.m b/Signal/src/audio/incall_audio/RemoteIOBufferListWrapper.m index d32527f43..359d5c547 100644 --- a/Signal/src/audio/incall_audio/RemoteIOBufferListWrapper.m +++ b/Signal/src/audio/incall_audio/RemoteIOBufferListWrapper.m @@ -4,18 +4,18 @@ @synthesize sampleCount, audioBufferList; -+(RemoteIOBufferListWrapper*) remoteIOBufferListWithMonoBufferSize:(NSUInteger)bufferSize { - AudioBufferList* audioBufferList = malloc(sizeof(AudioBufferList)); - audioBufferList->mNumberBuffers = 1; ++ (RemoteIOBufferListWrapper *)remoteIOBufferListWithMonoBufferSize:(NSUInteger)bufferSize { + AudioBufferList *audioBufferList = malloc(sizeof(AudioBufferList)); + audioBufferList->mNumberBuffers = 1; audioBufferList->mBuffers[0].mNumberChannels = 1; - audioBufferList->mBuffers[0].mDataByteSize = (UInt32)bufferSize; - audioBufferList->mBuffers[0].mData = malloc(bufferSize); - - RemoteIOBufferListWrapper* w = [RemoteIOBufferListWrapper new]; - w->audioBufferList = audioBufferList; + audioBufferList->mBuffers[0].mDataByteSize = (UInt32)bufferSize; + audioBufferList->mBuffers[0].mData = malloc(bufferSize); + + RemoteIOBufferListWrapper *w = [RemoteIOBufferListWrapper new]; + w->audioBufferList = audioBufferList; return w; } --(void) dealloc { +- (void)dealloc { free(audioBufferList->mBuffers[0].mData); } diff --git a/Signal/src/audio/incall_audio/SpeexCodec.h b/Signal/src/audio/incall_audio/SpeexCodec.h index a2e81ed9f..7476b812a 100644 --- a/Signal/src/audio/incall_audio/SpeexCodec.h +++ b/Signal/src/audio/incall_audio/SpeexCodec.h @@ -9,29 +9,28 @@ * **/ @interface SpeexCodec : NSObject { - - void* decodingState; + void *decodingState; SpeexBits decodingBits; spx_int16_t decodingFrameSize; - spx_int16_t* decodingBuffer; - - void* encodingState; + spx_int16_t *decodingBuffer; + + void *encodingState; SpeexBits encodingBits; spx_int16_t encodingFrameSize; NSUInteger encodingBufferSizeInBytes; - + BOOL terminated; - + id logging; NSUInteger cachedEncodedLength; } -+(SpeexCodec*) speexCodec; -+(NSUInteger)frameSizeInSamples; --(NSUInteger)encodedFrameSizeInBytes; --(NSUInteger)decodedFrameSizeInBytes; ++ (SpeexCodec *)speexCodec; ++ (NSUInteger)frameSizeInSamples; +- (NSUInteger)encodedFrameSizeInBytes; +- (NSUInteger)decodedFrameSizeInBytes; --(NSData*)decode:(NSData*)encodedData; --(NSData*)encode:(NSData*)rawData; +- (NSData *)decode:(NSData *)encodedData; +- (NSData *)encode:(NSData *)rawData; @end diff --git a/Signal/src/audio/incall_audio/SpeexCodec.m b/Signal/src/audio/incall_audio/SpeexCodec.m index 2991d35bc..e07120954 100644 --- a/Signal/src/audio/incall_audio/SpeexCodec.m +++ b/Signal/src/audio/incall_audio/SpeexCodec.m @@ -1,5 +1,5 @@ -#import "Environment.h" #import "Constraints.h" +#import "Environment.h" #import "SpeexCodec.h" @implementation SpeexCodec @@ -13,62 +13,64 @@ #define QUALITY_PARAMETER 3 #define COMPLEXITY_PARAMETER 1 -+(SpeexCodec*) speexCodec { - SpeexCodec* c = [SpeexCodec new]; - c->logging = [Environment.logging getConditionLoggerForSender:self]; ++ (SpeexCodec *)speexCodec { + SpeexCodec *c = [SpeexCodec new]; + c->logging = [Environment.logging getConditionLoggerForSender:self]; [c openSpeex]; return c; } --(void) dealloc { +- (void)dealloc { [self closeSpeex]; } -+(NSUInteger)frameSizeInSamples { ++ (NSUInteger)frameSizeInSamples { return FRAME_SIZE_IN_SAMPLES; } --(NSUInteger)encodedFrameSizeInBytes { +- (NSUInteger)encodedFrameSizeInBytes { requireState(cachedEncodedLength != 0); return cachedEncodedLength; } --(NSUInteger)decodedFrameSizeInBytes { - return FRAME_SIZE_IN_SAMPLES*DECODED_SAMPLE_SIZE_IN_BYTES; +- (NSUInteger)decodedFrameSizeInBytes { + return FRAME_SIZE_IN_SAMPLES * DECODED_SAMPLE_SIZE_IN_BYTES; } --(void) determineDecodedLength { - NSData* encoded = [self encode:[NSMutableData dataWithLength:[self decodedFrameSizeInBytes]]]; +- (void)determineDecodedLength { + NSData *encoded = [self encode:[NSMutableData dataWithLength:[self decodedFrameSizeInBytes]]]; cachedEncodedLength = encoded.length; } --(NSData*)encode:(NSData*)rawData { - require(rawData != nil); - require(rawData.length == FRAME_SIZE_IN_SAMPLES*DECODED_SAMPLE_SIZE_IN_BYTES); +- (NSData *)encode:(NSData *)rawData { + ows_require(rawData != nil); + ows_require(rawData.length == FRAME_SIZE_IN_SAMPLES * DECODED_SAMPLE_SIZE_IN_BYTES); speex_bits_reset(&encodingBits); - speex_encode_int(encodingState, (spx_int16_t*)[rawData bytes], &encodingBits); - - NSMutableData* outputBuffer = [NSMutableData dataWithLength:encodingBufferSizeInBytes]; - int outputSizeInBytes = speex_bits_write(&encodingBits, [outputBuffer mutableBytes], (int)encodingBufferSizeInBytes); + speex_encode_int(encodingState, (spx_int16_t *)[rawData bytes], &encodingBits); + + NSMutableData *outputBuffer = [NSMutableData dataWithLength:encodingBufferSizeInBytes]; + int outputSizeInBytes = + speex_bits_write(&encodingBits, [outputBuffer mutableBytes], (int)encodingBufferSizeInBytes); checkOperation(outputSizeInBytes > 0); [outputBuffer setLength:(NSUInteger)outputSizeInBytes]; - + return outputBuffer; } --(NSData*)decode:(NSData*)potentiallyMissingEncodedData { +- (NSData *)decode:(NSData *)potentiallyMissingEncodedData { NSUInteger encodedDataLength = potentiallyMissingEncodedData.length; if (potentiallyMissingEncodedData == nil) { encodedDataLength = [self decodedFrameSizeInBytes]; // size for infering audio data } - if(encodedDataLength == 0) return nil; - + if (encodedDataLength == 0) + return nil; + SpeexBits *dbits = [self getSpeexBitsFromData:potentiallyMissingEncodedData andDataLength:(int)encodedDataLength]; - + int decodedLength = [self decodeSpeexBits:dbits withLength:(int)encodedDataLength]; - - return [NSData dataWithBytes:decodingBuffer length:(NSUInteger)decodedLength*sizeof(spx_int16_t)]; + + return [NSData dataWithBytes:decodingBuffer length:(NSUInteger)decodedLength * sizeof(spx_int16_t)]; } --(NSUInteger) encodedDataLengthFromData:(NSData*)potentiallyMissingEncodedData{ +- (NSUInteger)encodedDataLengthFromData:(NSData *)potentiallyMissingEncodedData { if (potentiallyMissingEncodedData != nil) { return potentiallyMissingEncodedData.length; } @@ -76,10 +78,10 @@ } - (SpeexBits *)getSpeexBitsFromData:(NSData *)encodedData andDataLength:(int)encodedDataLength { - SpeexBits *dbits=NULL; - char* encodingStream; - if([encodedData bytes] != NULL){ - encodingStream = (char*)[encodedData bytes]; + SpeexBits *dbits = NULL; + char *encodingStream; + if ([encodedData bytes] != NULL) { + encodingStream = (char *)[encodedData bytes]; speex_bits_read_from(&decodingBits, encodingStream, encodedDataLength); dbits = &decodingBits; } @@ -87,28 +89,34 @@ } - (int)decodeSpeexBits:(SpeexBits *)dbits withLength:(int)encodedDataLength { - int decodingBufferIndex = 0; + int decodingBufferIndex = 0; int decodingBufferLength = (int)[self decodedFrameSizeInBytes]; - int count = 0; - while(0 == speex_decode_int(decodingState, dbits, decodingBuffer + decodingBufferIndex)){ + int count = 0; + while (0 == speex_decode_int(decodingState, dbits, decodingBuffer + decodingBufferIndex)) { count++; decodingBufferIndex += decodingFrameSize; - if(decodingBufferIndex + decodingFrameSize > decodingBufferLength){ - [logging logWarning:[NSString stringWithFormat:@"out of space in the decArr buffer, idx=%d, frameSize=%d, length=%d", decodingBufferIndex,decodingFrameSize,decodingBufferLength]]; + if (decodingBufferIndex + decodingFrameSize > decodingBufferLength) { + [logging + logWarning:[NSString + stringWithFormat:@"out of space in the decArr buffer, idx=%d, frameSize=%d, length=%d", + decodingBufferIndex, + decodingFrameSize, + decodingBufferLength]]; break; } - if(decodingBufferIndex + decodingFrameSize > decodingFrameSize * MAX_FRAMES){ - [logging logWarning:[NSString stringWithFormat:@"out of space in the dec_buffer buffer, idx=%d", decodingBufferIndex]]; + if (decodingBufferIndex + decodingFrameSize > decodingFrameSize * MAX_FRAMES) { + [logging logWarning:[NSString stringWithFormat:@"out of space in the dec_buffer buffer, idx=%d", + decodingBufferIndex]]; break; } - if(dbits == NULL){ + if (dbits == NULL) { break; } } return decodingBufferIndex; } --(void) openSpeex { +- (void)openSpeex { [self initiateEncoderAndDecoder]; [self applySpeexSettings]; [self initiateSpeexBuffers]; @@ -116,28 +124,27 @@ } - (void)initiateEncoderAndDecoder { - encodingState = speex_encoder_init(&speex_nb_mode); decodingState = speex_decoder_init(&speex_nb_mode); - + checkOperationDescribe(encodingState != NULL, @"speex encoder init failed"); checkOperationDescribe(decodingState != NULL, @"speex decoder init failed"); } --(void)applySpeexSettings{ +- (void)applySpeexSettings { spx_int32_t tmp; - tmp=PERPETUAL_ENHANCER_PARAMETER; + tmp = PERPETUAL_ENHANCER_PARAMETER; speex_decoder_ctl(decodingState, SPEEX_SET_ENH, &tmp); - tmp=VARIABLE_BIT_RATE_PARAMETER; + tmp = VARIABLE_BIT_RATE_PARAMETER; speex_encoder_ctl(encodingState, SPEEX_SET_VBR, &tmp); - tmp=QUALITY_PARAMETER; + tmp = QUALITY_PARAMETER; speex_encoder_ctl(encodingState, SPEEX_SET_QUALITY, &tmp); - tmp=COMPLEXITY_PARAMETER; + tmp = COMPLEXITY_PARAMETER; speex_encoder_ctl(encodingState, SPEEX_SET_COMPLEXITY, &tmp); - + speex_encoder_ctl(encodingState, SPEEX_GET_FRAME_SIZE, &encodingFrameSize); speex_decoder_ctl(decodingState, SPEEX_GET_FRAME_SIZE, &decodingFrameSize); - + int sampleRate = (int)SAMPLE_RATE; speex_encoder_ctl(encodingState, SPEEX_SET_SAMPLING_RATE, &sampleRate); speex_decoder_ctl(decodingState, SPEEX_SET_SAMPLING_RATE, &sampleRate); @@ -146,22 +153,22 @@ - (void)initiateSpeexBuffers { speex_bits_init(&encodingBits); speex_bits_init(&decodingBits); - + encodingBufferSizeInBytes = (NSUInteger)encodingFrameSize * MAX_FRAMES; - decodingBuffer = (spx_int16_t *) malloc( sizeof( spx_int16_t ) * (NSUInteger)decodingFrameSize*MAX_FRAMES ); - + decodingBuffer = (spx_int16_t *)malloc(sizeof(spx_int16_t) * (NSUInteger)decodingFrameSize * MAX_FRAMES); + checkOperationDescribe(decodingBuffer != NULL, @"buffer allocation failed"); } --(void) closeSpeex { +- (void)closeSpeex { terminated = true; - - speex_encoder_destroy( encodingState ); - speex_decoder_destroy( decodingState ); - - speex_bits_destroy( &encodingBits ); - speex_bits_destroy( &decodingBits ); - + + speex_encoder_destroy(encodingState); + speex_decoder_destroy(decodingState); + + speex_bits_destroy(&encodingBits); + speex_bits_destroy(&decodingBits); + free(decodingBuffer); } diff --git a/Signal/src/audio/incall_audio/processing/AudioProcessor.h b/Signal/src/audio/incall_audio/processing/AudioProcessor.h index dda0d9160..ed3cb86df 100644 --- a/Signal/src/audio/incall_audio/processing/AudioProcessor.h +++ b/Signal/src/audio/incall_audio/processing/AudioProcessor.h @@ -11,7 +11,7 @@ /** * - * AudioProcessor is responsible for transforming audio as it travels between + * AudioProcessor is responsible for transforming audio as it travels between * the network and the hardware. * * Processing involves: @@ -24,19 +24,24 @@ **/ @interface AudioProcessor : NSObject { -@private StretchFactorController* stretchFactorController; -@private AudioStretcher* audioStretcher; -@private AudioPacker* audioPacker; -@private JitterQueue* jitterQueue; -@private bool haveReceivedDataYet; + @private + StretchFactorController *stretchFactorController; + @private + AudioStretcher *audioStretcher; + @private + AudioPacker *audioPacker; + @private + JitterQueue *jitterQueue; + @private + bool haveReceivedDataYet; } -@property (nonatomic,readonly) SpeexCodec* codec; +@property (nonatomic, readonly) SpeexCodec *codec; -+(AudioProcessor*) audioProcessor; ++ (AudioProcessor *)audioProcessor; --(void) receivedPacket:(EncodedAudioPacket*)packet; --(NSArray*) encodeAudioPacketsFromBuffer:(CyclicalBuffer*) buffer; --(NSData*) tryDecodeOrInferFrame; +- (void)receivedPacket:(EncodedAudioPacket *)packet; +- (NSArray *)encodeAudioPacketsFromBuffer:(CyclicalBuffer *)buffer; +- (NSData *)tryDecodeOrInferFrame; @end diff --git a/Signal/src/audio/incall_audio/processing/AudioProcessor.m b/Signal/src/audio/incall_audio/processing/AudioProcessor.m index 96dd8b17d..ffefb9b5a 100644 --- a/Signal/src/audio/incall_audio/processing/AudioProcessor.m +++ b/Signal/src/audio/incall_audio/processing/AudioProcessor.m @@ -4,56 +4,60 @@ @synthesize codec; -+(AudioProcessor*) audioProcessor { - JitterQueue* jitterQueue = [JitterQueue jitterQueue]; - - AudioProcessor* newAudioProcessorInstance = [AudioProcessor new]; - newAudioProcessorInstance->codec = [SpeexCodec speexCodec]; - newAudioProcessorInstance->stretchFactorController = [StretchFactorController stretchFactorControllerForJitterQueue:jitterQueue]; ++ (AudioProcessor *)audioProcessor { + JitterQueue *jitterQueue = [JitterQueue jitterQueue]; + + AudioProcessor *newAudioProcessorInstance = [AudioProcessor new]; + newAudioProcessorInstance->codec = [SpeexCodec speexCodec]; + newAudioProcessorInstance->stretchFactorController = + [StretchFactorController stretchFactorControllerForJitterQueue:jitterQueue]; newAudioProcessorInstance->audioStretcher = [AudioStretcher audioStretcher]; - newAudioProcessorInstance->jitterQueue = jitterQueue; - newAudioProcessorInstance->audioPacker = [AudioPacker audioPacker]; + newAudioProcessorInstance->jitterQueue = jitterQueue; + newAudioProcessorInstance->audioPacker = [AudioPacker audioPacker]; return newAudioProcessorInstance; } --(void)receivedPacket:(EncodedAudioPacket *)packet { +- (void)receivedPacket:(EncodedAudioPacket *)packet { [jitterQueue tryEnqueue:packet]; } --(NSArray*) encodeAudioPacketsFromBuffer:(CyclicalBuffer*) buffer { - require(buffer != nil); - - NSMutableArray* encodedFrames = [NSMutableArray array]; - NSUInteger decodedFrameSize = [codec decodedFrameSizeInBytes]; - while([buffer enqueuedLength] >= decodedFrameSize){ - NSData* rawFrame = [buffer dequeueDataWithLength:decodedFrameSize]; +- (NSArray *)encodeAudioPacketsFromBuffer:(CyclicalBuffer *)buffer { + ows_require(buffer != nil); + + NSMutableArray *encodedFrames = [NSMutableArray array]; + NSUInteger decodedFrameSize = [codec decodedFrameSizeInBytes]; + while ([buffer enqueuedLength] >= decodedFrameSize) { + NSData *rawFrame = [buffer dequeueDataWithLength:decodedFrameSize]; requireState(rawFrame != nil); - NSData* encodedFrameData = [codec encode:rawFrame]; + NSData *encodedFrameData = [codec encode:rawFrame]; [encodedFrames addObject:[EncodedAudioFrame encodedAudioFrameWithData:encodedFrameData]]; } - - NSMutableArray* encodedPackets = [NSMutableArray array]; - for (EncodedAudioFrame* frame in encodedFrames) { + + NSMutableArray *encodedPackets = [NSMutableArray array]; + for (EncodedAudioFrame *frame in encodedFrames) { [audioPacker packFrame:frame]; - EncodedAudioPacket* packet = [audioPacker tryGetFinishedAudioPacket]; - if (packet != nil) [encodedPackets addObject:packet]; + EncodedAudioPacket *packet = [audioPacker tryGetFinishedAudioPacket]; + if (packet != nil) + [encodedPackets addObject:packet]; } - + return encodedPackets; } --(EncodedAudioFrame*) pullFrame { - EncodedAudioFrame* frame = [audioPacker tryGetReceivedFrame]; - if (frame != nil) return frame; - - EncodedAudioPacket* potentiallyMissingPacket = [jitterQueue tryDequeue]; +- (EncodedAudioFrame *)pullFrame { + EncodedAudioFrame *frame = [audioPacker tryGetReceivedFrame]; + if (frame != nil) + return frame; + + EncodedAudioPacket *potentiallyMissingPacket = [jitterQueue tryDequeue]; [audioPacker unpackPotentiallyMissingAudioPacket:potentiallyMissingPacket]; return [audioPacker tryGetReceivedFrame]; } --(NSData*) tryDecodeOrInferFrame { - EncodedAudioFrame* frame = [self pullFrame]; +- (NSData *)tryDecodeOrInferFrame { + EncodedAudioFrame *frame = [self pullFrame]; haveReceivedDataYet |= !frame.isMissingAudioData; - if (!haveReceivedDataYet) return nil; - - NSData* raw = [codec decode:frame.tryGetAudioData]; + if (!haveReceivedDataYet) + return nil; + + NSData *raw = [codec decode:frame.tryGetAudioData]; double stretch = [stretchFactorController getAndUpdateDesiredStretchFactor]; return [audioStretcher stretchAudioData:raw stretchFactor:stretch]; } diff --git a/Signal/src/audio/incall_audio/processing/AudioStretcher.h b/Signal/src/audio/incall_audio/processing/AudioStretcher.h index bf24a84d5..572f04828 100644 --- a/Signal/src/audio/incall_audio/processing/AudioStretcher.h +++ b/Signal/src/audio/incall_audio/processing/AudioStretcher.h @@ -12,10 +12,11 @@ **/ @interface AudioStretcher : NSObject { -@private struct time_scale_state_s timeScaleState; + @private + struct time_scale_state_s timeScaleState; } -+(AudioStretcher*) audioStretcher; --(NSData*) stretchAudioData:(NSData*)audioData stretchFactor:(double)stretchFactor; ++ (AudioStretcher *)audioStretcher; +- (NSData *)stretchAudioData:(NSData *)audioData stretchFactor:(double)stretchFactor; @end diff --git a/Signal/src/audio/incall_audio/processing/AudioStretcher.m b/Signal/src/audio/incall_audio/processing/AudioStretcher.m index f2a78d7ea..959541aa7 100644 --- a/Signal/src/audio/incall_audio/processing/AudioStretcher.m +++ b/Signal/src/audio/incall_audio/processing/AudioStretcher.m @@ -1,52 +1,55 @@ #import "AudioStretcher.h" #import "Constraints.h" -#import "time_scale.h" #import "Util.h" +#import "time_scale.h" #define MIN_STRETCH_FACTOR 0.1 #define MAX_STRETCH_FACTOR 10 @implementation AudioStretcher -+(AudioStretcher*) audioStretcher { - AudioStretcher* s = [AudioStretcher new]; ++ (AudioStretcher *)audioStretcher { + AudioStretcher *s = [AudioStretcher new]; checkOperation(time_scale_init(&s->timeScaleState, SAMPLE_RATE, 1.0) != NULL); return s; } --(NSData*) stretchAudioData:(NSData*)audioData stretchFactor:(double)stretchFactor { - require(stretchFactor > MIN_STRETCH_FACTOR); - require(stretchFactor < MAX_STRETCH_FACTOR); - - if (audioData == nil) return nil; - +- (NSData *)stretchAudioData:(NSData *)audioData stretchFactor:(double)stretchFactor { + ows_require(stretchFactor > MIN_STRETCH_FACTOR); + ows_require(stretchFactor < MAX_STRETCH_FACTOR); + + if (audioData == nil) + return nil; + checkOperationDescribe(time_scale_rate(&timeScaleState, (float)stretchFactor) == 0, @"Changing time scaling"); - - int inputSampleCount = (unsigned int)audioData.length/sizeof(int16_t); + + int inputSampleCount = (unsigned int)audioData.length / sizeof(int16_t); int maxOutputSampleCount = [self getSafeMaxOutputSampleCountFromInputSampleCount:inputSampleCount]; - - int16_t* input = (int16_t*)[audioData bytes]; - - NSMutableData* d = [NSMutableData dataWithLength:(NSUInteger)maxOutputSampleCount*sizeof(int16_t)]; + + int16_t *input = (int16_t *)[audioData bytes]; + + NSMutableData *d = [NSMutableData dataWithLength:(NSUInteger)maxOutputSampleCount * sizeof(int16_t)]; int outputSampleCount = time_scale(&timeScaleState, [d mutableBytes], input, inputSampleCount); checkOperationDescribe(outputSampleCount >= 0 && outputSampleCount <= maxOutputSampleCount, @"Scaling audio"); - - return [d take:(NSUInteger)outputSampleCount*sizeof(int16_t)]; + + return [d take:(NSUInteger)outputSampleCount * sizeof(int16_t)]; } --(int) getSafeMaxOutputSampleCountFromInputSampleCount:(int)inputSampleCount{ - // WARNING: In some cases SpanDSP (time_scale.h v 1.20) underestimates how much buffer it will need, so we must pad the result to be safe. +- (int)getSafeMaxOutputSampleCountFromInputSampleCount:(int)inputSampleCount { + // WARNING: In some cases SpanDSP (time_scale.h v 1.20) underestimates how much buffer it will need, so we must pad + // the result to be safe. // Issues has been notified upstream and once it is patched the padding can be removed - int unsafe_maxOutputSampleCount = time_scale_max_output_len(&timeScaleState, inputSampleCount); - const int BUFFER_OVERFLOW_PROTECTION_PAD = 2048; + int unsafe_maxOutputSampleCount = time_scale_max_output_len(&timeScaleState, inputSampleCount); + const int BUFFER_OVERFLOW_PROTECTION_PAD = 2048; const int BUFFER_OVERFLOW_PROPORTIONAL_MULTIPLIER = 2; - int expandedMaxCountToAvoidBufferOverflows = BUFFER_OVERFLOW_PROTECTION_PAD + (unsafe_maxOutputSampleCount * BUFFER_OVERFLOW_PROPORTIONAL_MULTIPLIER); - + int expandedMaxCountToAvoidBufferOverflows = + BUFFER_OVERFLOW_PROTECTION_PAD + (unsafe_maxOutputSampleCount * BUFFER_OVERFLOW_PROPORTIONAL_MULTIPLIER); + checkOperation(expandedMaxCountToAvoidBufferOverflows >= 0); return expandedMaxCountToAvoidBufferOverflows; } --(void) dealloc { +- (void)dealloc { checkOperation(time_scale_release(&timeScaleState) == 0); } diff --git a/Signal/src/audio/incall_audio/processing/DesiredBufferDepthController.h b/Signal/src/audio/incall_audio/processing/DesiredBufferDepthController.h index 38a917809..a014c2077 100644 --- a/Signal/src/audio/incall_audio/processing/DesiredBufferDepthController.h +++ b/Signal/src/audio/incall_audio/processing/DesiredBufferDepthController.h @@ -3,12 +3,13 @@ #import "DropoutTracker.h" #import "Environment.h" #import "JitterQueue.h" -#import "Terminable.h" #import "SpeexCodec.h" +#import "Terminable.h" /** * - * DesiredBufferDepthController is used to determine how much audio should be kept in reserve, in case of network jitter. + * DesiredBufferDepthController is used to determine how much audio should be kept in reserve, in case of network + *jitter. * * An instance must be registered to receive notifications from the network jitter queue in order to function correctly. * When packets arrive at a consistent rate without dropping, the desired buffer depth tends to decrease. @@ -16,13 +17,16 @@ * **/ -@interface DesiredBufferDepthController : NSObject { -@private DropoutTracker* dropoutTracker; -@private DecayingSampleEstimator* decayingDesiredBufferDepth; -@private id desiredDelayLogger; +@interface DesiredBufferDepthController : NSObject { + @private + DropoutTracker *dropoutTracker; + @private + DecayingSampleEstimator *decayingDesiredBufferDepth; + @private + id desiredDelayLogger; } -+(DesiredBufferDepthController*) desiredBufferDepthControllerForJitterQueue:(JitterQueue*)jitterQueue; --(double) getAndUpdateDesiredBufferDepth; ++ (DesiredBufferDepthController *)desiredBufferDepthControllerForJitterQueue:(JitterQueue *)jitterQueue; +- (double)getAndUpdateDesiredBufferDepth; @end diff --git a/Signal/src/audio/incall_audio/processing/DesiredBufferDepthController.m b/Signal/src/audio/incall_audio/processing/DesiredBufferDepthController.m index 8920c9f63..9d16f00e3 100644 --- a/Signal/src/audio/incall_audio/processing/DesiredBufferDepthController.m +++ b/Signal/src/audio/incall_audio/processing/DesiredBufferDepthController.m @@ -1,7 +1,7 @@ +#import "AudioPacker.h" #import "DesiredBufferDepthController.h" #import "PreferencesUtil.h" #import "Util.h" -#import "AudioPacker.h" #define MAX_DESIRED_FRAME_DELAY 12 #define MIN_DESIRED_FRAME_DELAY 0.5 @@ -11,29 +11,29 @@ @implementation DesiredBufferDepthController -+(DesiredBufferDepthController*) desiredBufferDepthControllerForJitterQueue:(JitterQueue*)jitterQueue { - require(jitterQueue != nil); - - NSTimeInterval audioDurationPerPacket = (NSTimeInterval)(AUDIO_FRAMES_PER_PACKET*[SpeexCodec frameSizeInSamples]) - / SAMPLE_RATE; - double initialDesiredBufferDepth = Environment.preferences.getCachedOrDefaultDesiredBufferDepth; - - DropoutTracker* dropoutTracker = [DropoutTracker dropoutTrackerWithAudioDurationPerPacket:audioDurationPerPacket]; ++ (DesiredBufferDepthController *)desiredBufferDepthControllerForJitterQueue:(JitterQueue *)jitterQueue { + ows_require(jitterQueue != nil); - DecayingSampleEstimator* decayingDesiredBufferDepth = + NSTimeInterval audioDurationPerPacket = + (NSTimeInterval)(AUDIO_FRAMES_PER_PACKET * [SpeexCodec frameSizeInSamples]) / SAMPLE_RATE; + double initialDesiredBufferDepth = Environment.preferences.getCachedOrDefaultDesiredBufferDepth; + + DropoutTracker *dropoutTracker = [DropoutTracker dropoutTrackerWithAudioDurationPerPacket:audioDurationPerPacket]; + + DecayingSampleEstimator *decayingDesiredBufferDepth = [DecayingSampleEstimator decayingSampleEstimatorWithInitialEstimate:initialDesiredBufferDepth andDecayPerUnitSample:DESIRED_BUFFER_DEPTH_DECAY_RATE]; - - DesiredBufferDepthController* result = [DesiredBufferDepthController new]; - result->dropoutTracker = dropoutTracker; - result->decayingDesiredBufferDepth = decayingDesiredBufferDepth; + + DesiredBufferDepthController *result = [DesiredBufferDepthController new]; + result->dropoutTracker = dropoutTracker; + result->decayingDesiredBufferDepth = decayingDesiredBufferDepth; result->desiredDelayLogger = [Environment.logging getValueLoggerForValue:@"desired buffer depth" from:self]; - + [jitterQueue registerWatcher:result]; return result; } --(double) getAndUpdateDesiredBufferDepth { +- (double)getAndUpdateDesiredBufferDepth { double r = decayingDesiredBufferDepth.currentEstimate; [decayingDesiredBufferDepth updateWithNextSample:[dropoutTracker getDepthForThreshold:DROPOUT_THRESHOLD]]; [decayingDesiredBufferDepth forceEstimateTo:[NumberUtil clamp:decayingDesiredBufferDepth.currentEstimate @@ -43,21 +43,23 @@ return r; } --(void) notifyArrival:(uint16_t)sequenceNumber { +- (void)notifyArrival:(uint16_t)sequenceNumber { [dropoutTracker observeSequenceNumber:sequenceNumber]; } --(void) notifyBadArrival:(uint16_t)sequenceNumber ofType:(enum JitterBadArrivalType)arrivalType { +- (void)notifyBadArrival:(uint16_t)sequenceNumber ofType:(enum JitterBadArrivalType)arrivalType { } --(void) notifyBadDequeueOfType:(enum JitterBadDequeueType)type { +- (void)notifyBadDequeueOfType:(enum JitterBadDequeueType)type { } --(void) notifyDequeue:(uint16_t)sequenceNumber withRemainingEnqueuedItemCount:(NSUInteger)remainingCount { +- (void)notifyDequeue:(uint16_t)sequenceNumber withRemainingEnqueuedItemCount:(NSUInteger)remainingCount { } --(void) notifyResyncFrom:(uint16_t)oldReadHeadSequenceNumber to:(uint16_t)newReadHeadSequenceNumber { +- (void)notifyResyncFrom:(uint16_t)oldReadHeadSequenceNumber to:(uint16_t)newReadHeadSequenceNumber { } --(void) notifyDiscardOverflow:(uint16_t)sequenceNumber resyncingFrom:(uint16_t)oldReadHeadSequenceNumber to:(uint16_t)newReadHeadSequenceNumber { +- (void)notifyDiscardOverflow:(uint16_t)sequenceNumber + resyncingFrom:(uint16_t)oldReadHeadSequenceNumber + to:(uint16_t)newReadHeadSequenceNumber { } --(void) terminate { +- (void)terminate { [Environment.preferences setCachedDesiredBufferDepth:decayingDesiredBufferDepth.currentEstimate]; } diff --git a/Signal/src/audio/incall_audio/processing/DropoutTracker.h b/Signal/src/audio/incall_audio/processing/DropoutTracker.h index c1481fc04..3c82213a7 100644 --- a/Signal/src/audio/incall_audio/processing/DropoutTracker.h +++ b/Signal/src/audio/incall_audio/processing/DropoutTracker.h @@ -28,23 +28,30 @@ * * > @author Stuart O. Anderson * - * Link to android implementation with comments: + * Link to android implementation with comments: * https://github.com/WhisperSystems/RedPhone/blob/2a6e8cec64cc457d2eb02351d0f3adf769db7a84/src/org/thoughtcrime/redphone/audio/DropoutTracker.java * */ @interface DropoutTracker : NSObject { -@private Queue* priorLatenesses; -@private NSMutableArray* lateBins; -@private SequenceCounter* sequenceCounter; -@private NSTimeInterval audioDurationPerPacket; -@private bool startTimeInitialized; -@private NSTimeInterval startTime; -@private NSTimeInterval drift; + @private + Queue *priorLatenesses; + @private + NSMutableArray *lateBins; + @private + SequenceCounter *sequenceCounter; + @private + NSTimeInterval audioDurationPerPacket; + @private + bool startTimeInitialized; + @private + NSTimeInterval startTime; + @private + NSTimeInterval drift; } -+(DropoutTracker*) dropoutTrackerWithAudioDurationPerPacket:(NSTimeInterval)audioDurationPerPacket; --(void) observeSequenceNumber:(uint16_t)seqNum; --(double)getDepthForThreshold:(NSUInteger)maxEvents; ++ (DropoutTracker *)dropoutTrackerWithAudioDurationPerPacket:(NSTimeInterval)audioDurationPerPacket; +- (void)observeSequenceNumber:(uint16_t)seqNum; +- (double)getDepthForThreshold:(NSUInteger)maxEvents; @end diff --git a/Signal/src/audio/incall_audio/processing/DropoutTracker.m b/Signal/src/audio/incall_audio/processing/DropoutTracker.m index 87b010e0e..ed0968aa1 100644 --- a/Signal/src/audio/incall_audio/processing/DropoutTracker.m +++ b/Signal/src/audio/incall_audio/processing/DropoutTracker.m @@ -9,14 +9,13 @@ @implementation DropoutTracker -+(DropoutTracker*) dropoutTrackerWithAudioDurationPerPacket:(NSTimeInterval)audioDurationPerPacket { - - DropoutTracker* d = [DropoutTracker new]; - ++ (DropoutTracker *)dropoutTrackerWithAudioDurationPerPacket:(NSTimeInterval)audioDurationPerPacket { + DropoutTracker *d = [DropoutTracker new]; + d->audioDurationPerPacket = audioDurationPerPacket; - d->sequenceCounter = [SequenceCounter sequenceCounter]; - d->priorLatenesses = [Queue new]; - d->lateBins = [NSMutableArray array]; + d->sequenceCounter = [SequenceCounter sequenceCounter]; + d->priorLatenesses = [Queue new]; + d->lateBins = [NSMutableArray array]; for (NSUInteger i = 0; i < PRIOR_LATENESS_LENGTH; i++) { [d->priorLatenesses enqueue:@0.0]; @@ -24,65 +23,64 @@ for (NSUInteger i = 0; i < LATE_BINS_LENGTH; i++) { [d->lateBins addObject:[EventWindow eventWindowWithWindowDuration:LATE_BIN_WINDOW_IN_SECONDS]]; } - + return d; } --(NSTimeInterval) detectPeak { - NSTimeInterval possiblePeakLatency = [[priorLatenesses peekAt:PRIOR_LATENESS_LENGTH/2] doubleValue]; - - for (NSUInteger i=0; i < PRIOR_LATENESS_LENGTH-1; i++) { +- (NSTimeInterval)detectPeak { + NSTimeInterval possiblePeakLatency = [[priorLatenesses peekAt:PRIOR_LATENESS_LENGTH / 2] doubleValue]; + + for (NSUInteger i = 0; i < PRIOR_LATENESS_LENGTH - 1; i++) { if ([[priorLatenesses peekAt:i] doubleValue] > possiblePeakLatency) { return -1; } } - + return possiblePeakLatency; } --(void) observeSequenceNumber:(uint16_t)sequenceNumber { +- (void)observeSequenceNumber:(uint16_t)sequenceNumber { int64_t expandedSequenceNumber = [sequenceCounter convertNext:sequenceNumber]; - if( !startTimeInitialized ) { - startTime = [TimeUtil time]; + if (!startTimeInitialized) { + startTime = [TimeUtil time]; startTimeInitialized = true; } - + NSTimeInterval expectedTime = startTime + drift + expandedSequenceNumber * audioDurationPerPacket; - NSTimeInterval now = [TimeUtil time]; - NSTimeInterval secLate = now-expectedTime; + NSTimeInterval now = [TimeUtil time]; + NSTimeInterval secLate = now - expectedTime; [priorLatenesses enqueue:@(secLate)]; [priorLatenesses dequeue]; - + // update zero time // if a packet arrives early, immediately update the timebase // if it arrives late, conservatively update the timebase drift += MIN(secLate, secLate / 50); - //Was the last packet a local peak? + // Was the last packet a local peak? NSTimeInterval peakLatency = [self detectPeak]; if (peakLatency > 0) { - NSUInteger lateBin = (NSUInteger)[NumberUtil clamp:peakLatency/(audioDurationPerPacket / binsPerPacket) + NSUInteger lateBin = (NSUInteger)[NumberUtil clamp:peakLatency / (audioDurationPerPacket / binsPerPacket) toMin:0 andMax:LATE_BINS_LENGTH - 1]; - + if (peakLatency <= maxActionableLatency) { [lateBins[lateBin] addEventAtTime:now]; } } - } /// How many packets would we have needed to buffer to stay below the desired dropout event count --(double)getDepthForThreshold:(NSUInteger)maxEvents { +- (double)getDepthForThreshold:(NSUInteger)maxEvents { NSUInteger eventCount = 0; - NSTimeInterval now = [TimeUtil time]; + NSTimeInterval now = [TimeUtil time]; for (NSUInteger depth = LATE_BINS_LENGTH; depth > 0; depth--) { - eventCount += [lateBins[depth-1] countAfterRemovingEventsBeforeWindowEndingAt:now]; + eventCount += [lateBins[depth - 1] countAfterRemovingEventsBeforeWindowEndingAt:now]; if (eventCount > maxEvents) { - return (depth-1)/binsPerPacket; + return (depth - 1) / binsPerPacket; } } - return -1/binsPerPacket; + return -1 / binsPerPacket; } @end diff --git a/Signal/src/audio/incall_audio/processing/JitterQueue.h b/Signal/src/audio/incall_audio/processing/JitterQueue.h index 60968c2e7..3306a785c 100644 --- a/Signal/src/audio/incall_audio/processing/JitterQueue.h +++ b/Signal/src/audio/incall_audio/processing/JitterQueue.h @@ -1,38 +1,45 @@ #import -#import "PriorityQueue.h" -#import "EncodedAudioPacket.h" -#import "Logging.h" -#import "JitterQueueNotificationReceiver.h" #import "BufferDepthMeasure.h" +#import "EncodedAudioPacket.h" +#import "JitterQueueNotificationReceiver.h" +#import "Logging.h" +#import "PriorityQueue.h" /** * - * JitterQueue handles the details of organizing and consuming real-time data, which may fail to arrive on time or arrive out of order. + * JitterQueue handles the details of organizing and consuming real-time data, which may fail to arrive on time or + *arrive out of order. * **/ @interface JitterQueue : NSObject { -@private PriorityQueue* resultPriorityQueue; -@private uint16_t readHeadMin; -@private uint16_t readHeadSpan; -@private NSMutableSet* idsInJitterQueue; -@private NSMutableArray* watchers; -@private uint16_t largestLatestEnqueued; + @private + PriorityQueue *resultPriorityQueue; + @private + uint16_t readHeadMin; + @private + uint16_t readHeadSpan; + @private + NSMutableSet *idsInJitterQueue; + @private + NSMutableArray *watchers; + @private + uint16_t largestLatestEnqueued; } -+(JitterQueue*) jitterQueue; ++ (JitterQueue *)jitterQueue; --(void) registerWatcher:(id)watcher; +- (void)registerWatcher:(id)watcher; // Provides a framed audio packet to be placed in sequence. // Returns true if the packet was successfully enqueued. // Returns false if the packet has arrived too late, far too early, or is a duplicate. --(bool) tryEnqueue:(EncodedAudioPacket*)packet; +- (bool)tryEnqueue:(EncodedAudioPacket *)packet; // Returns the next framed audio packet in sequence, or nil if the next packet has not arrived in time. --(EncodedAudioPacket*) tryDequeue; +- (EncodedAudioPacket *)tryDequeue; // The number of framed audio packets (contiguous or not) in the queue. --(NSUInteger) count; +- (NSUInteger)count; @end diff --git a/Signal/src/audio/incall_audio/processing/JitterQueue.m b/Signal/src/audio/incall_audio/processing/JitterQueue.m index b7dc26371..ccf11cb33 100644 --- a/Signal/src/audio/incall_audio/processing/JitterQueue.m +++ b/Signal/src/audio/incall_audio/processing/JitterQueue.m @@ -1,6 +1,6 @@ +#import "Environment.h" #import "JitterQueue.h" #import "Util.h" -#import "Environment.h" #define TRANSITIVE_SAFETY_RANGE 0x4000 #define READ_HEAD_MAX_QUEUE_AHEAD 0x1000 @@ -9,31 +9,32 @@ @implementation JitterQueue -+(JitterQueue*) jitterQueue { - JitterQueue* q = [JitterQueue new]; - q->readHeadSpan = READ_HEAD_BAD_SPAN_THRESHOLD+1; - q->watchers = [NSMutableArray array]; ++ (JitterQueue *)jitterQueue { + JitterQueue *q = [JitterQueue new]; + q->readHeadSpan = READ_HEAD_BAD_SPAN_THRESHOLD + 1; + q->watchers = [NSMutableArray array]; [q registerWatcher:Environment.logging.jitterQueueNotificationReceiver]; return q; } --(void) registerWatcher:(id)watcher { - if (watcher == nil) return; +- (void)registerWatcher:(id)watcher { + if (watcher == nil) + return; [watchers addObject:watcher]; } --(NSUInteger) count { +- (NSUInteger)count { return resultPriorityQueue.count; } --(bool) tryEnqueue:(EncodedAudioPacket*)audioPacket { - require(audioPacket != nil); - +- (bool)tryEnqueue:(EncodedAudioPacket *)audioPacket { + ows_require(audioPacket != nil); + uint16_t sequenceNumber = [audioPacket sequenceNumber]; if (![self tryFitIntoSequence:sequenceNumber]) { return false; } - + [idsInJitterQueue addObject:@(sequenceNumber)]; [resultPriorityQueue enqueue:audioPacket]; if ([NumberUtil congruentDifferenceMod2ToThe16From:largestLatestEnqueued to:sequenceNumber] > 0) { @@ -48,9 +49,10 @@ return true; } --(bool) tryFitIntoSequence:(uint16_t)sequenceNumber { - int16_t sequenceNumberRelativeToReadHead = [NumberUtil congruentDifferenceMod2ToThe16From:readHeadMin to:sequenceNumber]; - +- (bool)tryFitIntoSequence:(uint16_t)sequenceNumber { + int16_t sequenceNumberRelativeToReadHead = + [NumberUtil congruentDifferenceMod2ToThe16From:readHeadMin to:sequenceNumber]; + enum JitterBadArrivalType badArrivalType; if ([self tryForceSyncIfNecessary:sequenceNumber]) { return true; @@ -63,75 +65,73 @@ } else { return true; } - + for (id watcher in watchers) { [watcher notifyBadArrival:sequenceNumber ofType:badArrivalType]; } - + return false; } --(bool) tryForceSyncIfNecessary:(uint16_t)sequenceNumber { - if (readHeadSpan <= READ_HEAD_BAD_SPAN_THRESHOLD) return false; - +- (bool)tryForceSyncIfNecessary:(uint16_t)sequenceNumber { + if (readHeadSpan <= READ_HEAD_BAD_SPAN_THRESHOLD) + return false; + if (resultPriorityQueue != nil) { // (only log resyncs, not the initial sync) for (id watcher in watchers) { [watcher notifyResyncFrom:readHeadMin to:sequenceNumber]; } } - - readHeadMin = sequenceNumber; + + readHeadMin = sequenceNumber; largestLatestEnqueued = sequenceNumber; - readHeadSpan = 1; - idsInJitterQueue = [NSMutableSet set]; - resultPriorityQueue = [JitterQueue makeCyclingPacketPriorityQueue]; - + readHeadSpan = 1; + idsInJitterQueue = [NSMutableSet set]; + resultPriorityQueue = [JitterQueue makeCyclingPacketPriorityQueue]; + return true; } -+(PriorityQueue*) makeCyclingPacketPriorityQueue { - return [PriorityQueue priorityQueueAscendingWithComparator:^NSComparisonResult(EncodedAudioPacket* obj1, EncodedAudioPacket* obj2) { - int16_t d = [NumberUtil congruentDifferenceMod2ToThe16From:[obj2 sequenceNumber] - to:[obj1 sequenceNumber]]; - requireState(abs(d) <= TRANSITIVE_SAFETY_RANGE); - return [NumberUtil signOfInt32:d]; - }]; ++ (PriorityQueue *)makeCyclingPacketPriorityQueue { + return [PriorityQueue + priorityQueueAscendingWithComparator:^NSComparisonResult(EncodedAudioPacket *obj1, EncodedAudioPacket *obj2) { + int16_t d = [NumberUtil congruentDifferenceMod2ToThe16From:[obj2 sequenceNumber] to:[obj1 sequenceNumber]]; + requireState(abs(d) <= TRANSITIVE_SAFETY_RANGE); + return [NumberUtil signOfInt32:d]; + }]; } --(void) discardExcess { - if (resultPriorityQueue.count <= MAXIMUM_JITTER_QUEUE_SIZE_BEFORE_DISCARDING) return; - - EncodedAudioPacket* discarded = [resultPriorityQueue dequeue]; +- (void)discardExcess { + if (resultPriorityQueue.count <= MAXIMUM_JITTER_QUEUE_SIZE_BEFORE_DISCARDING) + return; + + EncodedAudioPacket *discarded = [resultPriorityQueue dequeue]; uint16_t discardedSequenceNumber = [discarded sequenceNumber]; [idsInJitterQueue removeObject:@(discardedSequenceNumber)]; - - uint16_t oldReadHeadMax = readHeadMin+readHeadSpan-1; - readHeadMin = [resultPriorityQueue.peek sequenceNumber]; - readHeadSpan = 1; - + + uint16_t oldReadHeadMax = readHeadMin + readHeadSpan - 1; + readHeadMin = [resultPriorityQueue.peek sequenceNumber]; + readHeadSpan = 1; + for (id e in watchers) { - [e notifyDiscardOverflow:discardedSequenceNumber - resyncingFrom:oldReadHeadMax - to:readHeadMin]; + [e notifyDiscardOverflow:discardedSequenceNumber resyncingFrom:oldReadHeadMax to:readHeadMin]; } } --(EncodedAudioPacket*) tryDequeue { - if ([self checkReactIfOutOfSyncForDequeue] - || [self checkReactIfEmptyForDequeue] - || [self checkReactIfNoDataUnderReadHeadForDequeue]) { - +- (EncodedAudioPacket *)tryDequeue { + if ([self checkReactIfOutOfSyncForDequeue] || [self checkReactIfEmptyForDequeue] || + [self checkReactIfNoDataUnderReadHeadForDequeue]) { return nil; } - - EncodedAudioPacket* result = [resultPriorityQueue dequeue]; - readHeadMin = [result sequenceNumber]+1; - readHeadSpan = 1; + + EncodedAudioPacket *result = [resultPriorityQueue dequeue]; + readHeadMin = [result sequenceNumber] + 1; + readHeadSpan = 1; [idsInJitterQueue removeObject:@([result sequenceNumber])]; - + for (id e in watchers) { [e notifyDequeue:[result sequenceNumber] withRemainingEnqueuedItemCount:idsInJitterQueue.count]; } return result; } --(bool) checkReactIfOutOfSyncForDequeue { +- (bool)checkReactIfOutOfSyncForDequeue { bool isOutOfSync = readHeadSpan > READ_HEAD_BAD_SPAN_THRESHOLD; if (isOutOfSync) { for (id watcher in watchers) { @@ -140,7 +140,7 @@ } return isOutOfSync; } --(bool) checkReactIfEmptyForDequeue { +- (bool)checkReactIfEmptyForDequeue { bool isEmpty = resultPriorityQueue.count == 0; if (isEmpty) { readHeadSpan += 1; @@ -150,11 +150,10 @@ } return isEmpty; } --(bool) checkReactIfNoDataUnderReadHeadForDequeue { - EncodedAudioPacket* result = resultPriorityQueue.peek; - int16_t d = [NumberUtil congruentDifferenceMod2ToThe16From:readHeadMin - to:[result sequenceNumber]]; - bool notUnderHead = d < 0 || d >= readHeadSpan; +- (bool)checkReactIfNoDataUnderReadHeadForDequeue { + EncodedAudioPacket *result = resultPriorityQueue.peek; + int16_t d = [NumberUtil congruentDifferenceMod2ToThe16From:readHeadMin to:[result sequenceNumber]]; + bool notUnderHead = d < 0 || d >= readHeadSpan; if (notUnderHead) { readHeadSpan += 1; for (id watcher in watchers) { @@ -164,8 +163,9 @@ return notUnderHead; } --(int16_t) currentBufferDepth { - if (readHeadSpan > READ_HEAD_BAD_SPAN_THRESHOLD) return 0; +- (int16_t)currentBufferDepth { + if (readHeadSpan > READ_HEAD_BAD_SPAN_THRESHOLD) + return 0; return [NumberUtil congruentDifferenceMod2ToThe16From:readHeadMin + readHeadSpan - 1 to:largestLatestEnqueued]; } diff --git a/Signal/src/audio/incall_audio/processing/StretchFactorController.h b/Signal/src/audio/incall_audio/processing/StretchFactorController.h index 514d548f4..6d0257875 100644 --- a/Signal/src/audio/incall_audio/processing/StretchFactorController.h +++ b/Signal/src/audio/incall_audio/processing/StretchFactorController.h @@ -12,15 +12,20 @@ **/ @interface StretchFactorController : NSObject { -@private int currentStretchMode; -@private id bufferDepthMeasure; -@private DesiredBufferDepthController* desiredBufferDepthController; -@private DecayingSampleEstimator* decayingBufferDepthMeasure; -@private id stretchModeChangeLogger; + @private + int currentStretchMode; + @private + id bufferDepthMeasure; + @private + DesiredBufferDepthController *desiredBufferDepthController; + @private + DecayingSampleEstimator *decayingBufferDepthMeasure; + @private + id stretchModeChangeLogger; } -+(StretchFactorController*) stretchFactorControllerForJitterQueue:(JitterQueue*)jitterQueue; ++ (StretchFactorController *)stretchFactorControllerForJitterQueue:(JitterQueue *)jitterQueue; --(double) getAndUpdateDesiredStretchFactor; +- (double)getAndUpdateDesiredStretchFactor; @end diff --git a/Signal/src/audio/incall_audio/processing/StretchFactorController.m b/Signal/src/audio/incall_audio/processing/StretchFactorController.m index 867a1f656..f4bbab39f 100644 --- a/Signal/src/audio/incall_audio/processing/StretchFactorController.m +++ b/Signal/src/audio/incall_audio/processing/StretchFactorController.m @@ -5,7 +5,7 @@ #define STRETCH_MODE_NORMAL 1 #define STRETCH_MODE_SHRINK 2 #define STRETCH_MODE_SUPER_SHRINK 3 -static double STRETCH_MODE_FACTORS[] = {1/0.95, 1, 1/1.05, 0.5}; +static double STRETCH_MODE_FACTORS[] = {1 / 0.95, 1, 1 / 1.05, 0.5}; #define SUPER_SHRINK_THRESHOLD 10 #define SHRINK_THRESHOLD 3.0 @@ -15,55 +15,61 @@ static double STRETCH_MODE_FACTORS[] = {1/0.95, 1, 1/1.05, 0.5}; @implementation StretchFactorController -+(StretchFactorController*) stretchFactorControllerForJitterQueue:(JitterQueue*)jitterQueue { - - require(jitterQueue != nil); - - DesiredBufferDepthController* desiredBufferDepthController = ++ (StretchFactorController *)stretchFactorControllerForJitterQueue:(JitterQueue *)jitterQueue { + ows_require(jitterQueue != nil); + + DesiredBufferDepthController *desiredBufferDepthController = [DesiredBufferDepthController desiredBufferDepthControllerForJitterQueue:jitterQueue]; - StretchFactorController* p = [StretchFactorController new]; + StretchFactorController *p = [StretchFactorController new]; p->desiredBufferDepthController = desiredBufferDepthController; - p->currentStretchMode = STRETCH_MODE_NORMAL; - p->bufferDepthMeasure = jitterQueue; - p->decayingBufferDepthMeasure = [DecayingSampleEstimator decayingSampleEstimatorWithInitialEstimate:0 andDecayPerUnitSample:BUFFER_DEPTH_DECAYING_FACTOR]; + p->currentStretchMode = STRETCH_MODE_NORMAL; + p->bufferDepthMeasure = jitterQueue; + p->decayingBufferDepthMeasure = + [DecayingSampleEstimator decayingSampleEstimatorWithInitialEstimate:0 + andDecayPerUnitSample:BUFFER_DEPTH_DECAYING_FACTOR]; p->stretchModeChangeLogger = [Environment.logging getValueLoggerForValue:@"stretch factor" from:self]; return p; } --(int) reconsiderStretchMode { +- (int)reconsiderStretchMode { int16_t currentBufferDepth = bufferDepthMeasure.currentBufferDepth; [decayingBufferDepthMeasure updateWithNextSample:currentBufferDepth]; double desiredBufferDepth = desiredBufferDepthController.getAndUpdateDesiredBufferDepth; - - double currentBufferDepthDelta = currentBufferDepth - desiredBufferDepth; + + double currentBufferDepthDelta = currentBufferDepth - desiredBufferDepth; double decayingBufferDepthDelta = decayingBufferDepthMeasure.currentEstimate - desiredBufferDepth; - - bool shouldStartSuperShrink = currentBufferDepthDelta > SUPER_SHRINK_THRESHOLD; + + bool shouldStartSuperShrink = currentBufferDepthDelta > SUPER_SHRINK_THRESHOLD; bool shouldMaintainSuperShrink = currentBufferDepthDelta > 0 && currentStretchMode == STRETCH_MODE_SUPER_SHRINK; - bool shouldEndSuperShrinkAndResetEstimate = !shouldMaintainSuperShrink && currentStretchMode == STRETCH_MODE_SUPER_SHRINK; - - bool shouldStartShrink = decayingBufferDepthDelta > SHRINK_THRESHOLD; + bool shouldEndSuperShrinkAndResetEstimate = + !shouldMaintainSuperShrink && currentStretchMode == STRETCH_MODE_SUPER_SHRINK; + + bool shouldStartShrink = decayingBufferDepthDelta > SHRINK_THRESHOLD; bool shouldMaintainShrink = decayingBufferDepthDelta > 0 && currentStretchMode == STRETCH_MODE_SHRINK; - - bool shouldStartExpand = decayingBufferDepthDelta < EXPAND_THRESHOLD; + + bool shouldStartExpand = decayingBufferDepthDelta < EXPAND_THRESHOLD; bool shouldMaintainExpand = decayingBufferDepthDelta < 0 && currentStretchMode == STRETCH_MODE_EXPAND; - + if (shouldEndSuperShrinkAndResetEstimate) { [decayingBufferDepthMeasure forceEstimateTo:desiredBufferDepth]; return STRETCH_MODE_NORMAL; } - if (shouldStartSuperShrink) return STRETCH_MODE_SUPER_SHRINK; - if (shouldStartShrink) return STRETCH_MODE_SHRINK; - if (shouldStartExpand) return STRETCH_MODE_EXPAND; - if (shouldMaintainShrink || shouldMaintainExpand || shouldMaintainSuperShrink) return currentStretchMode; + if (shouldStartSuperShrink) + return STRETCH_MODE_SUPER_SHRINK; + if (shouldStartShrink) + return STRETCH_MODE_SHRINK; + if (shouldStartExpand) + return STRETCH_MODE_EXPAND; + if (shouldMaintainShrink || shouldMaintainExpand || shouldMaintainSuperShrink) + return currentStretchMode; return STRETCH_MODE_NORMAL; } --(double) getAndUpdateDesiredStretchFactor { - int prevMode = currentStretchMode; +- (double)getAndUpdateDesiredStretchFactor { + int prevMode = currentStretchMode; currentStretchMode = [self reconsiderStretchMode]; - double factor = STRETCH_MODE_FACTORS[currentStretchMode]; + double factor = STRETCH_MODE_FACTORS[currentStretchMode]; if (prevMode != currentStretchMode) { [stretchModeChangeLogger logValue:factor]; } diff --git a/Signal/src/audio/incall_audio/protocols/AudioCallbackHandler.h b/Signal/src/audio/incall_audio/protocols/AudioCallbackHandler.h index a7acf017b..908b1186d 100644 --- a/Signal/src/audio/incall_audio/protocols/AudioCallbackHandler.h +++ b/Signal/src/audio/incall_audio/protocols/AudioCallbackHandler.h @@ -7,6 +7,6 @@ * **/ @protocol AudioCallbackHandler --(void) handleNewDataRecorded:(CyclicalBuffer*) data; --(void) handlePlaybackOccurredWithBytesRequested:(NSUInteger)requested andBytesRemaining:(NSUInteger)bytesRemaining; +- (void)handleNewDataRecorded:(CyclicalBuffer *)data; +- (void)handlePlaybackOccurredWithBytesRequested:(NSUInteger)requested andBytesRemaining:(NSUInteger)bytesRemaining; @end diff --git a/Signal/src/audio/incall_audio/protocols/BufferDepthMeasure.h b/Signal/src/audio/incall_audio/protocols/BufferDepthMeasure.h index ea8a2b9c7..dd06d58ce 100644 --- a/Signal/src/audio/incall_audio/protocols/BufferDepthMeasure.h +++ b/Signal/src/audio/incall_audio/protocols/BufferDepthMeasure.h @@ -1,5 +1,5 @@ #import @protocol BufferDepthMeasure --(int16_t) currentBufferDepth; +- (int16_t)currentBufferDepth; @end diff --git a/Signal/src/audio/incall_audio/protocols/JitterQueueNotificationReceiver.h b/Signal/src/audio/incall_audio/protocols/JitterQueueNotificationReceiver.h index ca59c2270..70c66c425 100644 --- a/Signal/src/audio/incall_audio/protocols/JitterQueueNotificationReceiver.h +++ b/Signal/src/audio/incall_audio/protocols/JitterQueueNotificationReceiver.h @@ -2,19 +2,22 @@ enum JitterBadArrivalType { JitterBadArrivalType_Duplicate = 0, // for when two packets with the same sequence number arrive - JitterBadArrivalType_Stale = 1, // for when sequence number is behind read head - JitterBadArrivalType_TooSoon = 2 // for when sequence number is *way* ahead of read head + JitterBadArrivalType_Stale = 1, // for when sequence number is behind read head + JitterBadArrivalType_TooSoon = 2 // for when sequence number is *way* ahead of read head }; enum JitterBadDequeueType { JitterBadDequeueType_Desynced = 0, // for when so many lack-of-datas have accumulated that the read head can skip - JitterBadDequeueType_Empty = 1, // for when there's no data anywhere in the jitter queue - JitterBadDequeueType_NoDataUnderReadHead = 2 // for when there's data in the jitter queue, but it's ahead of the read head + JitterBadDequeueType_Empty = 1, // for when there's no data anywhere in the jitter queue + JitterBadDequeueType_NoDataUnderReadHead = + 2 // for when there's data in the jitter queue, but it's ahead of the read head }; @protocol JitterQueueNotificationReceiver --(void) notifyArrival:(uint16_t)sequenceNumber; --(void) notifyDequeue:(uint16_t)sequenceNumber withRemainingEnqueuedItemCount:(NSUInteger)remainingCount; --(void) notifyBadArrival:(uint16_t)sequenceNumber ofType:(enum JitterBadArrivalType)arrivalType; --(void) notifyBadDequeueOfType:(enum JitterBadDequeueType)type; --(void) notifyResyncFrom:(uint16_t)oldReadHeadSequenceNumber to:(uint16_t)newReadHeadSequenceNumber; --(void) notifyDiscardOverflow:(uint16_t)discardedSequenceNumber resyncingFrom:(uint16_t)oldReadHeadSequenceNumber to:(uint16_t)newReadHeadSequenceNumber; +- (void)notifyArrival:(uint16_t)sequenceNumber; +- (void)notifyDequeue:(uint16_t)sequenceNumber withRemainingEnqueuedItemCount:(NSUInteger)remainingCount; +- (void)notifyBadArrival:(uint16_t)sequenceNumber ofType:(enum JitterBadArrivalType)arrivalType; +- (void)notifyBadDequeueOfType:(enum JitterBadDequeueType)type; +- (void)notifyResyncFrom:(uint16_t)oldReadHeadSequenceNumber to:(uint16_t)newReadHeadSequenceNumber; +- (void)notifyDiscardOverflow:(uint16_t)discardedSequenceNumber + resyncingFrom:(uint16_t)oldReadHeadSequenceNumber + to:(uint16_t)newReadHeadSequenceNumber; @end diff --git a/Signal/src/audio/incall_audio/protocols/utilities/AnonymousAudioCallbackHandler.h b/Signal/src/audio/incall_audio/protocols/utilities/AnonymousAudioCallbackHandler.h index 2c38b3067..45c6f8279 100644 --- a/Signal/src/audio/incall_audio/protocols/utilities/AnonymousAudioCallbackHandler.h +++ b/Signal/src/audio/incall_audio/protocols/utilities/AnonymousAudioCallbackHandler.h @@ -7,12 +7,15 @@ * **/ -@interface AnonymousAudioCallbackHandler : NSObject +@interface AnonymousAudioCallbackHandler : NSObject -@property (readonly,nonatomic,copy) void (^handleNewDataRecordedBlock)(CyclicalBuffer* data); -@property (readonly,nonatomic,copy) void (^handlePlaybackOccurredWithBytesRequestedBlock)(NSUInteger requested, NSUInteger bytesRemaining); +@property (readonly, nonatomic, copy) void (^handleNewDataRecordedBlock)(CyclicalBuffer *data); +@property (readonly, nonatomic, copy) void (^handlePlaybackOccurredWithBytesRequestedBlock) + (NSUInteger requested, NSUInteger bytesRemaining); -+(AnonymousAudioCallbackHandler*) anonymousAudioInterfaceDelegateWithRecordingCallback:(void(^)(CyclicalBuffer* data))recordingCallback - andPlaybackOccurredCallback:(void(^)(NSUInteger requested, NSUInteger bytesRemaining))playbackCallback; ++ (AnonymousAudioCallbackHandler *) +anonymousAudioInterfaceDelegateWithRecordingCallback:(void (^)(CyclicalBuffer *data))recordingCallback + andPlaybackOccurredCallback: + (void (^)(NSUInteger requested, NSUInteger bytesRemaining))playbackCallback; @end diff --git a/Signal/src/audio/incall_audio/protocols/utilities/AnonymousAudioCallbackHandler.m b/Signal/src/audio/incall_audio/protocols/utilities/AnonymousAudioCallbackHandler.m index b75ecbc88..cd8f51843 100644 --- a/Signal/src/audio/incall_audio/protocols/utilities/AnonymousAudioCallbackHandler.m +++ b/Signal/src/audio/incall_audio/protocols/utilities/AnonymousAudioCallbackHandler.m @@ -2,18 +2,20 @@ @implementation AnonymousAudioCallbackHandler -+(AnonymousAudioCallbackHandler*) anonymousAudioInterfaceDelegateWithRecordingCallback:(void(^)(CyclicalBuffer* data))recordingCallback - andPlaybackOccurredCallback:(void(^)(NSUInteger requested, NSUInteger bytesRemaining))playbackCallback { - AnonymousAudioCallbackHandler* a = [AnonymousAudioCallbackHandler new]; - a->_handleNewDataRecordedBlock = recordingCallback; ++ (AnonymousAudioCallbackHandler *) +anonymousAudioInterfaceDelegateWithRecordingCallback:(void (^)(CyclicalBuffer *data))recordingCallback + andPlaybackOccurredCallback: + (void (^)(NSUInteger requested, NSUInteger bytesRemaining))playbackCallback { + AnonymousAudioCallbackHandler *a = [AnonymousAudioCallbackHandler new]; + a->_handleNewDataRecordedBlock = recordingCallback; a->_handlePlaybackOccurredWithBytesRequestedBlock = playbackCallback; return a; } --(void) handleNewDataRecorded:(CyclicalBuffer*)data { +- (void)handleNewDataRecorded:(CyclicalBuffer *)data { if (_handleNewDataRecordedBlock != nil) _handleNewDataRecordedBlock(data); } --(void) handlePlaybackOccurredWithBytesRequested:(NSUInteger)requested andBytesRemaining:(NSUInteger)bytesRemaining { +- (void)handlePlaybackOccurredWithBytesRequested:(NSUInteger)requested andBytesRemaining:(NSUInteger)bytesRemaining { if (_handlePlaybackOccurredWithBytesRequestedBlock != nil) _handlePlaybackOccurredWithBytesRequestedBlock(requested, bytesRemaining); } diff --git a/Signal/src/call/RecentCall.h b/Signal/src/call/RecentCall.h index ce5704839..797fe8d0e 100644 --- a/Signal/src/call/RecentCall.h +++ b/Signal/src/call/RecentCall.h @@ -1,8 +1,9 @@ -#import #import -#import "PhoneNumber.h" -#import "ContactsManager.h" +#import +#import #import "Contact.h" +#import "ContactsManager.h" +#import "PhoneNumber.h" /** * @@ -12,11 +13,6 @@ * */ -typedef enum { - RPRecentCallTypeIncoming = 1, - RPRecentCallTypeOutgoing, - RPRecentCallTypeMissed, -} RPRecentCallType; extern NSString *const CALL_TYPE_IMAGE_NAME_INCOMING; extern NSString *const CALL_TYPE_IMAGE_NAME_OUTGOING; @@ -34,5 +30,5 @@ extern NSString *const CALL_TYPE_IMAGE_NAME_OUTGOING; andNumber:(PhoneNumber *)number andCallType:(RPRecentCallType)type; --(void)updateRecentCallWithContactId:(ABRecordID) contactID; +- (void)updateRecentCallWithContactId:(ABRecordID)contactID; @end diff --git a/Signal/src/call/RecentCall.m b/Signal/src/call/RecentCall.m index 51e71fa53..7f89a1bf8 100644 --- a/Signal/src/call/RecentCall.m +++ b/Signal/src/call/RecentCall.m @@ -1,10 +1,10 @@ #import "RecentCall.h" -static NSString *const DEFAULTS_KEY_CONTACT_ID = @"DefaultsKeyContactID"; -static NSString *const DEFAULTS_KEY_PHONE_NUMBER = @"DefaultsKeyPhoneNumber"; -static NSString *const DEFAULTS_KEY_CALL_TYPE = @"DefaultsKeycallType"; -static NSString *const DEFAULTS_KEY_DATE = @"DefaultsKeyDate"; -static NSString *const DEFAULTS_KEY_IS_ARCHIVED = @"DefaultsKeyDateIsArchived"; +static NSString *const DEFAULTS_KEY_CONTACT_ID = @"DefaultsKeyContactID"; +static NSString *const DEFAULTS_KEY_PHONE_NUMBER = @"DefaultsKeyPhoneNumber"; +static NSString *const DEFAULTS_KEY_CALL_TYPE = @"DefaultsKeycallType"; +static NSString *const DEFAULTS_KEY_DATE = @"DefaultsKeyDate"; +static NSString *const DEFAULTS_KEY_IS_ARCHIVED = @"DefaultsKeyDateIsArchived"; static NSString *const DEFAULTS_KEY_USER_NOTIFIED = @"DefaultsKeyUserNotified"; NSString *const CALL_TYPE_IMAGE_NAME_INCOMING = @"incoming_call_icon"; @@ -17,16 +17,15 @@ NSString *const CALL_TYPE_IMAGE_NAME_OUTGOING = @"outgoing_call_icon"; + (RecentCall *)recentCallWithContactID:(ABRecordID)contactID andNumber:(PhoneNumber *)number andCallType:(RPRecentCallType)type { - - RecentCall *recentCall = [RecentCall new]; + RecentCall *recentCall = [RecentCall new]; recentCall->contactRecordID = contactID; - recentCall->callType = type; - recentCall->date = [NSDate date]; - recentCall->phoneNumber = number; - recentCall->userNotified = type == RPRecentCallTypeMissed ? false : true; + recentCall->callType = type; + recentCall->date = [NSDate date]; + recentCall->phoneNumber = number; + recentCall->userNotified = type == RPRecentCallTypeMissed ? false : true; return recentCall; } --(void)updateRecentCallWithContactId:(ABRecordID)contactID{ +- (void)updateRecentCallWithContactId:(ABRecordID)contactID { contactRecordID = contactID; } @@ -42,13 +41,13 @@ NSString *const CALL_TYPE_IMAGE_NAME_OUTGOING = @"outgoing_call_icon"; } - (id)initWithCoder:(NSCoder *)decoder { - if((self = [super init])) { - callType = (RPRecentCallType)[[decoder decodeObjectForKey:DEFAULTS_KEY_CALL_TYPE] intValue]; + if ((self = [super init])) { + callType = (RPRecentCallType)[[decoder decodeObjectForKey:DEFAULTS_KEY_CALL_TYPE] intValue]; contactRecordID = [[decoder decodeObjectForKey:DEFAULTS_KEY_CONTACT_ID] intValue]; - phoneNumber = [decoder decodeObjectForKey:DEFAULTS_KEY_PHONE_NUMBER]; - date = [decoder decodeObjectForKey:DEFAULTS_KEY_DATE]; - isArchived = [decoder decodeBoolForKey:DEFAULTS_KEY_IS_ARCHIVED]; - userNotified = [decoder decodeBoolForKey:DEFAULTS_KEY_USER_NOTIFIED]; + phoneNumber = [decoder decodeObjectForKey:DEFAULTS_KEY_PHONE_NUMBER]; + date = [decoder decodeObjectForKey:DEFAULTS_KEY_DATE]; + isArchived = [decoder decodeBoolForKey:DEFAULTS_KEY_IS_ARCHIVED]; + userNotified = [decoder decodeBoolForKey:DEFAULTS_KEY_USER_NOTIFIED]; } return self; } diff --git a/Signal/src/call/RecentCallManager.h b/Signal/src/call/RecentCallManager.h index 38e9ac305..04a33c519 100644 --- a/Signal/src/call/RecentCallManager.h +++ b/Signal/src/call/RecentCallManager.h @@ -1,6 +1,6 @@ #import -#import "RecentCall.h" #import "PhoneManager.h" +#import "RecentCall.h" /** * @@ -12,10 +12,9 @@ @interface RecentCallManager : NSObject -- (void)watchForCallsThrough:(PhoneManager*)phoneManager - untilCancelled:(TOCCancelToken*)untilCancelledToken; +- (void)watchForCallsThrough:(PhoneManager *)phoneManager untilCancelled:(TOCCancelToken *)untilCancelledToken; - (void)addRecentCall:(RecentCall *)recentCall; -- (void)addMissedCallDueToBusy:(ResponderSessionDescriptor*)incomingCallDescriptor; +- (void)addMissedCallDueToBusy:(ResponderSessionDescriptor *)incomingCallDescriptor; @end diff --git a/Signal/src/call/RecentCallManager.m b/Signal/src/call/RecentCallManager.m index cb2c3a653..240718af4 100644 --- a/Signal/src/call/RecentCallManager.m +++ b/Signal/src/call/RecentCallManager.m @@ -1,3 +1,5 @@ +#import +#import "NotificationsManager.h" #import "RecentCallManager.h" #import "TSCall.h" #import "TSMessagesManager.h" @@ -9,50 +11,50 @@ @implementation RecentCallManager -- (instancetype)init{ +- (instancetype)init { self = [super init]; - + if (self) { _dbConnection = [TSStorageManager sharedManager].newDatabaseConnection; } - + return self; } -- (void)watchForCallsThrough:(PhoneManager*)phoneManager - untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(phoneManager != nil); +- (void)watchForCallsThrough:(PhoneManager *)phoneManager untilCancelled:(TOCCancelToken *)untilCancelledToken { + ows_require(phoneManager != nil); - [phoneManager.currentCallObservable watchLatestValue:^(CallState* latestCall) { - if (latestCall != nil) { - [self addCall:latestCall]; - } - } onThread:NSThread.currentThread untilCancelled:untilCancelledToken]; + [phoneManager.currentCallObservable watchLatestValue:^(CallState *latestCall) { + if (latestCall != nil) { + [self addCall:latestCall]; + } + } + onThread:NSThread.currentThread + untilCancelled:untilCancelledToken]; } -- (void)addCall:(CallState*)call { - require(call != nil); - - [call.futureTermination finallyDo:^(TOCFuture* interactionCompletion) { - bool isOutgoingCall = call.initiatedLocally; - bool isMissedCall = [self isMissedCall:interactionCompletion]; +- (void)addCall:(CallState *)call { + ows_require(call != nil); - Contact* contact = [self tryGetContactForCall:call]; - - RPRecentCallType callType = isOutgoingCall ? RPRecentCallTypeOutgoing - : isMissedCall ? RPRecentCallTypeMissed - : RPRecentCallTypeIncoming; - - [self addRecentCall:[RecentCall recentCallWithContactID:contact.recordID - andNumber:call.remoteNumber - andCallType:callType]]; + [call.futureTermination finallyDo:^(TOCFuture *interactionCompletion) { + bool isOutgoingCall = call.initiatedLocally; + bool isMissedCall = [self isMissedCall:interactionCompletion]; + + Contact *contact = [self tryGetContactForCall:call]; + + RPRecentCallType callType = + isOutgoingCall ? RPRecentCallTypeOutgoing : isMissedCall ? RPRecentCallTypeMissed : RPRecentCallTypeIncoming; + + [self addRecentCall:[RecentCall recentCallWithContactID:contact.recordID + andNumber:call.remoteNumber + andCallType:callType]]; }]; } -- (BOOL)isMissedCall:(TOCFuture*)interactionCompletion { +- (BOOL)isMissedCall:(TOCFuture *)interactionCompletion { if ([interactionCompletion hasResult]) { if ([[interactionCompletion forceGetResult] isKindOfClass:[CallTermination class]]) { - CallTermination *termination = (CallTermination*)interactionCompletion.forceGetResult; + CallTermination *termination = (CallTermination *)interactionCompletion.forceGetResult; if (termination.type == CallTerminationType_HangupRemote) { return YES; } @@ -61,38 +63,46 @@ return NO; } -- (Contact*)tryGetContactForCall:(CallState*)call { - if (call.potentiallySpecifiedContact != nil) return call.potentiallySpecifiedContact; +- (Contact *)tryGetContactForCall:(CallState *)call { + if (call.potentiallySpecifiedContact != nil) + return call.potentiallySpecifiedContact; return [self tryGetContactForNumber:call.remoteNumber]; } -- (Contact*)tryGetContactForNumber:(PhoneNumber*)number { +- (Contact *)tryGetContactForNumber:(PhoneNumber *)number { return [Environment.getCurrent.contactsManager latestContactForPhoneNumber:number]; } -- (void)addMissedCallDueToBusy:(ResponderSessionDescriptor*)incomingCallDescriptor { - require(incomingCallDescriptor != nil); - - Contact* contact = [self tryGetContactForNumber:incomingCallDescriptor.initiatorNumber]; +- (void)addMissedCallDueToBusy:(ResponderSessionDescriptor *)incomingCallDescriptor { + ows_require(incomingCallDescriptor != nil); + + Contact *contact = [self tryGetContactForNumber:incomingCallDescriptor.initiatorNumber]; [self addRecentCall:[RecentCall recentCallWithContactID:contact.recordID andNumber:incomingCallDescriptor.initiatorNumber andCallType:RPRecentCallTypeMissed]]; } -- (void)addRecentCall:(RecentCall*)recentCall { +- (void)addRecentCall:(RecentCall *)recentCall { [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - TSContactThread *thread = [TSContactThread getOrCreateThreadWithContactId:recentCall.phoneNumber.toE164 transaction:transaction]; - - uint64_t callDateSeconds = (uint64_t)[recentCall.date timeIntervalSince1970]; - TSCall *call = [[TSCall alloc] initWithTimestamp:callDateSeconds*1000 withCallNumber:recentCall.phoneNumber.toE164 callType:recentCall.callType inThread:thread]; - if(recentCall.isArchived) { //for migration only from Signal versions with RedPhone only - NSDate *date = [NSDate dateWithTimeIntervalSince1970:(callDateSeconds+60)]; // archive has to happen in the future of the original call - [thread archiveThreadWithTransaction:transaction referenceDate:date]; - } - - [call saveWithTransaction:transaction]; - - [[TSMessagesManager sharedManager] notifyUserForCall:call inThread:thread]; + TSContactThread *thread = + [TSContactThread getOrCreateThreadWithContactId:recentCall.phoneNumber.toE164 transaction:transaction]; + + uint64_t callDateSeconds = (uint64_t)[recentCall.date timeIntervalSince1970]; + TSCall *call = [[TSCall alloc] initWithTimestamp:callDateSeconds * 1000 + withCallNumber:recentCall.phoneNumber.toE164 + callType:recentCall.callType + inThread:thread]; + if (recentCall.isArchived) { // for migration only from Signal versions with RedPhone only + NSDate *date = + [NSDate dateWithTimeIntervalSince1970:(callDateSeconds + + 60)]; // archive has to happen in the future of the original call + [thread archiveThreadWithTransaction:transaction referenceDate:date]; + } + + [call saveWithTransaction:transaction]; + + NotificationsManager *manager = [TextSecureKitEnv sharedEnv].notificationsManager; + [manager notifyUserForCall:call inThread:thread]; }]; } diff --git a/Signal/src/contact/Contact.h b/Signal/src/contact/Contact.h deleted file mode 100644 index d19c896d3..000000000 --- a/Signal/src/contact/Contact.h +++ /dev/null @@ -1,45 +0,0 @@ -#import -#import -#import "PhoneNumber.h" - -/** - * - * Contact represents relevant information related to a contact from the user's contact list. - * - */ - -@interface Contact : NSObject - -@property (readonly,nonatomic) NSString *firstName; -@property (readonly,nonatomic) NSString *lastName; -@property (readonly,nonatomic) NSArray *parsedPhoneNumbers; -@property (readonly,nonatomic) NSArray *userTextPhoneNumbers; -@property (readonly,nonatomic) NSArray *emails; -@property (readonly,nonatomic) UIImage *image; -@property (readonly,nonatomic) NSString *notes; -@property (readonly,nonatomic) ABRecordID recordID; - -+ (Contact*)contactWithFirstName:(NSString*)firstName - andLastName:(NSString *)lastName - andUserTextPhoneNumbers:(NSArray*)phoneNumbers - andEmails:(NSArray*)emails - andContactID:(ABRecordID)record; - -+ (Contact*)contactWithFirstName:(NSString*)firstName - andLastName:(NSString *)lastName - andUserTextPhoneNumbers:(NSArray*)numbers - andEmails:(NSArray*)emails - andImage:(UIImage *)image - andContactID:(ABRecordID)record - andNotes:(NSString *)notes; - -- (NSString*)fullName; -- (NSString *)allPhoneNumbers; - -- (BOOL)isTextSecureContact; -- (BOOL)isRedPhoneContact; - -- (NSArray*)textSecureIdentifiers; -- (NSArray*)redPhoneIdentifiers; - -@end diff --git a/Signal/src/contact/Contact.m b/Signal/src/contact/Contact.m deleted file mode 100644 index 3e6850d39..000000000 --- a/Signal/src/contact/Contact.m +++ /dev/null @@ -1,134 +0,0 @@ -#import "Contact.h" -#import "ContactsManager.h" -#import "Environment.h" -#import "SignalRecipient.h" - -static NSString *const DEFAULTS_KEY_CONTACT = @"DefaultsKeyContact"; -static NSString *const DEFAULTS_KEY_PHONE_NUMBER = @"DefaultsKeyPhoneNumber"; -static NSString *const DEFAULTS_KEY_CALL_TYPE = @"DefaultsKeycallType"; -static NSString *const DEFAULTS_KEY_DATE = @"DefaultsKeyDate"; - -@implementation Contact - -@synthesize firstName, lastName, emails, image, recordID, notes, parsedPhoneNumbers, userTextPhoneNumbers; - -+ (Contact*)contactWithFirstName:(NSString*)firstName - andLastName:(NSString *)lastName - andUserTextPhoneNumbers:(NSArray*)phoneNumbers - andEmails:(NSArray*)emails - andContactID:(ABRecordID)record { - - Contact* contact = [Contact new]; - contact->firstName = firstName; - contact->lastName = lastName; - contact->userTextPhoneNumbers = phoneNumbers; - contact->emails = emails; - contact->recordID = record; - - NSMutableArray *parsedPhoneNumbers = [NSMutableArray array]; - - for (NSString *phoneNumberString in phoneNumbers) { - PhoneNumber *phoneNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:phoneNumberString]; - if (phoneNumber) { - [parsedPhoneNumbers addObject:phoneNumber]; - } - } - - contact->parsedPhoneNumbers = parsedPhoneNumbers.copy; - - return contact; -} - -+ (Contact*)contactWithFirstName:(NSString*)firstName - andLastName:(NSString *)lastName - andUserTextPhoneNumbers:(NSArray*)numbers - andEmails:(NSArray*)emails - andImage:(UIImage *)image - andContactID:(ABRecordID)record - andNotes:(NSString *)notes { - - Contact* contact = [Contact contactWithFirstName:firstName - andLastName:lastName - andUserTextPhoneNumbers:numbers - andEmails:emails - andContactID:record]; - - contact->image = image; - contact->notes = notes; - return contact; -} - -- (NSString *)fullName { - NSMutableString *fullName = [NSMutableString string]; - if (firstName) [fullName appendString:firstName]; - if (lastName) { - [fullName appendString:[NSString stringWithFormat:@" %@",lastName]]; - } - return fullName; -} - -- (NSString *)allPhoneNumbers { - NSString * allNumbers = @""; - for (PhoneNumber *number in self.parsedPhoneNumbers) { - allNumbers = [allNumbers stringByAppendingString:number.toE164]; - allNumbers = [allNumbers stringByAppendingString:@";"]; - } - return allNumbers; -} - --(NSString *)description { - return [NSString stringWithFormat:@"%@ %@: %@", firstName, lastName, userTextPhoneNumbers]; -} - -- (UIImage *)image { - return image; -} - -- (BOOL)isTextSecureContact{ - NSArray *identifiers = [self textSecureIdentifiers]; - - if ([identifiers count] > 0) { - return YES; - } - - return NO; -} - -- (NSArray*)textSecureIdentifiers{ - __block NSMutableArray *identifiers = [NSMutableArray array]; - - [[TSStorageManager sharedManager].dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - for (PhoneNumber *number in self.parsedPhoneNumbers) { - if ([SignalRecipient recipientWithTextSecureIdentifier:number.toE164 withTransaction:transaction]) { - [identifiers addObject:number.toE164]; - } - } - }]; - return identifiers; -} - -- (BOOL)isRedPhoneContact{ - NSArray *identifiers = [self redPhoneIdentifiers]; - - if ([identifiers count] > 0) { - return YES; - } - - return NO; -} - -- (NSArray *)redPhoneIdentifiers{ - __block NSMutableArray *identifiers = [NSMutableArray array]; - - [[TSStorageManager sharedManager].dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - for (PhoneNumber *number in self.parsedPhoneNumbers) { - SignalRecipient *recipient = [SignalRecipient recipientWithTextSecureIdentifier:number.toE164 withTransaction:transaction]; - if (recipient && recipient.supportsVoice) { - [identifiers addObject:number.toE164]; - } - } - }]; - return identifiers; -} - -@end diff --git a/Signal/src/contact/ContactsManager+updater.h b/Signal/src/contact/ContactsManager+updater.h deleted file mode 100644 index fb56da9b4..000000000 --- a/Signal/src/contact/ContactsManager+updater.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// ContactsManager+updater.h -// Signal -// -// Created by Frederic Jacobs on 21/11/15. -// Copyright © 2015 Open Whisper Systems. All rights reserved. -// - -#import "SignalRecipient.h" -#import "ContactsManager.h" - -@interface ContactsManager (updater) - -#define NOTFOUND_ERROR 777404 - -- (void)intersectContacts; -- (void)synchronousLookup:(NSString*)identifier - success:(void (^)(SignalRecipient*))success - failure:(void (^)(NSError *error))failure; - -- (void)lookupIdentifier:(NSString*)identifier - success:(void (^)(NSSet *matchedIds))success - failure:(void (^)(NSError *error))failure; - -- (void)updateSignalContactIntersectionWithSuccess:(void (^)())success - failure:(void (^)(NSError *error))failure; -@end diff --git a/Signal/src/contact/ContactsManager+updater.m b/Signal/src/contact/ContactsManager+updater.m deleted file mode 100644 index af4e180f0..000000000 --- a/Signal/src/contact/ContactsManager+updater.m +++ /dev/null @@ -1,184 +0,0 @@ -// -// ContactsManager+updater.m -// Signal -// -// Created by Frederic Jacobs on 21/11/15. -// Copyright © 2015 Open Whisper Systems. All rights reserved. -// - -#import "ContactsManager+updater.h" - -#import "Cryptography.h" -#import "Environment.h" -#import "TSContactsIntersectionRequest.h" -#import "TSNetworkManager.h" - -@implementation ContactsManager (updater) - -- (void)synchronousLookup:(NSString*)identifier - success:(void (^)(SignalRecipient*))success - failure:(void (^)(NSError *error))failure -{ - __block dispatch_semaphore_t sema = dispatch_semaphore_create(0); - __block SignalRecipient *recipient = nil; - __block NSError *error = nil; - - [self lookupIdentifier:identifier - success:^(NSSet *matchedIds) { - if ([matchedIds count] == 1) { - [[TSStorageManager sharedManager].dbConnection readWithBlock:^(YapDatabaseReadTransaction * _Nonnull transaction) { - recipient = [SignalRecipient recipientWithTextSecureIdentifier:identifier withTransaction:transaction]; - }]; - } else { - error = [NSError errorWithDomain:@"contactsmanager.notfound" code:NOTFOUND_ERROR userInfo:nil]; - } - dispatch_semaphore_signal(sema); - } failure:^(NSError *blockerror) { - error = blockerror; - dispatch_semaphore_signal(sema); - }]; - - dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); - if (error) { - SYNC_BLOCK_SAFE_RUN(failure, error); - } else { - SYNC_BLOCK_SAFE_RUN(success, recipient); - } - - return; -} - - - -- (void)lookupIdentifier:(NSString*)identifier - success:(void (^)(NSSet *matchedIds))success - failure:(void (^)(NSError *error))failure -{ - [self contactIntersectionWithSet:[NSSet setWithObject:identifier] - success:^(NSSet *matchedIds){ - BLOCK_SAFE_RUN(success, matchedIds); - } - failure:^(NSError *error) { - BLOCK_SAFE_RUN(failure, error); - }]; -} - -- (void)intersectContacts { - [self updateSignalContactIntersectionWithSuccess:nil failure:^(NSError *error) { - [NSTimer scheduledTimerWithTimeInterval:60 - target:self - selector:@selector(intersectContacts) - userInfo:nil - repeats:NO]; - }]; -} - -- (void)updateSignalContactIntersectionWithSuccess:(void (^)())success - failure:(void (^)(NSError *error))failure -{ - NSArray *abContacts = [[[Environment getCurrent] contactsManager] allContacts]; - NSMutableSet *abPhoneNumbers = [NSMutableSet set]; - - for (Contact *contact in abContacts) { - for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) { - [abPhoneNumbers addObject:phoneNumber.toE164]; - } - } - - __block NSMutableSet *recipientIds = [NSMutableSet set]; - [[TSStorageManager sharedManager].dbConnection readWithBlock:^(YapDatabaseReadTransaction * _Nonnull transaction) { - NSArray *allRecipientKeys = [transaction allKeysInCollection:[SignalRecipient collection]]; - [recipientIds addObjectsFromArray:allRecipientKeys]; - }]; - - NSMutableSet *allContacts = [[abPhoneNumbers setByAddingObjectsFromSet:recipientIds] mutableCopy]; - - [self contactIntersectionWithSet:allContacts - success:^(NSSet *matchedIds) { - [recipientIds minusSet:matchedIds]; - - // Cleaning up unregistered identifiers - [[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction * _Nonnull transaction) { - for (NSString *identifier in recipientIds) { - SignalRecipient *recipient = [SignalRecipient fetchObjectWithUniqueID:identifier transaction:transaction]; - [recipient removeWithTransaction:transaction]; - } - }]; - - BLOCK_SAFE_RUN(success); - } failure:^(NSError *error) { - BLOCK_SAFE_RUN(failure, error); - }]; -} - -- (void) contactIntersectionWithSet:(NSSet*)idSet - success:(void (^)(NSSet *matchedIds))success - failure:(void (^)(NSError *error))failure -{ - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSMutableDictionary *phoneNumbersByHashes = [NSMutableDictionary dictionary]; - for (NSString *identifier in idSet) { - [phoneNumbersByHashes setObject:identifier - forKey:[Cryptography truncatedSHA1Base64EncodedWithoutPadding:identifier]]; - } - NSArray *hashes = [phoneNumbersByHashes allKeys]; - - TSRequest *request = [[TSContactsIntersectionRequest alloc] initWithHashesArray:hashes]; - [[TSNetworkManager sharedManager] queueAuthenticatedRequest:request success:^(NSURLSessionDataTask *tsTask, id responseDict) { - NSMutableDictionary *attributesForIdentifier = [NSMutableDictionary dictionary]; - NSArray *contactsArray = [(NSDictionary*)responseDict objectForKey:@"contacts"]; - - // Map attributes to phone numbers - if (contactsArray) { - for (NSDictionary *dict in contactsArray) { - NSString *hash = [dict objectForKey:@"token"]; - NSString *identifier = [phoneNumbersByHashes objectForKey:hash]; - - if (!identifier) { - DDLogWarn(@"An interesecting hash wasn't found in the mapping."); - break; - } - - [attributesForIdentifier setObject:dict forKey:identifier]; - } - } - - // Insert or update contact attributes - [[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - for (NSString *identifier in attributesForIdentifier) { - SignalRecipient *recipient = [SignalRecipient recipientWithTextSecureIdentifier:identifier - withTransaction:transaction]; - if (!recipient) { - recipient = [[SignalRecipient alloc] initWithTextSecureIdentifier:identifier - relay:nil - supportsVoice:NO]; - } - - NSDictionary *attributes = [attributesForIdentifier objectForKey:identifier]; - - NSString *relay = [attributes objectForKey:@"relay"]; - if (relay) { - recipient.relay = relay; - } else { - recipient.relay = nil; - } - - BOOL supportsVoice = [[attributes objectForKey:@"voice"] boolValue]; - if (supportsVoice) { - recipient.supportsVoice = YES; - } else { - recipient.supportsVoice = NO; - } - - [recipient saveWithTransaction:transaction]; - } - }]; - - BLOCK_SAFE_RUN(success, [NSSet setWithArray:attributesForIdentifier.allKeys]); - } failure:^(NSURLSessionDataTask *task, NSError *error) { - BLOCK_SAFE_RUN(failure, error); - }]; - }); -} - -@end diff --git a/Signal/src/contact/ContactsManager.h b/Signal/src/contact/ContactsManager.h index d9aa04c6d..4a9dbfddf 100644 --- a/Signal/src/contact/ContactsManager.h +++ b/Signal/src/contact/ContactsManager.h @@ -1,8 +1,10 @@ +#import #import +#import +#import #import "CollapsingFutures.h" #import "Contact.h" #import "ObservableValue.h" -#import /** * @@ -16,43 +18,43 @@ #define SIGNAL_LIST_UPDATED @"Signal_AB_UPDATED" -typedef void(^ABAccessRequestCompletionBlock)(BOOL hasAccess); -typedef void(^ABReloadRequestCompletionBlock)(NSArray *contacts); +typedef void (^ABAccessRequestCompletionBlock)(BOOL hasAccess); +typedef void (^ABReloadRequestCompletionBlock)(NSArray *contacts); -@interface ContactsManager : NSObject { -@private TOCFuture* futureAddressBook; -@private ObservableValueController* observableContactsController; -@private ObservableValueController* observableTextSecureUsersController; -@private TOCCancelTokenSource* life; -@private NSDictionary *latestContactsById; -@private NSDictionary *latestWhisperUsersById; +@interface ContactsManager : NSObject { + @private + TOCFuture *futureAddressBook; + @private + ObservableValueController *observableContactsController; + @private + TOCCancelTokenSource *life; + @private + NSDictionary *latestContactsById; + @private + NSDictionary *latestWhisperUsersById; } @property CNContactStore *contactStore; --(ObservableValue *) getObservableContacts; -//-(ObservableValue *) getObservableRedPhoneUsers; +- (ObservableValue *)getObservableContacts; --(NSArray*) getContactsFromAddressBook:(ABAddressBookRef)addressBook; --(Contact*) latestContactWithRecordId:(ABRecordID)recordId; --(Contact*) latestContactForPhoneNumber:(PhoneNumber *)phoneNumber; --(NSArray*) latestContactsWithSearchString:(NSString *)searchString; +- (NSArray *)getContactsFromAddressBook:(ABAddressBookRef)addressBook; +- (Contact *)latestContactWithRecordId:(ABRecordID)recordId; +- (Contact *)latestContactForPhoneNumber:(PhoneNumber *)phoneNumber; +- (NSArray *)latestContactsWithSearchString:(NSString *)searchString; -+(NSDictionary *)groupContactsByFirstLetter:(NSArray *)contacts matchingSearchString:(NSString *)optionalSearchString; - -+(BOOL)name:(NSString *)nameString matchesQuery:(NSString *)queryString; -+(BOOL)phoneNumber:(PhoneNumber *)phoneNumber matchesQuery:(NSString *)queryString; ++ (NSDictionary *)groupContactsByFirstLetter:(NSArray *)contacts matchingSearchString:(NSString *)optionalSearchString; - (void)verifyABPermission; - (NSArray *)allContacts; -- (NSArray*)signalContacts; -- (NSArray*)textSecureContacts; +- (NSArray *)signalContacts; +- (NSArray *)textSecureContacts; --(void)doAfterEnvironmentInitSetup; +- (void)doAfterEnvironmentInitSetup; -- (NSString*)nameStringForPhoneIdentifier:(NSString*)identifier; -- (UIImage*)imageForPhoneIdentifier:(NSString*)identifier; +- (NSString *)nameStringForPhoneIdentifier:(NSString *)identifier; +- (UIImage *)imageForPhoneIdentifier:(NSString *)identifier; + (NSComparator)contactComparator; diff --git a/Signal/src/contact/ContactsManager.m b/Signal/src/contact/ContactsManager.m index e8c5bb9fe..5cd507d79 100644 --- a/Signal/src/contact/ContactsManager.m +++ b/Signal/src/contact/ContactsManager.m @@ -1,10 +1,11 @@ -#import "ContactsManager+updater.h" +#import "ContactsManager.h" +#import "ContactsUpdater.h" #import "Environment.h" #import "Util.h" #define ADDRESSBOOK_QUEUE dispatch_get_main_queue() -typedef BOOL (^ContactSearchBlock)(id, NSUInteger, BOOL*); +typedef BOOL (^ContactSearchBlock)(id, NSUInteger, BOOL *); @interface ContactsManager () { id addressBookReference; @@ -17,33 +18,35 @@ typedef BOOL (^ContactSearchBlock)(id, NSUInteger, BOOL*); - (id)init { self = [super init]; if (self) { - life = [TOCCancelTokenSource new]; - observableContactsController = [ObservableValueController observableValueControllerWithInitialValue:nil]; + life = [TOCCancelTokenSource new]; + observableContactsController = [ObservableValueController observableValueControllerWithInitialValue:nil]; } return self; } --(void) doAfterEnvironmentInitSetup { +- (void)doAfterEnvironmentInitSetup { if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(_iOS_9)) { self.contactStore = [[CNContactStore alloc] init]; - [self.contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) { - if (!granted) { - // We're still using the old addressbook API. - // User warned if permission not granted in that setup. - } - }]; + [self.contactStore requestAccessForEntityType:CNEntityTypeContacts + completionHandler:^(BOOL granted, NSError *_Nullable error) { + if (!granted) { + // We're still using the old addressbook API. + // User warned if permission not granted in that setup. + } + }]; } - + [self setupAddressBook]; - + [observableContactsController watchLatestValueOnArbitraryThread:^(NSArray *latestContacts) { - @synchronized(self) { - [self setupLatestContacts:latestContacts]; - } - } untilCancelled:life.token]; + @synchronized(self) { + [self setupLatestContacts:latestContacts]; + } + } + untilCancelled:life.token]; } --(void)dealloc { +- (void)dealloc { [life cancel]; } @@ -57,37 +60,50 @@ typedef BOOL (^ContactSearchBlock)(id, NSUInteger, BOOL*); void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef info, void *context); void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef info, void *context) { - ContactsManager* contactsManager = (__bridge ContactsManager*)context; + ContactsManager *contactsManager = (__bridge ContactsManager *)context; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - [contactsManager pullLatestAddressBook]; - [contactsManager intersectContacts]; + [contactsManager pullLatestAddressBook]; + [contactsManager intersectContacts]; }); } #pragma mark - Setup --(void) setupAddressBook { +- (void)setupAddressBook { dispatch_async(ADDRESSBOOK_QUEUE, ^{ - [[ContactsManager asyncGetAddressBook] thenDo:^(id addressBook) { - addressBookReference = addressBook; - ABAddressBookRef cfAddressBook = (__bridge ABAddressBookRef)addressBook; - ABAddressBookRegisterExternalChangeCallback(cfAddressBook, onAddressBookChanged, (__bridge void*)self); - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{ - [self pullLatestAddressBook]; - [self intersectContacts]; - }); - }]; + [[ContactsManager asyncGetAddressBook] thenDo:^(id addressBook) { + addressBookReference = addressBook; + ABAddressBookRef cfAddressBook = (__bridge ABAddressBookRef)addressBook; + ABAddressBookRegisterExternalChangeCallback(cfAddressBook, onAddressBookChanged, (__bridge void *)self); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [self pullLatestAddressBook]; + [self intersectContacts]; + }); + }]; }); } --(void) pullLatestAddressBook{ - CFErrorRef creationError = nil; - ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, &creationError); - checkOperationDescribe(nil == creationError, [((__bridge NSError *)creationError) localizedDescription]) ; - ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) { - if (!granted) { - [ContactsManager blockingContactDialog]; +- (void)intersectContacts { + [[ContactsUpdater sharedUpdater] updateSignalContactIntersectionWithABContacts:self.allContacts + success:^{ } + failure:^(NSError *error) { + [NSTimer scheduledTimerWithTimeInterval:60 + target:self + selector:@selector(intersectContacts) + userInfo:nil + repeats:NO]; + }]; +} + +- (void)pullLatestAddressBook { + CFErrorRef creationError = nil; + ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, &creationError); + checkOperationDescribe(nil == creationError, [((__bridge NSError *)creationError)localizedDescription]); + ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) { + if (!granted) { + [ContactsManager blockingContactDialog]; + } }); [observableContactsController updateValue:[self getContactsFromAddressBook:addressBookRef]]; } @@ -98,49 +114,60 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in } } -+ (void)blockingContactDialog{ ++ (void)blockingContactDialog { switch (ABAddressBookGetAuthorizationStatus()) { - case kABAuthorizationStatusRestricted:{ - UIAlertController *controller = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"AB_PERMISSION_MISSING_TITLE", nil) - message:NSLocalizedString(@"ADDRESSBOOK_RESTRICTED_ALERT_BODY", nil) - preferredStyle:UIAlertControllerStyleAlert]; - - [controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"ADDRESSBOOK_RESTRICTED_ALERT_BUTTON", nil) - style:UIAlertActionStyleDefault - handler:^(UIAlertAction *action) { - exit(0); - }]]; - - [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:controller animated:YES completion:nil]; - + case kABAuthorizationStatusRestricted: { + UIAlertController *controller = + [UIAlertController alertControllerWithTitle:NSLocalizedString(@"AB_PERMISSION_MISSING_TITLE", nil) + message:NSLocalizedString(@"ADDRESSBOOK_RESTRICTED_ALERT_BODY", nil) + preferredStyle:UIAlertControllerStyleAlert]; + + [controller + addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"ADDRESSBOOK_RESTRICTED_ALERT_BUTTON", nil) + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *action) { + exit(0); + }]]; + + [[UIApplication sharedApplication] + .keyWindow.rootViewController presentViewController:controller + animated:YES + completion:nil]; + break; } case kABAuthorizationStatusDenied: { - UIAlertController *controller = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"AB_PERMISSION_MISSING_TITLE", nil) - message:NSLocalizedString(@"AB_PERMISSION_MISSING_BODY", nil) - preferredStyle:UIAlertControllerStyleAlert]; - - [controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"AB_PERMISSION_MISSING_ACTION", nil) - style:UIAlertActionStyleDefault - handler:^(UIAlertAction *action) { - [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]; - }]]; - - [[[UIApplication sharedApplication] keyWindow].rootViewController presentViewController:controller animated:YES completion:nil]; + UIAlertController *controller = + [UIAlertController alertControllerWithTitle:NSLocalizedString(@"AB_PERMISSION_MISSING_TITLE", nil) + message:NSLocalizedString(@"AB_PERMISSION_MISSING_BODY", nil) + preferredStyle:UIAlertControllerStyleAlert]; + + [controller addAction:[UIAlertAction + actionWithTitle:NSLocalizedString(@"AB_PERMISSION_MISSING_ACTION", nil) + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *action) { + [[UIApplication sharedApplication] + openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]; + }]]; + + [[[UIApplication sharedApplication] keyWindow] + .rootViewController presentViewController:controller + animated:YES + completion:nil]; break; } - + case kABAuthorizationStatusNotDetermined: { DDLogInfo(@"AddressBook access not granted but status undetermined."); [[Environment getCurrent].contactsManager pullLatestAddressBook]; break; } - - case kABAuthorizationStatusAuthorized:{ + + case kABAuthorizationStatusAuthorized: { DDLogInfo(@"AddressBook access not granted but status authorized."); break; } - + default: break; } @@ -154,76 +181,77 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in #pragma mark - Observables --(ObservableValue *)getObservableContacts { +- (ObservableValue *)getObservableContacts { return observableContactsController; } #pragma mark - Address Book utils -+(TOCFuture*) asyncGetAddressBook { - CFErrorRef creationError = nil; ++ (TOCFuture *)asyncGetAddressBook { + CFErrorRef creationError = nil; ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, &creationError); assert((addressBookRef == nil) == (creationError != nil)); if (creationError != nil) { [self blockingContactDialog]; return [TOCFuture futureWithFailure:(__bridge_transfer id)creationError]; } - + TOCFutureSource *futureAddressBookSource = [TOCFutureSource new]; - + id addressBook = (__bridge_transfer id)addressBookRef; ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef requestAccessError) { - if (granted && ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) { - dispatch_async(ADDRESSBOOK_QUEUE,^{ - [futureAddressBookSource trySetResult:addressBook]; - }); - } else { - [self blockingContactDialog]; - [futureAddressBookSource trySetFailure:(__bridge id)requestAccessError]; - } + if (granted && ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) { + dispatch_async(ADDRESSBOOK_QUEUE, ^{ + [futureAddressBookSource trySetResult:addressBook]; + }); + } else { + [self blockingContactDialog]; + [futureAddressBookSource trySetFailure:(__bridge id)requestAccessError]; + } }); - + return futureAddressBookSource.future; } --(NSArray*) getContactsFromAddressBook:(ABAddressBookRef)addressBook { +- (NSArray *)getContactsFromAddressBook:(ABAddressBookRef)addressBook { CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook); - CFMutableArrayRef allPeopleMutable = CFArrayCreateMutableCopy(kCFAllocatorDefault, - CFArrayGetCount(allPeople),allPeople); - - CFArraySortValues(allPeopleMutable,CFRangeMake(0, CFArrayGetCount(allPeopleMutable)), + CFMutableArrayRef allPeopleMutable = + CFArrayCreateMutableCopy(kCFAllocatorDefault, CFArrayGetCount(allPeople), allPeople); + + CFArraySortValues(allPeopleMutable, + CFRangeMake(0, CFArrayGetCount(allPeopleMutable)), (CFComparatorFunction)ABPersonComparePeopleByName, - (void*)(unsigned long)ABPersonGetSortOrdering()); - + (void *)(unsigned long)ABPersonGetSortOrdering()); + NSArray *sortedPeople = (__bridge_transfer NSArray *)allPeopleMutable; - + // This predicate returns all contacts from the addressbook having at least one phone number - - NSPredicate* predicate = [NSPredicate predicateWithBlock: ^BOOL(id record, NSDictionary *bindings) { - ABMultiValueRef phoneNumbers = ABRecordCopyValue( (__bridge ABRecordRef)record, kABPersonPhoneProperty); - BOOL result = NO; - - for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) { - NSString* phoneNumber = (__bridge_transfer NSString*) ABMultiValueCopyValueAtIndex(phoneNumbers, i); - if (phoneNumber.length>0) { - result = YES; - break; - } - } - CFRelease(phoneNumbers); - return result; + + NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id record, NSDictionary *bindings) { + ABMultiValueRef phoneNumbers = ABRecordCopyValue((__bridge ABRecordRef)record, kABPersonPhoneProperty); + BOOL result = NO; + + for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) { + NSString *phoneNumber = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phoneNumbers, i); + if (phoneNumber.length > 0) { + result = YES; + break; + } + } + CFRelease(phoneNumbers); + return result; }]; CFRelease(allPeople); - NSArray* filteredContacts = [sortedPeople filteredArrayUsingPredicate:predicate]; - + NSArray *filteredContacts = [sortedPeople filteredArrayUsingPredicate:predicate]; + return [filteredContacts map:^id(id item) { - return [self contactForRecord:(__bridge ABRecordRef)item]; + return [self contactForRecord:(__bridge ABRecordRef)item]; }]; } --(NSArray*)latestContactsWithSearchString:(NSString *)searchString { +- (NSArray *)latestContactsWithSearchString:(NSString *)searchString { return [latestContactsById.allValues filter:^int(Contact *contact) { - return searchString.length == 0 || [ContactsManager name:contact.fullName matchesQuery:searchString]; + return searchString.length == 0 || [ContactsManager name:contact.fullName matchesQuery:searchString]; }]; } @@ -231,50 +259,47 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in - (Contact *)contactForRecord:(ABRecordRef)record { ABRecordID recordID = ABRecordGetRecordID(record); - - NSString *firstName = (__bridge_transfer NSString*)ABRecordCopyValue(record, kABPersonFirstNameProperty); - NSString *lastName = (__bridge_transfer NSString*)ABRecordCopyValue(record, kABPersonLastNameProperty); + + NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(record, kABPersonFirstNameProperty); + NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(record, kABPersonLastNameProperty); NSArray *phoneNumbers = [self phoneNumbersForRecord:record]; - + if (!firstName && !lastName) { - NSString *companyName = (__bridge_transfer NSString*)ABRecordCopyValue(record, kABPersonOrganizationProperty); + NSString *companyName = (__bridge_transfer NSString *)ABRecordCopyValue(record, kABPersonOrganizationProperty); if (companyName) { firstName = companyName; } else if (phoneNumbers.count) { - firstName = phoneNumbers.firstObject; + firstName = phoneNumbers.firstObject; } } - - NSString *notes = (__bridge_transfer NSString*)ABRecordCopyValue(record, kABPersonNoteProperty); - NSArray *emails = [ContactsManager emailsForRecord:record]; - NSData *image = (__bridge_transfer NSData*)ABPersonCopyImageDataWithFormat(record, kABPersonImageFormatThumbnail); - UIImage *img = [UIImage imageWithData:image]; - - return [Contact contactWithFirstName:firstName - andLastName:lastName - andUserTextPhoneNumbers:phoneNumbers - andEmails:emails - andImage:img - andContactID:recordID - andNotes:notes]; + + // NSString *notes = (__bridge_transfer NSString *)ABRecordCopyValue(record, kABPersonNoteProperty); + // NSArray *emails = [ContactsManager emailsForRecord:record]; + // NSData *image = (__bridge_transfer NSData *)ABPersonCopyImageDataWithFormat(record, + // kABPersonImageFormatThumbnail); + // UIImage *img = [UIImage imageWithData:image]; + + return [[Contact alloc] initWithContactWithFirstName:firstName + andLastName:lastName + andUserTextPhoneNumbers:phoneNumbers + andContactID:recordID]; } --(Contact*)latestContactForPhoneNumber:(PhoneNumber *)phoneNumber { +- (Contact *)latestContactForPhoneNumber:(PhoneNumber *)phoneNumber { NSArray *allContacts = [self allContacts]; - + ContactSearchBlock searchBlock = ^BOOL(Contact *contact, NSUInteger idx, BOOL *stop) { - for (PhoneNumber *number in contact.parsedPhoneNumbers) { - - if ([self phoneNumber:number matchesNumber:phoneNumber]) { - *stop = YES; - return YES; - } - } - return NO; + for (PhoneNumber *number in contact.parsedPhoneNumbers) { + if ([self phoneNumber:number matchesNumber:phoneNumber]) { + *stop = YES; + return YES; + } + } + return NO; }; - + NSUInteger contactIndex = [allContacts indexOfObjectPassingTest:searchBlock]; - + if (contactIndex != NSNotFound) { return allContacts[contactIndex]; } else { @@ -288,21 +313,22 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in - (NSArray *)phoneNumbersForRecord:(ABRecordRef)record { ABMultiValueRef numberRefs = ABRecordCopyValue(record, kABPersonPhoneProperty); - + @try { - NSArray *phoneNumbers = (__bridge_transfer NSArray*)ABMultiValueCopyArrayOfAllValues(numberRefs); - - if (phoneNumbers == nil) phoneNumbers = @[]; - + NSArray *phoneNumbers = (__bridge_transfer NSArray *)ABMultiValueCopyArrayOfAllValues(numberRefs); + + if (phoneNumbers == nil) + phoneNumbers = @[]; + NSMutableArray *numbers = [NSMutableArray array]; - + for (NSUInteger i = 0; i < phoneNumbers.count; i++) { NSString *phoneNumber = phoneNumbers[i]; [numbers addObject:phoneNumber]; } - + return numbers; - + } @finally { if (numberRefs) { CFRelease(numberRefs); @@ -310,16 +336,17 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in } } -+(NSArray *)emailsForRecord:(ABRecordRef)record { ++ (NSArray *)emailsForRecord:(ABRecordRef)record { ABMultiValueRef emailRefs = ABRecordCopyValue(record, kABPersonEmailProperty); - + @try { - NSArray *emails = (__bridge_transfer NSArray*)ABMultiValueCopyArrayOfAllValues(emailRefs); - - if (emails == nil) emails = @[]; - + NSArray *emails = (__bridge_transfer NSArray *)ABMultiValueCopyArrayOfAllValues(emailRefs); + + if (emails == nil) + emails = @[]; + return emails; - + } @finally { if (emailRefs) { CFRelease(emailRefs); @@ -327,47 +354,47 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in } } -+(NSDictionary *)groupContactsByFirstLetter:(NSArray *)contacts matchingSearchString:(NSString *)optionalSearchString { - require(contacts != nil); - ++ (NSDictionary *)groupContactsByFirstLetter:(NSArray *)contacts matchingSearchString:(NSString *)optionalSearchString { + assert(contacts != nil); + NSArray *matchingContacts = [contacts filter:^int(Contact *contact) { - return optionalSearchString.length == 0 || [self name:contact.fullName matchesQuery:optionalSearchString]; + return optionalSearchString.length == 0 || [self name:contact.fullName matchesQuery:optionalSearchString]; }]; - + return [matchingContacts groupBy:^id(Contact *contact) { - NSString *nameToUse = @""; - - BOOL firstNameOrdering = ABPersonGetSortOrdering() == kABPersonCompositeNameFormatFirstNameFirst?YES:NO; - - if (firstNameOrdering && contact.firstName != nil && contact.firstName.length > 0) { - nameToUse = contact.firstName; - } else if (!firstNameOrdering && contact.lastName != nil && contact.lastName.length > 0){ - nameToUse = contact.lastName; - } else if (contact.lastName == nil) { - if (contact.fullName.length > 0) { - nameToUse = contact.fullName; - } else { - return nameToUse; - } - } else { - nameToUse = contact.lastName; - } - - if (nameToUse.length >= 1) { - return [[[nameToUse substringToIndex:1] uppercaseString] decomposedStringWithCompatibilityMapping]; - } else{ - return @" "; - } + NSString *nameToUse = @""; + + BOOL firstNameOrdering = ABPersonGetSortOrdering() == kABPersonCompositeNameFormatFirstNameFirst ? YES : NO; + + if (firstNameOrdering && contact.firstName != nil && contact.firstName.length > 0) { + nameToUse = contact.firstName; + } else if (!firstNameOrdering && contact.lastName != nil && contact.lastName.length > 0) { + nameToUse = contact.lastName; + } else if (contact.lastName == nil) { + if (contact.fullName.length > 0) { + nameToUse = contact.fullName; + } else { + return nameToUse; + } + } else { + nameToUse = contact.lastName; + } + + if (nameToUse.length >= 1) { + return [[[nameToUse substringToIndex:1] uppercaseString] decomposedStringWithCompatibilityMapping]; + } else { + return @" "; + } }]; } -+(NSDictionary *)keyContactsById:(NSArray *)contacts { - return [contacts keyedBy:^id(Contact* contact) { - return @((int)contact.recordID); ++ (NSDictionary *)keyContactsById:(NSArray *)contacts { + return [contacts keyedBy:^id(Contact *contact) { + return @((int)contact.recordID); }]; } --(Contact *)latestContactWithRecordId:(ABRecordID)recordId { +- (Contact *)latestContactWithRecordId:(ABRecordID)recordId { @synchronized(self) { return latestContactsById[@(recordId)]; } @@ -375,10 +402,10 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in - (NSArray *)allContacts { NSMutableArray *allContacts = [NSMutableArray array]; - - for (NSString *key in latestContactsById.allKeys){ + + for (NSString *key in latestContactsById.allKeys) { Contact *contact = [latestContactsById objectForKey:key]; - + if ([contact isKindOfClass:[Contact class]]) { [allContacts addObject:contact]; } @@ -386,40 +413,42 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in return allContacts; } -- (NSArray*)recordsForContacts:(NSArray*) contacts{ +- (NSArray *)recordsForContacts:(NSArray *)contacts { return [contacts map:^id(Contact *contact) { - return @([contact recordID]); + return @([contact recordID]); }]; } -+(BOOL)name:(NSString *)nameString matchesQuery:(NSString *)queryString { ++ (BOOL)name:(NSString *)nameString matchesQuery:(NSString *)queryString { NSCharacterSet *whitespaceSet = NSCharacterSet.whitespaceCharacterSet; - NSArray *queryStrings = [queryString componentsSeparatedByCharactersInSet:whitespaceSet]; - NSArray *nameStrings = [nameString componentsSeparatedByCharactersInSet:whitespaceSet]; - - return [queryStrings all:^int(NSString* query) { - if (query.length == 0) return YES; - return [nameStrings any:^int(NSString* nameWord) { - NSStringCompareOptions searchOpts = NSCaseInsensitiveSearch | NSAnchoredSearch; - return [nameWord rangeOfString:query options:searchOpts].location != NSNotFound; - }]; + NSArray *queryStrings = [queryString componentsSeparatedByCharactersInSet:whitespaceSet]; + NSArray *nameStrings = [nameString componentsSeparatedByCharactersInSet:whitespaceSet]; + + return [queryStrings all:^int(NSString *query) { + if (query.length == 0) + return YES; + return [nameStrings any:^int(NSString *nameWord) { + NSStringCompareOptions searchOpts = NSCaseInsensitiveSearch | NSAnchoredSearch; + return [nameWord rangeOfString:query options:searchOpts].location != NSNotFound; + }]; }]; } -+(BOOL)phoneNumber:(PhoneNumber *)phoneNumber matchesQuery:(NSString *)queryString { ++ (BOOL)phoneNumber:(PhoneNumber *)phoneNumber matchesQuery:(NSString *)queryString { NSString *phoneNumberString = phoneNumber.localizedDescriptionForUser; - NSString *searchString = phoneNumberString.digitsOnly; - - if (queryString.length == 0) return YES; + NSString *searchString = phoneNumberString.digitsOnly; + + if (queryString.length == 0) + return YES; NSStringCompareOptions searchOpts = NSCaseInsensitiveSearch | NSAnchoredSearch; return [searchString rangeOfString:queryString options:searchOpts].location != NSNotFound; } --(NSArray*) contactsForContactIds:(NSArray *)contactIds { +- (NSArray *)contactsForContactIds:(NSArray *)contactIds { NSMutableArray *contacts = [NSMutableArray array]; for (NSNumber *favouriteId in contactIds) { Contact *contact = [self latestContactWithRecordId:favouriteId.intValue]; - + if (contact) { [contacts addObject:contact]; } @@ -429,47 +458,47 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in #pragma mark - Whisper User Management --(NSArray*) getSignalUsersFromContactsArray:(NSArray*)contacts { - return [[contacts filter:^int(Contact* contact) { - return contact.isRedPhoneContact || contact.isTextSecureContact; +- (NSArray *)getSignalUsersFromContactsArray:(NSArray *)contacts { + return [[contacts filter:^int(Contact *contact) { + return contact.isRedPhoneContact || contact.isTextSecureContact; }] sortedArrayUsingComparator:[[self class] contactComparator]]; } + (NSComparator)contactComparator { return ^NSComparisonResult(id obj1, id obj2) { - Contact *contact1 = (Contact*)obj1; - Contact *contact2 = (Contact*)obj2; - - BOOL firstNameOrdering = ABPersonGetSortOrdering() == kABPersonCompositeNameFormatFirstNameFirst?YES:NO; - - if (firstNameOrdering) { - return [contact1.firstName caseInsensitiveCompare:contact2.firstName]; - } else { - return [contact1.lastName caseInsensitiveCompare:contact2.lastName]; - }; + Contact *contact1 = (Contact *)obj1; + Contact *contact2 = (Contact *)obj2; + + BOOL firstNameOrdering = ABPersonGetSortOrdering() == kABPersonCompositeNameFormatFirstNameFirst ? YES : NO; + + if (firstNameOrdering) { + return [contact1.firstName caseInsensitiveCompare:contact2.firstName]; + } else { + return [contact1.lastName caseInsensitiveCompare:contact2.lastName]; + }; }; } --(NSArray*) signalContacts { +- (NSArray *)signalContacts { return [self getSignalUsersFromContactsArray:self.allContacts]; } --(NSArray*) textSecureContacts { - return [[self.allContacts filter:^int(Contact* contact) { - return [contact isTextSecureContact]; +- (NSArray *)textSecureContacts { + return [[self.allContacts filter:^int(Contact *contact) { + return [contact isTextSecureContact]; }] sortedArrayUsingComparator:[[self class] contactComparator]]; } --(NSArray*) getNewItemsFrom:(NSArray*) newArray comparedTo:(NSArray*) oldArray { +- (NSArray *)getNewItemsFrom:(NSArray *)newArray comparedTo:(NSArray *)oldArray { NSMutableSet *newSet = [NSMutableSet setWithArray:newArray]; - NSSet *oldSet = [NSSet setWithArray:oldArray]; - + NSSet *oldSet = [NSSet setWithArray:oldArray]; + [newSet minusSet:oldSet]; return newSet.allObjects; } -- (NSString*)nameStringForPhoneIdentifier:(NSString*)identifier{ +- (NSString *)nameStringForPhoneIdentifier:(NSString *)identifier { for (Contact *contact in self.allContacts) { for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) { if ([phoneNumber.toE164 isEqualToString:identifier]) { @@ -480,7 +509,7 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in return nil; } -- (UIImage*)imageForPhoneIdentifier:(NSString*)identifier{ +- (UIImage *)imageForPhoneIdentifier:(NSString *)identifier { for (Contact *contact in self.allContacts) { for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) { if ([phoneNumber.toE164 isEqualToString:identifier]) { diff --git a/Signal/src/crypto/CryptoTools.h b/Signal/src/crypto/CryptoTools.h index 6c0270cdc..0a8c3c818 100644 --- a/Signal/src/crypto/CryptoTools.h +++ b/Signal/src/crypto/CryptoTools.h @@ -6,38 +6,39 @@ @interface CryptoTools : NSObject /// Returns a secure random 16-bit unsigned integer. -+(uint16_t)generateSecureRandomUInt16; ++ (uint16_t)generateSecureRandomUInt16; /// Returns a secure random 32-bit unsigned integer. -+(uint32_t)generateSecureRandomUInt32; ++ (uint32_t)generateSecureRandomUInt32; /// Returns data composed of 'length' cryptographically unpredictable bytes sampled uniformly from [0, 256). -+(NSData*)generateSecureRandomData:(NSUInteger)length; ++ (NSData *)generateSecureRandomData:(NSUInteger)length; /// Returns the token included as part of HTTP OTP authentication. -+(NSString*) computeOtpWithPassword:(NSString*)password andCounter:(int64_t)counter; ++ (NSString *)computeOtpWithPassword:(NSString *)password andCounter:(int64_t)counter; @end @interface NSData (CryptoTools) --(NSData*)hashWithSha256; +- (NSData *)hashWithSha256; --(NSData*)hmacWithSha1WithKey:(NSData*)key; --(NSData*)hmacWithSha256WithKey:(NSData*)key; +- (NSData *)hmacWithSha1WithKey:(NSData *)key; +- (NSData *)hmacWithSha256WithKey:(NSData *)key; --(NSData*)encryptWithAesInCipherFeedbackModeWithKey:(NSData*)key andIv:(NSData*)iv; --(NSData*)decryptWithAesInCipherFeedbackModeWithKey:(NSData*)key andIv:(NSData*)iv; +- (NSData *)encryptWithAesInCipherFeedbackModeWithKey:(NSData *)key andIv:(NSData *)iv; +- (NSData *)decryptWithAesInCipherFeedbackModeWithKey:(NSData *)key andIv:(NSData *)iv; --(NSData*)encryptWithAesInCipherBlockChainingModeWithPkcs7PaddingWithKey:(NSData*)key andIv:(NSData*)iv; --(NSData*)decryptWithAesInCipherBlockChainingModeWithPkcs7PaddingWithKey:(NSData*)key andIv:(NSData*)iv; +- (NSData *)encryptWithAesInCipherBlockChainingModeWithPkcs7PaddingWithKey:(NSData *)key andIv:(NSData *)iv; +- (NSData *)decryptWithAesInCipherBlockChainingModeWithPkcs7PaddingWithKey:(NSData *)key andIv:(NSData *)iv; --(NSData*)encryptWithAesInCounterModeWithKey:(NSData*)key andIv:(NSData*)iv; --(NSData*)decryptWithAesInCounterModeWithKey:(NSData*)key andIv:(NSData*)iv; +- (NSData *)encryptWithAesInCounterModeWithKey:(NSData *)key andIv:(NSData *)iv; +- (NSData *)decryptWithAesInCounterModeWithKey:(NSData *)key andIv:(NSData *)iv; /// Determines if two data vectors contain the same information. -/// Avoids short-circuiting or data-dependent branches, so that early returns can't be used to infer where the difference is. +/// Avoids short-circuiting or data-dependent branches, so that early returns can't be used to infer where the +/// difference is. /// Returns early if data is of different length. --(bool)isEqualToData_TimingSafe:(NSData*)other; +- (bool)isEqualToData_TimingSafe:(NSData *)other; @end diff --git a/Signal/src/crypto/CryptoTools.m b/Signal/src/crypto/CryptoTools.m index 85d168b32..9bd3f6e26 100644 --- a/Signal/src/crypto/CryptoTools.m +++ b/Signal/src/crypto/CryptoTools.m @@ -8,28 +8,28 @@ @implementation CryptoTools -+(NSData*)generateSecureRandomData:(NSUInteger)length { - NSMutableData* d = [NSMutableData dataWithLength:length]; - int err = SecRandomCopyBytes(kSecRandomDefault, length, [d mutableBytes]); ++ (NSData *)generateSecureRandomData:(NSUInteger)length { + NSMutableData *d = [NSMutableData dataWithLength:length]; + int err = SecRandomCopyBytes(kSecRandomDefault, length, [d mutableBytes]); if (err != 0) { [SecurityFailure raise:@"SecRandomCopyBytes failed"]; } return d; } -+(uint16_t)generateSecureRandomUInt16 { ++ (uint16_t)generateSecureRandomUInt16 { return [[self generateSecureRandomData:sizeof(uint16_t)] bigEndianUInt16At:0]; } -+(uint32_t)generateSecureRandomUInt32 { ++ (uint32_t)generateSecureRandomUInt32 { return [[self generateSecureRandomData:sizeof(uint32_t)] bigEndianUInt32At:0]; } -+(NSString*) computeOtpWithPassword:(NSString*)password andCounter:(int64_t)counter { - require(password != nil); - - NSData* d = [[@(counter) stringValue] encodedAsUtf8]; - NSData* h = [d hmacWithSha1WithKey:password.encodedAsUtf8]; ++ (NSString *)computeOtpWithPassword:(NSString *)password andCounter:(int64_t)counter { + ows_require(password != nil); + + NSData *d = [[@(counter) stringValue] encodedAsUtf8]; + NSData *h = [d hmacWithSha1WithKey:password.encodedAsUtf8]; return h.encodedAsBase64; } @@ -37,41 +37,43 @@ @implementation NSData (CryptoTools) --(NSData*)hmacWithSha1WithKey:(NSData*)key { +- (NSData *)hmacWithSha1WithKey:(NSData *)key { return [EvpMessageDigest hmacUsingSha1Data:self withKey:key]; } --(NSData*)hmacWithSha256WithKey:(NSData*)key { +- (NSData *)hmacWithSha256WithKey:(NSData *)key { return [EvpMessageDigest hmacUsingSha256Data:self withKey:key]; } --(NSData*)encryptWithAesInCipherFeedbackModeWithKey:(NSData*)key andIv:(NSData*)iv { +- (NSData *)encryptWithAesInCipherFeedbackModeWithKey:(NSData *)key andIv:(NSData *)iv { return [EvpSymetricUtil encryptMessage:self usingAes128WithCfbAndKey:key andIv:iv]; } --(NSData*)encryptWithAesInCipherBlockChainingModeWithPkcs7PaddingWithKey:(NSData*)key andIv:(NSData*)iv { +- (NSData *)encryptWithAesInCipherBlockChainingModeWithPkcs7PaddingWithKey:(NSData *)key andIv:(NSData *)iv { return [EvpSymetricUtil encryptMessage:self usingAes128WithCbcAndPaddingAndKey:key andIv:iv]; } --(NSData*)encryptWithAesInCounterModeWithKey:(NSData*)key andIv:(NSData*)iv { +- (NSData *)encryptWithAesInCounterModeWithKey:(NSData *)key andIv:(NSData *)iv { return [EvpSymetricUtil encryptMessage:self usingAes128InCounterModeAndKey:key andIv:iv]; } --(NSData*)decryptWithAesInCipherFeedbackModeWithKey:(NSData*)key andIv:(NSData*)iv { +- (NSData *)decryptWithAesInCipherFeedbackModeWithKey:(NSData *)key andIv:(NSData *)iv { return [EvpSymetricUtil decryptMessage:self usingAes128WithCfbAndKey:key andIv:iv]; } --(NSData*)decryptWithAesInCipherBlockChainingModeWithPkcs7PaddingWithKey:(NSData*)key andIv:(NSData*)iv { +- (NSData *)decryptWithAesInCipherBlockChainingModeWithPkcs7PaddingWithKey:(NSData *)key andIv:(NSData *)iv { return [EvpSymetricUtil decryptMessage:self usingAes128WithCbcAndPaddingAndKey:key andIv:iv]; } --(NSData*)decryptWithAesInCounterModeWithKey:(NSData*)key andIv:(NSData*)iv { +- (NSData *)decryptWithAesInCounterModeWithKey:(NSData *)key andIv:(NSData *)iv { return [EvpSymetricUtil decryptMessage:self usingAes128InCounterModeAndKey:key andIv:iv]; } --(NSData*)hashWithSha256 { +- (NSData *)hashWithSha256 { return [EvpMessageDigest hashWithSha256:self]; } --(bool)isEqualToData_TimingSafe:(NSData*)other { - if (other == nil) return false; +- (bool)isEqualToData_TimingSafe:(NSData *)other { + if (other == nil) + return false; NSUInteger n = self.length; - if (other.length != n) return false; + if (other.length != n) + return false; bool equal = true; for (NSUInteger i = 0; i < n; i++) equal &= [self uint8At:i] == [other uint8At:i]; diff --git a/Signal/src/crypto/EvpMessageDigest.h b/Signal/src/crypto/EvpMessageDigest.h index 0e51da63a..145cdcba9 100644 --- a/Signal/src/crypto/EvpMessageDigest.h +++ b/Signal/src/crypto/EvpMessageDigest.h @@ -4,7 +4,7 @@ @interface EvpMessageDigest : NSObject -+(NSData*) hashWithSha256:(NSData*) data; -+(NSData*) hmacUsingSha1Data:(NSData*) data withKey:(NSData*) key; -+(NSData*) hmacUsingSha256Data:(NSData*) data withKey:(NSData*) key; ++ (NSData *)hashWithSha256:(NSData *)data; ++ (NSData *)hmacUsingSha1Data:(NSData *)data withKey:(NSData *)key; ++ (NSData *)hmacUsingSha256Data:(NSData *)data withKey:(NSData *)key; @end diff --git a/Signal/src/crypto/EvpMessageDigest.m b/Signal/src/crypto/EvpMessageDigest.m index b959d3196..d9fb5ec19 100644 --- a/Signal/src/crypto/EvpMessageDigest.m +++ b/Signal/src/crypto/EvpMessageDigest.m @@ -9,44 +9,41 @@ @implementation EvpMessageDigest -+(NSData*) hash:(NSData*) data withDigest:(const EVP_MD*) digest { ++ (NSData *)hash:(NSData *)data withDigest:(const EVP_MD *)digest { NSUInteger expectedDigestLength = [NumberUtil assertConvertIntToNSUInteger:EVP_MD_size(digest)]; - unsigned int digestLength = 0; + unsigned int digestLength = 0; unsigned char digestBuffer[expectedDigestLength]; - - EVP_MD_CTX* ctx = EVP_MD_CTX_create(); - require(NULL != ctx); + + EVP_MD_CTX *ctx = EVP_MD_CTX_create(); + ows_require(NULL != ctx); @try { RAISE_EXCEPTION_ON_FAILURE(EVP_DigestInit_ex(ctx, digest, NULL)); RAISE_EXCEPTION_ON_FAILURE(EVP_DigestUpdate(ctx, data.bytes, data.length)); RAISE_EXCEPTION_ON_FAILURE(EVP_DigestFinal_ex(ctx, digestBuffer, &digestLength)); - } - @finally { + } @finally { EVP_MD_CTX_destroy(ctx); } - - require(digestLength == expectedDigestLength); + + ows_require(digestLength == expectedDigestLength); return [NSData dataWithBytes:digestBuffer length:digestLength]; } -+(NSData*) hmacWithData:(NSData*) data andKey:(NSData*) key andDigest:(const EVP_MD*) md{ ++ (NSData *)hmacWithData:(NSData *)data andKey:(NSData *)key andDigest:(const EVP_MD *)md { NSUInteger digestLength = [NumberUtil assertConvertIntToNSUInteger:EVP_MD_size(md)]; - - unsigned char* digest = HMAC(md, - [key bytes], [NumberUtil assertConvertNSUIntegerToInt:key.length], - [data bytes], data.length, - NULL, NULL); - - return [NSData dataWithBytes:digest length:digestLength]; + + unsigned char *digest = HMAC( + md, [key bytes], [NumberUtil assertConvertNSUIntegerToInt:key.length], [data bytes], data.length, NULL, NULL); + + return [NSData dataWithBytes:digest length:digestLength]; } -+(NSData*) hashWithSha256:(NSData *)data { ++ (NSData *)hashWithSha256:(NSData *)data { return [self hash:data withDigest:EVP_sha256()]; } -+(NSData*) hmacUsingSha1Data:(NSData*) data withKey:(NSData*) key { ++ (NSData *)hmacUsingSha1Data:(NSData *)data withKey:(NSData *)key { return [self hmacWithData:data andKey:key andDigest:EVP_sha1()]; } -+(NSData*) hmacUsingSha256Data:(NSData*) data withKey:(NSData*) key{ ++ (NSData *)hmacUsingSha256Data:(NSData *)data withKey:(NSData *)key { return [self hmacWithData:data andKey:key andDigest:EVP_sha256()]; } @end diff --git a/Signal/src/crypto/EvpSymetricUtil.h b/Signal/src/crypto/EvpSymetricUtil.h index 6896995b9..8077fa2dc 100644 --- a/Signal/src/crypto/EvpSymetricUtil.h +++ b/Signal/src/crypto/EvpSymetricUtil.h @@ -5,12 +5,12 @@ @interface EvpSymetricUtil : NSObject -+(NSData*) encryptMessage:(NSData*) message usingAes128WithCbcAndPaddingAndKey:(NSData*) key andIv:(NSData*) iv; -+(NSData*) decryptMessage:(NSData*) message usingAes128WithCbcAndPaddingAndKey:(NSData*) key andIv:(NSData*) iv; ++ (NSData *)encryptMessage:(NSData *)message usingAes128WithCbcAndPaddingAndKey:(NSData *)key andIv:(NSData *)iv; ++ (NSData *)decryptMessage:(NSData *)message usingAes128WithCbcAndPaddingAndKey:(NSData *)key andIv:(NSData *)iv; -+(NSData*) encryptMessage:(NSData*) message usingAes128WithCfbAndKey:(NSData*) key andIv:(NSData*) iv; -+(NSData*) decryptMessage:(NSData*) message usingAes128WithCfbAndKey:(NSData*) key andIv:(NSData*) iv; ++ (NSData *)encryptMessage:(NSData *)message usingAes128WithCfbAndKey:(NSData *)key andIv:(NSData *)iv; ++ (NSData *)decryptMessage:(NSData *)message usingAes128WithCfbAndKey:(NSData *)key andIv:(NSData *)iv; -+(NSData*) encryptMessage:(NSData *)message usingAes128InCounterModeAndKey:(NSData *)key andIv:(NSData *)iv; -+(NSData*) decryptMessage:(NSData *)message usingAes128InCounterModeAndKey:(NSData *)key andIv:(NSData *)iv; ++ (NSData *)encryptMessage:(NSData *)message usingAes128InCounterModeAndKey:(NSData *)key andIv:(NSData *)iv; ++ (NSData *)decryptMessage:(NSData *)message usingAes128InCounterModeAndKey:(NSData *)key andIv:(NSData *)iv; @end diff --git a/Signal/src/crypto/EvpSymetricUtil.m b/Signal/src/crypto/EvpSymetricUtil.m index 006b2174b..5a21db5fc 100644 --- a/Signal/src/crypto/EvpSymetricUtil.m +++ b/Signal/src/crypto/EvpSymetricUtil.m @@ -6,94 +6,104 @@ @implementation EvpSymetricUtil -+(NSData*) encryptMessage:(NSData *)message usingCipher:(const EVP_CIPHER*) cipher andKey:(NSData *)key andIv:(NSData *)iv { ++ (NSData *)encryptMessage:(NSData *)message + usingCipher:(const EVP_CIPHER *)cipher + andKey:(NSData *)key + andIv:(NSData *)iv { [self assertKey:key andIv:iv lengthsAgainstCipher:cipher]; - - int messageLength = [NumberUtil assertConvertNSUIntegerToInt:message.length]; - int cipherBlockSize = EVP_CIPHER_block_size(cipher); - int cipherTextLength = 0; - int paddingLength = 0; - int bufferLength = ( messageLength + cipherBlockSize - 1); + int messageLength = [NumberUtil assertConvertNSUIntegerToInt:message.length]; + int cipherBlockSize = EVP_CIPHER_block_size(cipher); + int cipherTextLength = 0; + int paddingLength = 0; + + int bufferLength = (messageLength + cipherBlockSize - 1); unsigned char cipherText[bufferLength]; - - EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); - if(!ctx) { RAISE_EXCEPTION;} - + + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + if (!ctx) { + RAISE_EXCEPTION; + } + @try { - RAISE_EXCEPTION_ON_FAILURE( EVP_EncryptInit_ex(ctx, cipher, NULL,[key bytes], [iv bytes])) - RAISE_EXCEPTION_ON_FAILURE( EVP_EncryptUpdate(ctx, cipherText, &cipherTextLength, [message bytes], messageLength)) - RAISE_EXCEPTION_ON_FAILURE( EVP_EncryptFinal_ex(ctx, cipherText + cipherTextLength, &paddingLength)) - + RAISE_EXCEPTION_ON_FAILURE(EVP_EncryptInit_ex(ctx, cipher, NULL, [key bytes], [iv bytes])) + RAISE_EXCEPTION_ON_FAILURE( + EVP_EncryptUpdate(ctx, cipherText, &cipherTextLength, [message bytes], messageLength)) + RAISE_EXCEPTION_ON_FAILURE(EVP_EncryptFinal_ex(ctx, cipherText + cipherTextLength, &paddingLength)) + cipherTextLength += paddingLength; - } - @finally { + } @finally { EVP_CIPHER_CTX_free(ctx); } - - require(cipherTextLength <= bufferLength); - return [NSData dataWithBytes:cipherText length: [NumberUtil assertConvertIntToNSUInteger:cipherTextLength]]; + ows_require(cipherTextLength <= bufferLength); + + return [NSData dataWithBytes:cipherText length:[NumberUtil assertConvertIntToNSUInteger:cipherTextLength]]; } -+(void) assertKey:(NSData*) key andIv:(NSData*) iv lengthsAgainstCipher:(const EVP_CIPHER*) cipher { - int cipherKeyLength = EVP_CIPHER_key_length(cipher); - int cipherIvLength = EVP_CIPHER_iv_length(cipher); - - require(key.length == [NumberUtil assertConvertIntToNSUInteger:cipherKeyLength]); - require(iv.length == [NumberUtil assertConvertIntToNSUInteger:cipherIvLength]); ++ (void)assertKey:(NSData *)key andIv:(NSData *)iv lengthsAgainstCipher:(const EVP_CIPHER *)cipher { + int cipherKeyLength = EVP_CIPHER_key_length(cipher); + int cipherIvLength = EVP_CIPHER_iv_length(cipher); + + ows_require(key.length == [NumberUtil assertConvertIntToNSUInteger:cipherKeyLength]); + ows_require(iv.length == [NumberUtil assertConvertIntToNSUInteger:cipherIvLength]); } -+(NSData*) decryptMessage:(NSData *)cipherText usingCipher:(const EVP_CIPHER*) cipher andKey:(NSData *)key andIv:(NSData *)iv { - ++ (NSData *)decryptMessage:(NSData *)cipherText + usingCipher:(const EVP_CIPHER *)cipher + andKey:(NSData *)key + andIv:(NSData *)iv { [self assertKey:key andIv:iv lengthsAgainstCipher:cipher]; - - int cipherTextLength = [NumberUtil assertConvertNSUIntegerToInt:cipherText.length]; - int cipherBlockSize = EVP_CIPHER_block_size(cipher); - int plainTextLength = 0; - int paddingLength = 0; - int bufferLength = ( cipherTextLength + cipherBlockSize); + int cipherTextLength = [NumberUtil assertConvertNSUIntegerToInt:cipherText.length]; + int cipherBlockSize = EVP_CIPHER_block_size(cipher); + int plainTextLength = 0; + int paddingLength = 0; + + int bufferLength = (cipherTextLength + cipherBlockSize); unsigned char plainText[bufferLength]; - - EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); - if(!ctx) { RAISE_EXCEPTION;} + + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + if (!ctx) { + RAISE_EXCEPTION; + } @try { - RAISE_EXCEPTION_ON_FAILURE(EVP_DecryptInit_ex( ctx, cipher, NULL, [key bytes], [iv bytes])) - RAISE_EXCEPTION_ON_FAILURE(EVP_DecryptUpdate( ctx, plainText, &plainTextLength, [cipherText bytes], cipherTextLength)) - RAISE_EXCEPTION_ON_FAILURE(EVP_DecryptFinal_ex( ctx, plainText + plainTextLength, &paddingLength)) - + RAISE_EXCEPTION_ON_FAILURE(EVP_DecryptInit_ex(ctx, cipher, NULL, [key bytes], [iv bytes])) + RAISE_EXCEPTION_ON_FAILURE( + EVP_DecryptUpdate(ctx, plainText, &plainTextLength, [cipherText bytes], cipherTextLength)) + RAISE_EXCEPTION_ON_FAILURE(EVP_DecryptFinal_ex(ctx, plainText + plainTextLength, &paddingLength)) + plainTextLength += paddingLength; - } - @finally { + } @finally { EVP_CIPHER_CTX_free(ctx); } - - require(plainTextLength <= bufferLength); - - return [NSData dataWithBytes:plainText length: [NumberUtil assertConvertIntToNSUInteger:plainTextLength]]; + + ows_require(plainTextLength <= bufferLength); + + return [NSData dataWithBytes:plainText length:[NumberUtil assertConvertIntToNSUInteger:plainTextLength]]; } -+(NSData*) encryptMessage:(NSData*) message usingAes128WithCbcAndPaddingAndKey:(NSData*) key andIv:(NSData*) iv { ++ (NSData *)encryptMessage:(NSData *)message usingAes128WithCbcAndPaddingAndKey:(NSData *)key andIv:(NSData *)iv { return [self encryptMessage:message usingCipher:EVP_aes_128_cbc() andKey:key andIv:iv]; } -+(NSData*) decryptMessage:(NSData*) message usingAes128WithCbcAndPaddingAndKey:(NSData*) key andIv:(NSData*) iv { ++ (NSData *)decryptMessage:(NSData *)message usingAes128WithCbcAndPaddingAndKey:(NSData *)key andIv:(NSData *)iv { return [self decryptMessage:message usingCipher:EVP_aes_128_cbc() andKey:key andIv:iv]; } -+(NSData*) encryptMessage:(NSData*) message usingAes128WithCfbAndKey:(NSData*) key andIv:(NSData*) iv { ++ (NSData *)encryptMessage:(NSData *)message usingAes128WithCfbAndKey:(NSData *)key andIv:(NSData *)iv { return [self encryptMessage:message usingCipher:EVP_aes_128_cfb128() andKey:key andIv:iv]; } -+(NSData*) decryptMessage:(NSData*) message usingAes128WithCfbAndKey:(NSData*) key andIv:(NSData*) iv { ++ (NSData *)decryptMessage:(NSData *)message usingAes128WithCfbAndKey:(NSData *)key andIv:(NSData *)iv { return [self decryptMessage:message usingCipher:EVP_aes_128_cfb128() andKey:key andIv:iv]; } -+(NSData*) encryptMessage:(NSData*) message usingAes128InCounterModeAndKey:(NSData*) key andIv:(NSData*) iv { ++ (NSData *)encryptMessage:(NSData *)message usingAes128InCounterModeAndKey:(NSData *)key andIv:(NSData *)iv { return [self encryptMessage:message usingCipher:EVP_aes_128_ctr() andKey:key andIv:iv]; } -+(NSData*) decryptMessage:(NSData*) message usingAes128InCounterModeAndKey:(NSData*) key andIv:(NSData*) iv { ++ (NSData *)decryptMessage:(NSData *)message usingAes128InCounterModeAndKey:(NSData *)key andIv:(NSData *)iv { return [self decryptMessage:message usingCipher:EVP_aes_128_ctr() andKey:key andIv:iv]; } -@end; +@end +; diff --git a/Signal/src/crypto/EvpUtil.h b/Signal/src/crypto/EvpUtil.h index 2b6165f0e..ceb3993e9 100644 --- a/Signal/src/crypto/EvpUtil.h +++ b/Signal/src/crypto/EvpUtil.h @@ -1,4 +1,7 @@ #import -#define RAISE_EXCEPTION [NSException raise:@"OPENSSL_Exception" format:@"Line:%d File:%s ", __LINE__ , __FILE__] -#define RAISE_EXCEPTION_ON_FAILURE(X) if( 1 != X){ RAISE_EXCEPTION;} +#define RAISE_EXCEPTION [NSException raise:@"OPENSSL_Exception" format:@"Line:%d File:%s ", __LINE__, __FILE__] +#define RAISE_EXCEPTION_ON_FAILURE(X) \ + if (1 != X) { \ + RAISE_EXCEPTION; \ + } diff --git a/Signal/src/environment/DebugLogger.h b/Signal/src/environment/DebugLogger.h index c0c4ab16b..b3265512b 100644 --- a/Signal/src/environment/DebugLogger.h +++ b/Signal/src/environment/DebugLogger.h @@ -12,7 +12,7 @@ @interface DebugLogger : NSObject -MacrosSingletonInterface ++ (instancetype)sharedLogger; - (void)enableFileLogging; @@ -22,7 +22,7 @@ MacrosSingletonInterface - (void)wipeLogs; -- (NSString*)logsDirectory; +- (NSString *)logsDirectory; @property (nonatomic) DDFileLogger *fileLogger; diff --git a/Signal/src/environment/DebugLogger.m b/Signal/src/environment/DebugLogger.m index 7f679fa37..9786f00b7 100644 --- a/Signal/src/environment/DebugLogger.m +++ b/Signal/src/environment/DebugLogger.m @@ -18,61 +18,73 @@ @implementation DebugLogger -MacrosSingletonImplemention ++ (instancetype)sharedLogger { + static DebugLogger *sharedManager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedManager = [self new]; + }); + return sharedManager; +} -- (void)enableFileLogging{ - self.fileLogger = [[DDFileLogger alloc] init]; //Logging to file, because it's in the Cache folder, they are not uploaded in iTunes/iCloud backups. - self.fileLogger.rollingFrequency = 60 * 60 * 24; // 24 hour rolling. - self.fileLogger.logFileManager.maximumNumberOfLogFiles = 3; // Keep three days of logs. + +- (void)enableFileLogging { + self.fileLogger = [[DDFileLogger alloc] + init]; // Logging to file, because it's in the Cache folder, they are not uploaded in iTunes/iCloud backups. + self.fileLogger.rollingFrequency = 60 * 60 * 24; // 24 hour rolling. + self.fileLogger.logFileManager.maximumNumberOfLogFiles = 3; // Keep three days of logs. [DDLog addLogger:self.fileLogger]; } -- (void)disableFileLogging{ +- (void)disableFileLogging { [DDLog removeLogger:self.fileLogger]; self.fileLogger = nil; } -- (void)enableTTYLogging{ +- (void)enableTTYLogging { [DDLog addLogger:DDTTYLogger.sharedInstance]; } -- (void)wipeLogs{ - BOOL reenableLogging = (self.fileLogger?YES:NO); +- (void)wipeLogs { + BOOL reenableLogging = (self.fileLogger ? YES : NO); NSError *error; NSArray *logsPath = self.fileLogger.logFileManager.unsortedLogFilePaths; - + if (reenableLogging) { [self disableFileLogging]; } - - for (NSUInteger i = 0; i < logsPath.count; i++) { + + for (NSUInteger i = 0; i < logsPath.count; i++) { [[NSFileManager defaultManager] removeItemAtPath:[logsPath objectAtIndex:i] error:&error]; } - + if (error) { DDLogError(@"Logs couldn't be removed. %@", error.description); } - + if (reenableLogging) { [self enableFileLogging]; } } -- (NSString*)logsDirectory{ - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); - NSString *baseDir = ([paths count] > 0) ? [paths objectAtIndex:0] : nil; +- (NSString *)logsDirectory { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); + NSString *baseDir = ([paths count] > 0) ? [paths objectAtIndex:0] : nil; NSString *logsDirectory = [baseDir stringByAppendingPathComponent:@"Logs"]; - + if (![[NSFileManager defaultManager] fileExistsAtPath:logsDirectory]) { NSError *error; - - [[NSFileManager defaultManager] createDirectoryAtPath:logsDirectory withIntermediateDirectories:YES attributes:nil error:nil]; - + + [[NSFileManager defaultManager] createDirectoryAtPath:logsDirectory + withIntermediateDirectories:YES + attributes:nil + error:nil]; + if (error) { DDLogError(@"Log folder couldn't be created. %@", error.description); } } - + return logsDirectory; } diff --git a/Signal/src/environment/Environment.h b/Signal/src/environment/Environment.h index 1665283c7..b6efe99a0 100644 --- a/Signal/src/environment/Environment.h +++ b/Signal/src/environment/Environment.h @@ -1,12 +1,12 @@ #import #import "Logging.h" -#import "PropertyListPreferences.h" #import "PacketHandler.h" +#import "PropertyListPreferences.h" #import "SecureEndPoint.h" #import "TSGroupModel.h" #import "TSStorageHeaders.h" -static NSString* const kCallSegue = @"2.0_6.0_Call_Segue"; +static NSString *const kCallSegue = @"2.0_6.0_Call_Segue"; /** * @@ -20,7 +20,8 @@ static NSString* const kCallSegue = @"2.0_6.0_Call_Segue"; #define ENVIRONMENT_TESTING_OPTION_LOSE_CONF_ACK_ON_PURPOSE @"LoseConfAck" #define ENVIRONMENT_TESTING_OPTION_ALLOW_NETWORK_STREAM_TO_NON_SECURE_END_POINTS @"AllowTcpWithoutTls" -#define ENVIRONMENT_LEGACY_OPTION_RTP_PADDING_BIT_IMPLIES_EXTENSION_BIT_AND_TWELVE_EXTRA_ZERO_BYTES_IN_HEADER @"LegacyAndroidInterop_1" +#define ENVIRONMENT_LEGACY_OPTION_RTP_PADDING_BIT_IMPLIES_EXTENSION_BIT_AND_TWELVE_EXTRA_ZERO_BYTES_IN_HEADER \ + @"LegacyAndroidInterop_1" #define TESTING_OPTION_USE_DH_FOR_HANDSHAKE @"DhKeyAgreementOnly" @class RecentCallManager; @@ -31,62 +32,59 @@ static NSString* const kCallSegue = @"2.0_6.0_Call_Segue"; @interface Environment : NSObject @property (nonatomic, readonly) in_port_t serverPort; @property (nonatomic, readonly) id logging; -@property (nonatomic, readonly) SecureEndPoint* masterServerSecureEndPoint; -@property (nonatomic, readonly) NSString* defaultRelayName; -@property (nonatomic, readonly) Certificate* certificate; -@property (nonatomic, readonly) NSString* relayServerHostNameSuffix; -@property (nonatomic, readonly) NSArray* keyAgreementProtocolsInDescendingPriority; +@property (nonatomic, readonly) SecureEndPoint *masterServerSecureEndPoint; +@property (nonatomic, readonly) NSString *defaultRelayName; +@property (nonatomic, readonly) Certificate *certificate; +@property (nonatomic, readonly) NSString *relayServerHostNameSuffix; +@property (nonatomic, readonly) NSArray *keyAgreementProtocolsInDescendingPriority; @property (nonatomic, readonly) ErrorHandlerBlock errorNoter; -@property (nonatomic, readonly) NSString* currentRegionCodeForPhoneNumbers; -@property (nonatomic, readonly) PhoneManager* phoneManager; +@property (nonatomic, readonly) PhoneManager *phoneManager; @property (nonatomic, readonly) RecentCallManager *recentCallManager; -@property (nonatomic, readonly) NSArray* testingAndLegacyOptions; -@property (nonatomic, readonly) NSData* zrtpClientId; -@property (nonatomic, readonly) NSData* zrtpVersionId; +@property (nonatomic, readonly) NSArray *testingAndLegacyOptions; +@property (nonatomic, readonly) NSData *zrtpClientId; +@property (nonatomic, readonly) NSData *zrtpVersionId; @property (nonatomic, readonly) ContactsManager *contactsManager; @property (nonatomic, readonly) SignalsViewController *signalsViewController; @property (nonatomic, readonly, weak) UINavigationController *signUpFlowNavigationController; -+(SecureEndPoint*) getMasterServerSecureEndPoint; -+(SecureEndPoint*) getSecureEndPointToDefaultRelayServer; -+(SecureEndPoint*) getSecureEndPointToSignalingServerNamed:(NSString*)name; ++ (SecureEndPoint *)getMasterServerSecureEndPoint; ++ (SecureEndPoint *)getSecureEndPointToDefaultRelayServer; ++ (SecureEndPoint *)getSecureEndPointToSignalingServerNamed:(NSString *)name; -+(Environment*) environmentWithLogging:(id)logging - andErrorNoter:(ErrorHandlerBlock)errorNoter - andServerPort:(in_port_t)serverPort - andMasterServerHostName:(NSString*)masterServerHostName - andDefaultRelayName:(NSString*)defaultRelayName - andRelayServerHostNameSuffix:(NSString*)relayServerHostNameSuffix - andCertificate:(Certificate*)certificate - andCurrentRegionCodeForPhoneNumbers:(NSString*)currentRegionCodeForPhoneNumbers - andSupportedKeyAgreementProtocols:(NSArray*)keyAgreementProtocolsInDescendingPriority - andPhoneManager:(PhoneManager*)phoneManager - andRecentCallManager:(RecentCallManager *)recentCallManager - andTestingAndLegacyOptions:(NSArray*)testingAndLegacyOptions - andZrtpClientId:(NSData*)zrtpClientId - andZrtpVersionId:(NSData*)zrtpVersionId - andContactsManager:(ContactsManager *)contactsManager; ++ (Environment *)environmentWithLogging:(id)logging + andErrorNoter:(ErrorHandlerBlock)errorNoter + andServerPort:(in_port_t)serverPort + andMasterServerHostName:(NSString *)masterServerHostName + andDefaultRelayName:(NSString *)defaultRelayName + andRelayServerHostNameSuffix:(NSString *)relayServerHostNameSuffix + andCertificate:(Certificate *)certificate + andSupportedKeyAgreementProtocols:(NSArray *)keyAgreementProtocolsInDescendingPriority + andPhoneManager:(PhoneManager *)phoneManager + andRecentCallManager:(RecentCallManager *)recentCallManager + andTestingAndLegacyOptions:(NSArray *)testingAndLegacyOptions + andZrtpClientId:(NSData *)zrtpClientId + andZrtpVersionId:(NSData *)zrtpVersionId + andContactsManager:(ContactsManager *)contactsManager; -+(Environment*) getCurrent; -+(void) setCurrent:(Environment*)curEnvironment; -+(id) logging; -+(NSString*) relayServerNameToHostName:(NSString*)name; -+(ErrorHandlerBlock) errorNoter; -+(NSString*) currentRegionCodeForPhoneNumbers; -+(bool) hasEnabledTestingOrLegacyOption:(NSString*)flag; -+(PhoneManager*) phoneManager; ++ (Environment *)getCurrent; ++ (void)setCurrent:(Environment *)curEnvironment; ++ (id)logging; ++ (NSString *)relayServerNameToHostName:(NSString *)name; ++ (ErrorHandlerBlock)errorNoter; ++ (bool)hasEnabledTestingOrLegacyOption:(NSString *)flag; ++ (PhoneManager *)phoneManager; -+(PropertyListPreferences*)preferences; ++ (PropertyListPreferences *)preferences; -+(BOOL)isRedPhoneRegistered; -+(void)resetAppData; ++ (BOOL)isRedPhoneRegistered; ++ (void)resetAppData; - (void)initCallListener; - (void)setSignalsViewController:(SignalsViewController *)signalsViewController; - (void)setSignUpFlowNavigationController:(UINavigationController *)signUpFlowNavigationController; -+ (void)messageThreadId:(NSString*)threadId; -+ (void)messageIdentifier:(NSString*)identifier withCompose:(BOOL)compose; -+ (void)messageGroupModel:(TSGroupModel*)model withCompose:(BOOL)compose; ++ (void)messageThreadId:(NSString *)threadId; ++ (void)messageIdentifier:(NSString *)identifier withCompose:(BOOL)compose; ++ (void)messageGroupModel:(TSGroupModel *)model withCompose:(BOOL)compose; @end diff --git a/Signal/src/environment/Environment.m b/Signal/src/environment/Environment.m index d82ccb8ff..1df6c9548 100644 --- a/Signal/src/environment/Environment.m +++ b/Signal/src/environment/Environment.m @@ -1,11 +1,11 @@ +#import "Constraints.h" +#import "DH3KKeyAgreementProtocol.h" #import "DebugLogger.h" #import "Environment.h" -#import "Constraints.h" #import "FunctionalUtil.h" #import "KeyAgreementProtocol.h" -#import "DH3KKeyAgreementProtocol.h" -#import "RecentCallManager.h" #import "MessagesViewController.h" +#import "RecentCallManager.h" #import "SignalKeyingStorage.h" #import "SignalsViewController.h" #import "TSContactThread.h" @@ -13,164 +13,145 @@ #define isRegisteredUserDefaultString @"isRegistered" -static Environment* environment = nil; +static Environment *environment = nil; @implementation Environment -@synthesize testingAndLegacyOptions, -currentRegionCodeForPhoneNumbers, -errorNoter, -keyAgreementProtocolsInDescendingPriority, -logging, -masterServerSecureEndPoint, -defaultRelayName, -relayServerHostNameSuffix, -certificate, -serverPort, -zrtpClientId, -zrtpVersionId, -phoneManager, -recentCallManager, -contactsManager; +@synthesize testingAndLegacyOptions, errorNoter, keyAgreementProtocolsInDescendingPriority, logging, + masterServerSecureEndPoint, defaultRelayName, relayServerHostNameSuffix, certificate, serverPort, zrtpClientId, + zrtpVersionId, phoneManager, recentCallManager, contactsManager; -+(NSString*) currentRegionCodeForPhoneNumbers { - return self.getCurrent.currentRegionCodeForPhoneNumbers; -} - -+(Environment*) getCurrent { - require(environment != nil); ++ (Environment *)getCurrent { + NSAssert((environment != nil), @"Environment is not defined."); return environment; } -+(void) setCurrent:(Environment*)curEnvironment { ++ (void)setCurrent:(Environment *)curEnvironment { environment = curEnvironment; } -+(ErrorHandlerBlock) errorNoter { ++ (ErrorHandlerBlock)errorNoter { return self.getCurrent.errorNoter; } -+(bool) hasEnabledTestingOrLegacyOption:(NSString*)flag { ++ (bool)hasEnabledTestingOrLegacyOption:(NSString *)flag { return [self.getCurrent.testingAndLegacyOptions containsObject:flag]; } -+(NSString*) relayServerNameToHostName:(NSString*)name { - return [NSString stringWithFormat:@"%@.%@", - name, - Environment.getCurrent.relayServerHostNameSuffix]; ++ (NSString *)relayServerNameToHostName:(NSString *)name { + return [NSString stringWithFormat:@"%@.%@", name, Environment.getCurrent.relayServerHostNameSuffix]; } -+(SecureEndPoint*) getMasterServerSecureEndPoint { ++ (SecureEndPoint *)getMasterServerSecureEndPoint { return Environment.getCurrent.masterServerSecureEndPoint; } -+(SecureEndPoint*) getSecureEndPointToDefaultRelayServer { ++ (SecureEndPoint *)getSecureEndPointToDefaultRelayServer { return [Environment getSecureEndPointToSignalingServerNamed:Environment.getCurrent.defaultRelayName]; } -+(SecureEndPoint*) getSecureEndPointToSignalingServerNamed:(NSString*)name { - require(name != nil); - Environment* env = Environment.getCurrent; - - NSString* hostName = [self relayServerNameToHostName:name]; - HostNameEndPoint* location = [HostNameEndPoint hostNameEndPointWithHostName:hostName andPort:env.serverPort]; ++ (SecureEndPoint *)getSecureEndPointToSignalingServerNamed:(NSString *)name { + ows_require(name != nil); + Environment *env = Environment.getCurrent; + + NSString *hostName = [self relayServerNameToHostName:name]; + HostNameEndPoint *location = [HostNameEndPoint hostNameEndPointWithHostName:hostName andPort:env.serverPort]; return [SecureEndPoint secureEndPointForHost:location identifiedByCertificate:env.certificate]; } -+(Environment*) environmentWithLogging:(id)logging - andErrorNoter:(ErrorHandlerBlock)errorNoter - andServerPort:(in_port_t)serverPort - andMasterServerHostName:(NSString*)masterServerHostName - andDefaultRelayName:(NSString*)defaultRelayName - andRelayServerHostNameSuffix:(NSString*)relayServerHostNameSuffix - andCertificate:(Certificate*)certificate - andCurrentRegionCodeForPhoneNumbers:(NSString*)currentRegionCodeForPhoneNumbers - andSupportedKeyAgreementProtocols:(NSArray*)keyAgreementProtocolsInDescendingPriority - andPhoneManager:(PhoneManager*)phoneManager - andRecentCallManager:(RecentCallManager *)recentCallManager - andTestingAndLegacyOptions:(NSArray*)testingAndLegacyOptions - andZrtpClientId:(NSData*)zrtpClientId - andZrtpVersionId:(NSData*)zrtpVersionId - andContactsManager:(ContactsManager *)contactsManager { - - require(errorNoter != nil); - require(zrtpClientId != nil); - require(zrtpVersionId != nil); - require(testingAndLegacyOptions != nil); - require(currentRegionCodeForPhoneNumbers != nil); - require(keyAgreementProtocolsInDescendingPriority != nil); - require([keyAgreementProtocolsInDescendingPriority all:^int(id p) { - return [p conformsToProtocol:@protocol(KeyAgreementProtocol)]; ++ (Environment *)environmentWithLogging:(id)logging + andErrorNoter:(ErrorHandlerBlock)errorNoter + andServerPort:(in_port_t)serverPort + andMasterServerHostName:(NSString *)masterServerHostName + andDefaultRelayName:(NSString *)defaultRelayName + andRelayServerHostNameSuffix:(NSString *)relayServerHostNameSuffix + andCertificate:(Certificate *)certificate + andSupportedKeyAgreementProtocols:(NSArray *)keyAgreementProtocolsInDescendingPriority + andPhoneManager:(PhoneManager *)phoneManager + andRecentCallManager:(RecentCallManager *)recentCallManager + andTestingAndLegacyOptions:(NSArray *)testingAndLegacyOptions + andZrtpClientId:(NSData *)zrtpClientId + andZrtpVersionId:(NSData *)zrtpVersionId + andContactsManager:(ContactsManager *)contactsManager { + ows_require(errorNoter != nil); + ows_require(zrtpClientId != nil); + ows_require(zrtpVersionId != nil); + ows_require(testingAndLegacyOptions != nil); + ows_require(keyAgreementProtocolsInDescendingPriority != nil); + ows_require([keyAgreementProtocolsInDescendingPriority all:^int(id p) { + return [p conformsToProtocol:@protocol(KeyAgreementProtocol)]; }]); - + // must support DH3k - require([keyAgreementProtocolsInDescendingPriority any:^int(id p) { - return [p isKindOfClass:DH3KKeyAgreementProtocol.class]; + ows_require([keyAgreementProtocolsInDescendingPriority any:^int(id p) { + return [p isKindOfClass:DH3KKeyAgreementProtocol.class]; }]); - - Environment* e = [Environment new]; - e->errorNoter = errorNoter; - e->logging = logging; - e->testingAndLegacyOptions = testingAndLegacyOptions; - e->serverPort = serverPort; - e->masterServerSecureEndPoint = [SecureEndPoint secureEndPointForHost:[HostNameEndPoint hostNameEndPointWithHostName:masterServerHostName - andPort:serverPort] - identifiedByCertificate:certificate]; - e->defaultRelayName = defaultRelayName; - e->certificate = certificate; - e->relayServerHostNameSuffix = relayServerHostNameSuffix; + + Environment *e = [Environment new]; + e->errorNoter = errorNoter; + e->logging = logging; + e->testingAndLegacyOptions = testingAndLegacyOptions; + e->serverPort = serverPort; + e->masterServerSecureEndPoint = [SecureEndPoint + secureEndPointForHost:[HostNameEndPoint hostNameEndPointWithHostName:masterServerHostName andPort:serverPort] + identifiedByCertificate:certificate]; + e->defaultRelayName = defaultRelayName; + e->certificate = certificate; + e->relayServerHostNameSuffix = relayServerHostNameSuffix; e->keyAgreementProtocolsInDescendingPriority = keyAgreementProtocolsInDescendingPriority; - e->currentRegionCodeForPhoneNumbers = currentRegionCodeForPhoneNumbers; - e->phoneManager = phoneManager; - e->recentCallManager = recentCallManager; - e->zrtpClientId = zrtpClientId; - e->zrtpVersionId = zrtpVersionId; - e->contactsManager = contactsManager; - + e->phoneManager = phoneManager; + e->recentCallManager = recentCallManager; + e->zrtpClientId = zrtpClientId; + e->zrtpVersionId = zrtpVersionId; + e->contactsManager = contactsManager; + if (recentCallManager != nil) { - // recentCallManagers are nil in unit tests because they would require unnecessary allocations. Detailed explanation: https://github.com/WhisperSystems/Signal-iOS/issues/62#issuecomment-51482195 - - [recentCallManager watchForCallsThrough:phoneManager - untilCancelled:nil]; + // recentCallManagers are nil in unit tests because they would require unnecessary allocations. Detailed + // explanation: https://github.com/WhisperSystems/Signal-iOS/issues/62#issuecomment-51482195 + + [recentCallManager watchForCallsThrough:phoneManager untilCancelled:nil]; } - + return e; } -+(PhoneManager*) phoneManager { ++ (PhoneManager *)phoneManager { return Environment.getCurrent.phoneManager; } -+(id) logging { ++ (id)logging { // Many tests create objects that rely on Environment only for logging. // So we bypass the nil check in getCurrent and silently don't log during unit testing, instead of failing hard. - if (environment == nil) return nil; - + if (environment == nil) + return nil; + return Environment.getCurrent.logging; } -+(BOOL)isRedPhoneRegistered{ ++ (BOOL)isRedPhoneRegistered { // Attributes that need to be set NSData *signalingKey = SignalKeyingStorage.signalingCipherKey; NSData *macKey = SignalKeyingStorage.signalingMacKey; NSData *extra = SignalKeyingStorage.signalingExtraKey; NSString *serverAuth = SignalKeyingStorage.serverAuthPassword; - + return signalingKey && macKey && extra && serverAuth; } - (void)initCallListener { - [self.phoneManager.currentCallObservable watchLatestValue:^(CallState* latestCall) { - if (latestCall == nil){ - return; - } - - SignalsViewController *vc = [[Environment getCurrent] signalsViewController]; - [vc dismissViewControllerAnimated:NO completion:nil]; - vc.latestCall = latestCall; - [vc performSegueWithIdentifier:kCallSegue sender:self]; - } onThread:NSThread.mainThread untilCancelled:nil]; + [self.phoneManager.currentCallObservable watchLatestValue:^(CallState *latestCall) { + if (latestCall == nil) { + return; + } + + SignalsViewController *vc = [[Environment getCurrent] signalsViewController]; + [vc dismissViewControllerAnimated:NO completion:nil]; + vc.latestCall = latestCall; + [vc performSegueWithIdentifier:kCallSegue sender:self]; + } + onThread:NSThread.mainThread + untilCancelled:nil]; } -+(PropertyListPreferences*)preferences{ ++ (PropertyListPreferences *)preferences { return [PropertyListPreferences new]; } -- (void)setSignalsViewController:(SignalsViewController *)signalsViewController{ +- (void)setSignalsViewController:(SignalsViewController *)signalsViewController { _signalsViewController = signalsViewController; } @@ -178,76 +159,77 @@ contactsManager; _signUpFlowNavigationController = navigationController; } -+ (void)messageThreadId:(NSString*)threadId { ++ (void)messageThreadId:(NSString *)threadId { TSThread *thread = [TSThread fetchObjectWithUniqueID:threadId]; - + if (!thread) { DDLogWarn(@"We get UILocalNotifications with unknown threadId: %@", threadId); return; } - + if ([thread isGroupThread]) { - [self messageGroup:(TSGroupThread*)thread]; + [self messageGroup:(TSGroupThread *)thread]; } else { - Environment *env = [self getCurrent]; - SignalsViewController *vc = env.signalsViewController; - UIViewController *topvc = vc.navigationController.topViewController; - + Environment *env = [self getCurrent]; + SignalsViewController *vc = env.signalsViewController; + UIViewController *topvc = vc.navigationController.topViewController; + if ([topvc isKindOfClass:[MessagesViewController class]]) { - MessagesViewController *mvc = (MessagesViewController*)topvc; + MessagesViewController *mvc = (MessagesViewController *)topvc; if ([mvc.thread.uniqueId isEqualToString:threadId]) { [mvc popKeyBoard]; return; } } - [self messageIdentifier:((TSContactThread*)thread).contactIdentifier withCompose:YES]; + [self messageIdentifier:((TSContactThread *)thread).contactIdentifier withCompose:YES]; } } -+ (void)messageIdentifier:(NSString*)identifier withCompose:(BOOL)compose { ++ (void)messageIdentifier:(NSString *)identifier withCompose:(BOOL)compose { Environment *env = [self getCurrent]; SignalsViewController *vc = env.signalsViewController; - + if (vc.presentedViewController) { [vc.presentedViewController dismissViewControllerAnimated:YES completion:nil]; } - + [vc.navigationController popToRootViewControllerAnimated:NO]; vc.contactIdentifierFromCompose = identifier; vc.composeMessage = compose; [vc performSegueWithIdentifier:@"showSegue" sender:nil]; } -+ (void)messageGroup:(TSGroupThread*)groupThread { ++ (void)messageGroup:(TSGroupThread *)groupThread { Environment *env = [self getCurrent]; SignalsViewController *vc = env.signalsViewController; - + if (vc.presentedViewController) { [vc.presentedViewController dismissViewControllerAnimated:YES completion:nil]; } - + [vc.navigationController popToRootViewControllerAnimated:NO]; [vc performSegueWithIdentifier:@"showSegue" sender:groupThread]; } -+ (void)messageGroupModel:(TSGroupModel*)model withCompose:(BOOL)compose { ++ (void)messageGroupModel:(TSGroupModel *)model withCompose:(BOOL)compose { Environment *env = [self getCurrent]; SignalsViewController *vc = env.signalsViewController; - + if (vc.presentedViewController) { [vc.presentedViewController dismissViewControllerAnimated:YES completion:nil]; } - + [vc.navigationController popToRootViewControllerAnimated:NO]; vc.groupFromCompose = model; vc.composeMessage = compose; [vc performSegueWithIdentifier:@"showSegue" sender:nil]; } -+ (void)resetAppData{ ++ (void)resetAppData { [[TSStorageManager sharedManager] wipeSignalStorage]; [Environment.preferences clear]; - [DebugLogger.sharedInstance wipeLogs]; + [DebugLogger.sharedLogger wipeLogs]; + exit(0); } @end diff --git a/Signal/src/environment/LocalizableText.h b/Signal/src/environment/LocalizableText.h index 3626e9d92..d052f6c03 100644 --- a/Signal/src/environment/LocalizableText.h +++ b/Signal/src/environment/LocalizableText.h @@ -1,43 +1,38 @@ #import -#import "CallTermination.h" #import "CallProgress.h" +#import "CallTermination.h" -#define TXT_IN_CALL_CONNECTING NSLocalizedString(@"IN_CALL_CONNECTING", @"") -#define TXT_IN_CALL_RINGING NSLocalizedString(@"IN_CALL_RINGING", @"") -#define TXT_IN_CALL_SECURING NSLocalizedString(@"IN_CALL_SECURING", @"") -#define TXT_IN_CALL_TALKING NSLocalizedString(@"IN_CALL_TALKING", @"") -#define TXT_IN_CALL_TERMINATED NSLocalizedString(@"IN_CALL_TERMINATED", @"") +#define TXT_IN_CALL_CONNECTING NSLocalizedString(@"IN_CALL_CONNECTING", @"") +#define TXT_IN_CALL_RINGING NSLocalizedString(@"IN_CALL_RINGING", @"") +#define TXT_IN_CALL_SECURING NSLocalizedString(@"IN_CALL_SECURING", @"") +#define TXT_IN_CALL_TALKING NSLocalizedString(@"IN_CALL_TALKING", @"") +#define TXT_IN_CALL_TERMINATED NSLocalizedString(@"IN_CALL_TERMINATED", @"") -#define TXT_END_CALL_LOGIN_FAILED NSLocalizedString(@"END_CALL_LOGIN_FAILED", @"") -#define TXT_END_CALL_STALE_SESSION NSLocalizedString(@"END_CALL_STALE_SESSION", @"") -#define TXT_END_CALL_NO_SUCH_USER NSLocalizedString(@"END_CALL_NO_SUCH_USER", @"") -#define TXT_END_CALL_RESPONDER_IS_BUSY NSLocalizedString(@"END_CALL_RESPONDER_IS_BUSY", @"") -#define TXT_END_CALL_REJECTED_LOCAL NSLocalizedString(@"END_CALL_REJECTED_LOCAL", @"") -#define TXT_END_CALL_REJECTED_REMOTE NSLocalizedString(@"END_CALL_REJECTED_REMOTE", @"") -#define TXT_END_CALL_RECIPIENT_UNAVAILABLE NSLocalizedString(@"END_CALL_RECIPIENT_UNAVAILABLE", @"") -#define TXT_END_CALL_UNCATEGORIZED_FAILURE NSLocalizedString(@"END_CALL_UNCATEGORIZED_FAILURE", @"") -#define TXT_END_CALL_BAD_INTERACTION_WITH_SERVER NSLocalizedString(@"END_CALL_BAD_INTERACTION_WITH_SERVER", @"") -#define TXT_END_CALL_HANDSHAKE_FAILED NSLocalizedString(@"END_CALL_HANDSHAKE_FAILED", @"") -#define TXT_END_CALL_HANGUP_REMOTE NSLocalizedString(@"END_CALL_HANGUP_REMOTE", @"") -#define TXT_END_CALL_HANGUP_LOCAL NSLocalizedString(@"END_CALL_HANGUP_LOCAL", @"") -#define TXT_END_CALL_REPLACED_BY_NEXT NSLocalizedString(@"END_CALL_REPLACED_BY_NEXT", @"") -#define TXT_END_CALL_MESSAGE_FROM_SERVER_PREFIX NSLocalizedString(@"END_CALL_MESSAGE_FROM_SERVER_PREFIX", @"") +#define TXT_END_CALL_LOGIN_FAILED NSLocalizedString(@"END_CALL_LOGIN_FAILED", @"") +#define TXT_END_CALL_STALE_SESSION NSLocalizedString(@"END_CALL_STALE_SESSION", @"") +#define TXT_END_CALL_NO_SUCH_USER NSLocalizedString(@"END_CALL_NO_SUCH_USER", @"") +#define TXT_END_CALL_RESPONDER_IS_BUSY NSLocalizedString(@"END_CALL_RESPONDER_IS_BUSY", @"") +#define TXT_END_CALL_REJECTED_LOCAL NSLocalizedString(@"END_CALL_REJECTED_LOCAL", @"") +#define TXT_END_CALL_REJECTED_REMOTE NSLocalizedString(@"END_CALL_REJECTED_REMOTE", @"") +#define TXT_END_CALL_RECIPIENT_UNAVAILABLE NSLocalizedString(@"END_CALL_RECIPIENT_UNAVAILABLE", @"") +#define TXT_END_CALL_UNCATEGORIZED_FAILURE NSLocalizedString(@"END_CALL_UNCATEGORIZED_FAILURE", @"") +#define TXT_END_CALL_BAD_INTERACTION_WITH_SERVER NSLocalizedString(@"END_CALL_BAD_INTERACTION_WITH_SERVER", @"") +#define TXT_END_CALL_HANDSHAKE_FAILED NSLocalizedString(@"END_CALL_HANDSHAKE_FAILED", @"") +#define TXT_END_CALL_HANGUP_REMOTE NSLocalizedString(@"END_CALL_HANGUP_REMOTE", @"") +#define TXT_END_CALL_HANGUP_LOCAL NSLocalizedString(@"END_CALL_HANGUP_LOCAL", @"") +#define TXT_END_CALL_REPLACED_BY_NEXT NSLocalizedString(@"END_CALL_REPLACED_BY_NEXT", @"") +#define TXT_END_CALL_MESSAGE_FROM_SERVER_PREFIX NSLocalizedString(@"END_CALL_MESSAGE_FROM_SERVER_PREFIX", @"") #pragma mark - View Controller Titles - -#define WHISPER_NAV_BAR_TITLE NSLocalizedString(@"WHISPER_NAV_BAR_TITLE", @"Title for home feed view controller") -#define CONTACT_BROWSE_NAV_BAR_TITLE NSLocalizedString(@"CONTACT_BROWSE_NAV_BAR_TITLE", @"Title for contact browse view controller") -#define KEYPAD_NAV_BAR_TITLE NSLocalizedString(@"KEYPAD_NAV_BAR_TITLE", @"Title for keypad view controller") -#define RECENT_NAV_BAR_TITLE NSLocalizedString(@"RECENT_NAV_BAR_TITLE", @"Title for recent calls view controller") -#define SETTINGS_NAV_BAR_TITLE NSLocalizedString(@"SETTINGS_NAV_BAR_TITLE", @"Title for recent calls view controller") -#define FAVOURITES_NAV_BAR_TITLE NSLocalizedString(@"FAVOURITES_NAV_BAR_TITLE", @"Title for favourites view controller") +#define SETTINGS_NAV_BAR_TITLE NSLocalizedString(@"SETTINGS_NAV_BAR_TITLE", @"Title for recent calls view controller") +#define FAVOURITES_NAV_BAR_TITLE NSLocalizedString(@"FAVOURITES_NAV_BAR_TITLE", @"Title for favourites view controller") #pragma mark - Contact Detail Communication Types -#define CONTACT_DETAIL_COMM_TYPE_EMAIL NSLocalizedString(@"CONTACT_DETAIL_COMM_TYPE_EMAIL", @"") +#define CONTACT_DETAIL_COMM_TYPE_EMAIL NSLocalizedString(@"CONTACT_DETAIL_COMM_TYPE_EMAIL", @"") #define CONTACT_DETAIL_COMM_TYPE_SECURE NSLocalizedString(@"CONTACT_DETAIL_COMM_TYPE_SECURE", @"") #define CONTACT_DETAIL_COMM_TYPE_INSECURE NSLocalizedString(@"CONTACT_DETAIL_COMM_TYPE_INSECURE", @"") -#define CONTACT_DETAIL_COMM_TYPE_NOTES NSLocalizedString(@"CONTACT_DETAIL_COMM_TYPE_NOTES", @"") +#define CONTACT_DETAIL_COMM_TYPE_NOTES NSLocalizedString(@"CONTACT_DETAIL_COMM_TYPE_NOTES", @"") #define DIALER_CALL_BUTTON_TITLE NSLocalizedString(@"DIALER_CALL_BUTTON_TITLE", @"") @@ -83,7 +78,6 @@ #define REGISTER_CC_ERR_ALERT_VIEW_DISMISS NSLocalizedString(@"OK", @"") #define CONTINUE_TO_WHISPER_TITLE NSLocalizedString(@"CONTINUE_TO_WHISPER_TITLE", @"") -#define REGISTER_BUTTON_TITLE NSLocalizedString(@"REGISTER_BUTTON_TITLE", @"") #define CHALLENGE_CODE_BUTTON_TITLE NSLocalizedString(@"CHALLENGE_CODE_BUTTON_TITLE", @"") #define END_CALL_BUTTON_TITLE NSLocalizedString(@"END_CALL_BUTTON_TITLE", @"") @@ -91,7 +85,7 @@ #define REJECT_CALL_BUTTON_TITLE NSLocalizedString(@"REJECT_CALL_BUTTON_TITLE", @"") #define REGISTER_ERROR_ALERT_VIEW_TITLE NSLocalizedString(@"REGISTRATION_ERROR", @"") -#define REGISTER_ERROR_ALERT_VIEW_BODY NSLocalizedString(@"REGISTRATION_BODY", @"") +#define REGISTER_ERROR_ALERT_VIEW_BODY NSLocalizedString(@"REGISTRATION_BODY", @"") #define REGISTER_ERROR_ALERT_VIEW_DISMISS NSLocalizedString(@"OK", @"") #define REGISTER_CHALLENGE_ALERT_VIEW_TITLE NSLocalizedString(@"REGISTER_CHALLENGE_ALERT_VIEW_TITLE", @"") @@ -104,16 +98,15 @@ #pragma mark - Invite User Modal -#define INVITE_USER_MODAL_TITLE NSLocalizedString(@"INVITE_USER_MODAL_TITLE",@"") -#define INVITE_USER_MODAL_BUTTON_CANCEL NSLocalizedString(@"INVITE_USER_MODAL_BUTTON_CANCEL",@"") -#define INVITE_USER_MODAL_BUTTON_INVITE NSLocalizedString(@"INVITE_USER_MODAL_BUTTON_INVITE",@"") -#define INVITE_USER_MODAL_TEXT NSLocalizedString(@"INVITE_USER_MODAL_TEXT",@"") +#define INVITE_USER_MODAL_TITLE NSLocalizedString(@"INVITE_USER_MODAL_TITLE", @"") +#define INVITE_USER_MODAL_BUTTON_CANCEL NSLocalizedString(@"INVITE_USER_MODAL_BUTTON_CANCEL", @"") +#define INVITE_USER_MODAL_BUTTON_INVITE NSLocalizedString(@"INVITE_USER_MODAL_BUTTON_INVITE", @"") +#define INVITE_USER_MODAL_TEXT NSLocalizedString(@"INVITE_USER_MODAL_TEXT", @"") #pragma mark - Contact Intersection -#define TIMEOUT NSLocalizedString(@"ERROR_WAS_DETECTED_TITLE",@"") -#define TIMEOUT_CONTACTS_DETAIL NSLocalizedString(@"TIMEOUT_CONTACTS_DETAIL", @"") - -NSDictionary* makeCallProgressLocalizedTextDictionary(void); -NSDictionary* makeCallTerminationLocalizedTextDictionary(void); +#define TIMEOUT NSLocalizedString(@"ERROR_WAS_DETECTED_TITLE", @"") +#define TIMEOUT_CONTACTS_DETAIL NSLocalizedString(@"TIMEOUT_CONTACTS_DETAIL", @"") +NSDictionary *makeCallProgressLocalizedTextDictionary(void); +NSDictionary *makeCallTerminationLocalizedTextDictionary(void); diff --git a/Signal/src/environment/LocalizableText.m b/Signal/src/environment/LocalizableText.m index 8f9e3a731..6b37eddf7 100644 --- a/Signal/src/environment/LocalizableText.m +++ b/Signal/src/environment/LocalizableText.m @@ -1,39 +1,38 @@ #import "LocalizableText.h" -CallTermination* ct(enum CallTerminationType t); -CallTermination* ct(enum CallTerminationType t) { +CallTermination *ct(enum CallTerminationType t); +CallTermination *ct(enum CallTerminationType t) { return [CallTermination callTerminationOfType:t withFailure:nil andMessageInfo:nil]; } -CallProgress* cp(enum CallProgressType t); -CallProgress* cp(enum CallProgressType t) { +CallProgress *cp(enum CallProgressType t); +CallProgress *cp(enum CallProgressType t) { return [CallProgress callProgressWithType:t]; } -NSDictionary* makeCallProgressLocalizedTextDictionary(void) { +NSDictionary *makeCallProgressLocalizedTextDictionary(void) { return @{ - cp(CallProgressType_Connecting): TXT_IN_CALL_CONNECTING, - cp(CallProgressType_Ringing): TXT_IN_CALL_RINGING, - cp(CallProgressType_Securing): TXT_IN_CALL_SECURING, - cp(CallProgressType_Talking): TXT_IN_CALL_TALKING, - cp(CallProgressType_Terminated): TXT_IN_CALL_TERMINATED - }; - + cp(CallProgressType_Connecting) : TXT_IN_CALL_CONNECTING, + cp(CallProgressType_Ringing) : TXT_IN_CALL_RINGING, + cp(CallProgressType_Securing) : TXT_IN_CALL_SECURING, + cp(CallProgressType_Talking) : TXT_IN_CALL_TALKING, + cp(CallProgressType_Terminated) : TXT_IN_CALL_TERMINATED + }; } -NSDictionary* makeCallTerminationLocalizedTextDictionary(void) { +NSDictionary *makeCallTerminationLocalizedTextDictionary(void) { return @{ - ct(CallTerminationType_NoSuchUser): TXT_END_CALL_NO_SUCH_USER, - ct(CallTerminationType_LoginFailed): TXT_END_CALL_LOGIN_FAILED, - ct(CallTerminationType_ResponderIsBusy): TXT_END_CALL_RESPONDER_IS_BUSY, - ct(CallTerminationType_StaleSession): TXT_END_CALL_STALE_SESSION, - ct(CallTerminationType_UncategorizedFailure): TXT_END_CALL_UNCATEGORIZED_FAILURE, - ct(CallTerminationType_ReplacedByNext): TXT_END_CALL_REPLACED_BY_NEXT, - ct(CallTerminationType_RecipientUnavailable): TXT_END_CALL_RECIPIENT_UNAVAILABLE, - ct(CallTerminationType_BadInteractionWithServer): TXT_END_CALL_BAD_INTERACTION_WITH_SERVER, - ct(CallTerminationType_HandshakeFailed): TXT_END_CALL_HANDSHAKE_FAILED, - ct(CallTerminationType_HangupRemote): TXT_END_CALL_HANGUP_REMOTE, - ct(CallTerminationType_HangupLocal): TXT_END_CALL_HANGUP_LOCAL, - ct(CallTerminationType_ServerMessage): TXT_END_CALL_MESSAGE_FROM_SERVER_PREFIX, - ct(CallTerminationType_RejectedLocal): TXT_END_CALL_REJECTED_LOCAL, - ct(CallTerminationType_RejectedRemote): TXT_END_CALL_REJECTED_REMOTE - }; + ct(CallTerminationType_NoSuchUser) : TXT_END_CALL_NO_SUCH_USER, + ct(CallTerminationType_LoginFailed) : TXT_END_CALL_LOGIN_FAILED, + ct(CallTerminationType_ResponderIsBusy) : TXT_END_CALL_RESPONDER_IS_BUSY, + ct(CallTerminationType_StaleSession) : TXT_END_CALL_STALE_SESSION, + ct(CallTerminationType_UncategorizedFailure) : TXT_END_CALL_UNCATEGORIZED_FAILURE, + ct(CallTerminationType_ReplacedByNext) : TXT_END_CALL_REPLACED_BY_NEXT, + ct(CallTerminationType_RecipientUnavailable) : TXT_END_CALL_RECIPIENT_UNAVAILABLE, + ct(CallTerminationType_BadInteractionWithServer) : TXT_END_CALL_BAD_INTERACTION_WITH_SERVER, + ct(CallTerminationType_HandshakeFailed) : TXT_END_CALL_HANDSHAKE_FAILED, + ct(CallTerminationType_HangupRemote) : TXT_END_CALL_HANGUP_REMOTE, + ct(CallTerminationType_HangupLocal) : TXT_END_CALL_HANGUP_LOCAL, + ct(CallTerminationType_ServerMessage) : TXT_END_CALL_MESSAGE_FROM_SERVER_PREFIX, + ct(CallTerminationType_RejectedLocal) : TXT_END_CALL_REJECTED_LOCAL, + ct(CallTerminationType_RejectedRemote) : TXT_END_CALL_REJECTED_REMOTE + }; } diff --git a/Signal/src/environment/NotificationsManager.h b/Signal/src/environment/NotificationsManager.h new file mode 100644 index 000000000..f3f4e98dc --- /dev/null +++ b/Signal/src/environment/NotificationsManager.h @@ -0,0 +1,18 @@ +// +// NotificationsManager.h +// Signal +// +// Created by Frederic Jacobs on 22/12/15. +// Copyright © 2015 Open Whisper Systems. All rights reserved. +// + +#import +#import + +@class TSCall; + +@interface NotificationsManager : NSObject + +- (void)notifyUserForCall:(TSCall *)call inThread:(TSThread *)thread; + +@end diff --git a/Signal/src/environment/NotificationsManager.m b/Signal/src/environment/NotificationsManager.m new file mode 100644 index 000000000..b9bcd9fd3 --- /dev/null +++ b/Signal/src/environment/NotificationsManager.m @@ -0,0 +1,150 @@ +// +// NotificationsManager.m +// Signal +// +// Created by Frederic Jacobs on 22/12/15. +// Copyright © 2015 Open Whisper Systems. All rights reserved. +// + +#import +#import +#import +#import +#import +#import +#import "Environment.h" +#import "NotificationsManager.h" +#import "PreferencesUtil.h" +#import "PushManager.h" + +@interface NotificationsManager () + +@property SystemSoundID newMessageSound; + +@end + +@implementation NotificationsManager + +- (instancetype)init { + self = [super init]; + + if (self) { + NSURL *newMessageSound = + [NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"NewMessage" ofType:@"aifc"]]; + self.newMessageSound = AudioServicesCreateSystemSoundID((__bridge CFURLRef)newMessageSound, &_newMessageSound); + } + + return self; +} + +- (void)notifyUserForCall:(TSCall *)call inThread:(TSThread *)thread { + if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive) { + // Remove previous notification of call and show missed notification. + UILocalNotification *notif = [[PushManager sharedManager] closeVOIPBackgroundTask]; + TSContactThread *cThread = (TSContactThread *)thread; + + if (call.callType == RPRecentCallTypeMissed) { + if (notif) { + [[UIApplication sharedApplication] cancelLocalNotification:notif]; + } + + UILocalNotification *notification = [[UILocalNotification alloc] init]; + notification.category = Signal_CallBack_Category; + notification.userInfo = @{Signal_Call_UserInfo_Key : cThread.contactIdentifier}; + notification.soundName = @"NewMessage.aifc"; + notification.alertBody = + [NSString stringWithFormat:NSLocalizedString(@"MSGVIEW_MISSED_CALL", nil), [thread name]]; + + [[PushManager sharedManager] presentNotification:notification]; + } + } +} + +- (void)notifyUserForErrorMessage:(TSErrorMessage *)message inThread:(TSThread *)thread { + NSString *messageDescription = message.description; + + if (([UIApplication sharedApplication].applicationState != UIApplicationStateActive) && messageDescription) { + UILocalNotification *notification = [[UILocalNotification alloc] init]; + notification.userInfo = @{Signal_Thread_UserInfo_Key : thread.uniqueId}; + notification.soundName = @"NewMessage.aifc"; + + NSString *alertBodyString = @""; + + NSString *authorName = [thread name]; + switch ([[Environment preferences] notificationPreviewType]) { + case NotificationNamePreview: + case NotificationNameNoPreview: + alertBodyString = [NSString stringWithFormat:@"%@: %@", authorName, messageDescription]; + break; + case NotificationNoNameNoPreview: + alertBodyString = messageDescription; + break; + } + notification.alertBody = alertBodyString; + + [[PushManager sharedManager] presentNotification:notification]; + } else { + if ([Environment.preferences soundInForeground]) { + AudioServicesPlayAlertSound(_newMessageSound); + } + } +} + +- (void)notifyUserForIncomingMessage:(TSIncomingMessage *)message from:(NSString *)name inThread:(TSThread *)thread { + NSString *messageDescription = message.description; + + if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive && messageDescription) { + UILocalNotification *notification = [[UILocalNotification alloc] init]; + notification.soundName = @"NewMessage.aifc"; + + switch ([[Environment preferences] notificationPreviewType]) { + case NotificationNamePreview: + notification.category = Signal_Full_New_Message_Category; + notification.userInfo = + @{Signal_Thread_UserInfo_Key : thread.uniqueId, Signal_Message_UserInfo_Key : message.uniqueId}; + + if ([thread isGroupThread]) { + NSString *sender = + [[TextSecureKitEnv sharedEnv].contactsManager nameStringForPhoneIdentifier:message.authorId]; + if (!sender) { + sender = message.authorId; + } + + NSString *threadName = [NSString stringWithFormat:@"\"%@\"", name]; + notification.alertBody = + [NSString stringWithFormat:NSLocalizedString(@"APN_MESSAGE_IN_GROUP_DETAILED", nil), + sender, + threadName, + messageDescription]; + } else { + notification.alertBody = [NSString stringWithFormat:@"%@: %@", name, messageDescription]; + } + break; + case NotificationNameNoPreview: { + notification.userInfo = @{Signal_Thread_UserInfo_Key : thread.uniqueId}; + if ([thread isGroupThread]) { + notification.alertBody = + [NSString stringWithFormat:@"%@ \"%@\"", NSLocalizedString(@"APN_MESSAGE_IN_GROUP", nil), name]; + } else { + notification.alertBody = + [NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"APN_MESSAGE_FROM", nil), name]; + } + break; + } + case NotificationNoNameNoPreview: + notification.alertBody = NSLocalizedString(@"APN_Message", nil); + break; + default: + notification.alertBody = NSLocalizedString(@"APN_Message", nil); + break; + } + + [[PushManager sharedManager] presentNotification:notification]; + } else { + if ([Environment.preferences soundInForeground]) { + AudioServicesPlayAlertSound(_newMessageSound); + } + } +} + +@end diff --git a/Signal/src/environment/PreferencesUtil.h b/Signal/src/environment/PreferencesUtil.h index 816eb3b68..fd7f31658 100644 --- a/Signal/src/environment/PreferencesUtil.h +++ b/Signal/src/environment/PreferencesUtil.h @@ -19,14 +19,14 @@ typedef NS_ENUM(NSUInteger, TSImageQuality) { @interface PropertyListPreferences (PropertyUtil) -- (NSTimeInterval) getCachedOrDefaultDesiredBufferDepth; -- (void) setCachedDesiredBufferDepth:(double)value; +- (NSTimeInterval)getCachedOrDefaultDesiredBufferDepth; +- (void)setCachedDesiredBufferDepth:(double)value; -- (BOOL) getHasSentAMessage; -- (void) setHasSentAMessage:(BOOL)enabled; +- (BOOL)getHasSentAMessage; +- (void)setHasSentAMessage:(BOOL)enabled; -- (BOOL) getHasArchivedAMessage; -- (void) setHasArchivedAMessage:(BOOL)enabled; +- (BOOL)getHasArchivedAMessage; +- (void)setHasArchivedAMessage:(BOOL)enabled; - (BOOL)loggingIsEnabled; - (void)setLoggingEnabled:(BOOL)flag; @@ -36,19 +36,19 @@ typedef NS_ENUM(NSUInteger, TSImageQuality) { - (NotificationType)notificationPreviewType; - (void)setNotificationPreviewType:(NotificationType)type; -- (NSString*)nameForNotificationPreviewType:(NotificationType)notificationType; +- (NSString *)nameForNotificationPreviewType:(NotificationType)notificationType; - (BOOL)soundInForeground; - (void)setSoundInForeground:(BOOL)enabled; - (BOOL)hasRegisteredVOIPPush; --(void)setHasRegisteredVOIPPush:(BOOL)enabled; +- (void)setHasRegisteredVOIPPush:(BOOL)enabled; - (TSImageQuality)imageUploadQuality; - (void)setImageUploadQuality:(TSImageQuality)quality; -- (NSString*)lastRanVersion; -- (NSString*)setAndGetCurrentVersion; +- (NSString *)lastRanVersion; +- (NSString *)setAndGetCurrentVersion; @end diff --git a/Signal/src/environment/PreferencesUtil.m b/Signal/src/environment/PreferencesUtil.m index 2aca4aaf1..bdbef50c7 100644 --- a/Signal/src/environment/PreferencesUtil.m +++ b/Signal/src/environment/PreferencesUtil.m @@ -1,5 +1,5 @@ -#import "PreferencesUtil.h" #import "Constraints.h" +#import "PreferencesUtil.h" #define CALL_STREAM_DES_BUFFER_LEVEL_KEY @"CallStreamDesiredBufferLevel" @@ -25,17 +25,18 @@ @implementation PropertyListPreferences (PropertyUtil) --(NSTimeInterval) getCachedOrDefaultDesiredBufferDepth { +- (NSTimeInterval)getCachedOrDefaultDesiredBufferDepth { id v = [self tryGetValueForKey:CALL_STREAM_DES_BUFFER_LEVEL_KEY]; - if (v == nil) return DEFAULT_CALL_STREAM_DES_BUFFER_LEVEL; + if (v == nil) + return DEFAULT_CALL_STREAM_DES_BUFFER_LEVEL; return [v doubleValue]; } --(void) setCachedDesiredBufferDepth:(double)value { - require(value >= 0); +- (void)setCachedDesiredBufferDepth:(double)value { + ows_require(value >= 0); [self setValueForKey:CALL_STREAM_DES_BUFFER_LEVEL_KEY toValue:@(value)]; } --(BOOL) getFreshInstallTutorialsEnabled { +- (BOOL)getFreshInstallTutorialsEnabled { NSNumber *preference = [self tryGetValueForKey:FRESH_INSTALL_TUTORIALS_ENABLED_KEY]; if (preference) { return [preference boolValue]; @@ -43,7 +44,7 @@ return YES; } } --(BOOL) getContactImagesEnabled { +- (BOOL)getContactImagesEnabled { NSNumber *preference = [self tryGetValueForKey:CONTACT_IMAGES_ENABLED_KEY]; if (preference) { return [preference boolValue]; @@ -51,7 +52,7 @@ return YES; } } --(BOOL) getAutocorrectEnabled { +- (BOOL)getAutocorrectEnabled { NSNumber *preference = [self tryGetValueForKey:AUTOCORRECT_ENABLED_KEY]; if (preference) { return [preference boolValue]; @@ -59,7 +60,7 @@ return YES; } } --(BOOL) getHistoryLogEnabled { +- (BOOL)getHistoryLogEnabled { NSNumber *preference = [self tryGetValueForKey:HISTORY_LOG_ENABLED_KEY]; if (preference) { return [preference boolValue]; @@ -68,110 +69,108 @@ } } -- (BOOL)loggingIsEnabled{ +- (BOOL)loggingIsEnabled { NSNumber *preference = [self tryGetValueForKey:DEBUG_IS_ENABLED_KEY]; if (preference) { return [preference boolValue]; - } else{ + } else { return YES; } } --(BOOL)screenSecurityIsEnabled{ +- (BOOL)screenSecurityIsEnabled { NSNumber *preference = [self tryGetValueForKey:SCREEN_SECURITY_KEY]; if (preference) { return [preference boolValue]; - } else{ + } else { return NO; } } -- (BOOL) getHasSentAMessage{ +- (BOOL)getHasSentAMessage { NSNumber *preference = [self tryGetValueForKey:HAS_SENT_A_MESSAGE_KEY]; if (preference) { return [preference boolValue]; - } else{ + } else { return NO; } - } -- (BOOL) getHasArchivedAMessage { +- (BOOL)getHasArchivedAMessage { NSNumber *preference = [self tryGetValueForKey:HAS_ARCHIVED_A_MESSAGE_KEY]; if (preference) { return [preference boolValue]; - } else{ + } else { return NO; } - } - (BOOL)hasRegisteredVOIPPush { NSNumber *preference = [self tryGetValueForKey:HAS_REGISTERED_VOIP_PUSH]; if (preference) { return [preference boolValue]; - } else{ + } else { return YES; } - } --(TSImageQuality)imageUploadQuality { +- (TSImageQuality)imageUploadQuality { // always return average image quality return TSImageQualityMedium; } --(void)setImageUploadQuality:(TSImageQuality)quality { +- (void)setImageUploadQuality:(TSImageQuality)quality { [self setValueForKey:IMAGE_UPLOAD_QUALITY_KEY toValue:@(quality)]; } --(void)setScreenSecurity:(BOOL)flag{ +- (void)setScreenSecurity:(BOOL)flag { [self setValueForKey:SCREEN_SECURITY_KEY toValue:@(flag)]; } --(void) setFreshInstallTutorialsEnabled:(BOOL)enabled { +- (void)setFreshInstallTutorialsEnabled:(BOOL)enabled { [self setValueForKey:FRESH_INSTALL_TUTORIALS_ENABLED_KEY toValue:@(enabled)]; } --(void)setHasRegisteredVOIPPush:(BOOL)enabled { +- (void)setHasRegisteredVOIPPush:(BOOL)enabled { [self setValueForKey:HAS_REGISTERED_VOIP_PUSH toValue:@(enabled)]; } --(void) setContactImagesEnabled:(BOOL)enabled { +- (void)setContactImagesEnabled:(BOOL)enabled { [self setValueForKey:CONTACT_IMAGES_ENABLED_KEY toValue:@(enabled)]; } --(void) setAutocorrectEnabled:(BOOL)enabled { +- (void)setAutocorrectEnabled:(BOOL)enabled { [self setValueForKey:AUTOCORRECT_ENABLED_KEY toValue:@(enabled)]; } --(void) setHistoryLogEnabled:(BOOL)enabled { +- (void)setHistoryLogEnabled:(BOOL)enabled { [self setValueForKey:HISTORY_LOG_ENABLED_KEY toValue:@(enabled)]; } --(BOOL) encounteredRevokedPushPermission{ +- (BOOL)encounteredRevokedPushPermission { return [[self tryGetValueForKey:PUSH_REVOKED_KEY] boolValue]; } --(void) setRevokedPushPermission:(BOOL)revoked{ +- (void)setRevokedPushPermission:(BOOL)revoked { [self setValueForKey:PUSH_REVOKED_KEY toValue:@(revoked)]; } --(void) setLoggingEnabled:(BOOL)flag{ +- (void)setLoggingEnabled:(BOOL)flag { [self setValueForKey:DEBUG_IS_ENABLED_KEY toValue:@(flag)]; } --(NSString*)lastRanVersion{ +- (NSString *)lastRanVersion { return [NSUserDefaults.standardUserDefaults objectForKey:kSignalVersionKey]; } -- (void) setHasSentAMessage:(BOOL)enabled{ +- (void)setHasSentAMessage:(BOOL)enabled { [self setValueForKey:HAS_SENT_A_MESSAGE_KEY toValue:@(enabled)]; } -- (void) setHasArchivedAMessage:(BOOL)enabled{ +- (void)setHasArchivedAMessage:(BOOL)enabled { [self setValueForKey:HAS_ARCHIVED_A_MESSAGE_KEY toValue:@(enabled)]; } --(NSString*)setAndGetCurrentVersion{ - NSString *currentVersion = [NSString stringWithFormat:@"%@", NSBundle.mainBundle.infoDictionary[@"CFBundleVersion"]]; +- (NSString *)setAndGetCurrentVersion { + NSString *currentVersion = + [NSString stringWithFormat:@"%@", NSBundle.mainBundle.infoDictionary[@"CFBundleVersion"]]; [NSUserDefaults.standardUserDefaults setObject:currentVersion forKey:kSignalVersionKey]; [NSUserDefaults.standardUserDefaults synchronize]; return currentVersion; @@ -183,7 +182,7 @@ NSNumber *preference = [self tryGetValueForKey:PLAY_SOUND_IN_FOREGROUND_KEY]; if (preference) { return [preference boolValue]; - } else{ + } else { return YES; } } @@ -192,14 +191,13 @@ [self setValueForKey:PLAY_SOUND_IN_FOREGROUND_KEY toValue:@(enabled)]; } --(void)setNotificationPreviewType:(NotificationType)type -{ +- (void)setNotificationPreviewType:(NotificationType)type { [self setValueForKey:NOTIFICATION_PREVIEW_TYPE_KEY toValue:@(type)]; } --(NotificationType)notificationPreviewType { +- (NotificationType)notificationPreviewType { NSNumber *preference = [self tryGetValueForKey:NOTIFICATION_PREVIEW_TYPE_KEY]; - + if (preference) { return [preference unsignedIntegerValue]; } else { @@ -207,7 +205,7 @@ } } -- (NSString*)nameForNotificationPreviewType:(NotificationType)notificationType { +- (NSString *)nameForNotificationPreviewType:(NotificationType)notificationType { switch (notificationType) { case NotificationNamePreview: return NSLocalizedString(@"NOTIFICATIONS_SENDER_AND_MESSAGE", nil); diff --git a/Signal/src/environment/PropertyListPreferences.h b/Signal/src/environment/PropertyListPreferences.h index c2c997b1b..aa1d34dba 100644 --- a/Signal/src/environment/PropertyListPreferences.h +++ b/Signal/src/environment/PropertyListPreferences.h @@ -2,9 +2,9 @@ @interface PropertyListPreferences : NSObject --(id) tryGetValueForKey:(NSString*)key; --(void) setValueForKey:(NSString*)key toValue:(id)value; --(id) adjustAndTryGetNewValueForKey:(NSString*)key afterAdjuster:(id (^)(id oldValue))adjuster; --(void) clear; +- (id)tryGetValueForKey:(NSString *)key; +- (void)setValueForKey:(NSString *)key toValue:(id)value; +- (id)adjustAndTryGetNewValueForKey:(NSString *)key afterAdjuster:(id (^)(id oldValue))adjuster; +- (void)clear; @end diff --git a/Signal/src/environment/PropertyListPreferences.m b/Signal/src/environment/PropertyListPreferences.m index aa5c9cad0..12481edf5 100644 --- a/Signal/src/environment/PropertyListPreferences.m +++ b/Signal/src/environment/PropertyListPreferences.m @@ -1,5 +1,5 @@ -#import "PropertyListPreferences.h" #import "Constraints.h" +#import "PropertyListPreferences.h" #import "TSStorageHeaders.h" #define SignalDatabaseCollection @"SignalPreferences" @@ -7,7 +7,7 @@ @implementation PropertyListPreferences --(void) clear { +- (void)clear { @synchronized(self) { NSString *appDomain = NSBundle.mainBundle.bundleIdentifier; [NSUserDefaults.standardUserDefaults removePersistentDomainForName:appDomain]; @@ -15,17 +15,17 @@ } - (id)tryGetValueForKey:(NSString *)key { - require(key != nil); + ows_require(key != nil); return [TSStorageManager.sharedManager objectForKey:key inCollection:SignalDatabaseCollection]; } - (void)setValueForKey:(NSString *)key toValue:(id)value { - require(key != nil); - + ows_require(key != nil); + [TSStorageManager.sharedManager setObject:value forKey:key inCollection:SignalDatabaseCollection]; } - (id)adjustAndTryGetNewValueForKey:(NSString *)key afterAdjuster:(id (^)(id))adjuster { - require(key != nil); - require(adjuster != nil); + ows_require(key != nil); + ows_require(adjuster != nil); @synchronized(self) { id oldValue = [self tryGetValueForKey:key]; id newValue = adjuster(oldValue); diff --git a/Signal/src/environment/Release.h b/Signal/src/environment/Release.h index 2cf43c47a..e060054e5 100644 --- a/Signal/src/environment/Release.h +++ b/Signal/src/environment/Release.h @@ -1,18 +1,18 @@ #import -#import "Environment.h" #import "DH3KKeyAgreementProtocol.h" #import "EC25KeyAgreementProtocol.h" +#import "Environment.h" @interface Release : NSObject /// Connects to actual production infrastructure -+(Environment*) releaseEnvironmentWithLogging:(id)logging; ++ (Environment *)releaseEnvironmentWithLogging:(id)logging; -+(Environment*) stagingEnvironmentWithLogging:(id)logging; ++ (Environment *)stagingEnvironmentWithLogging:(id)logging; /// Fake environment with no logging -+(Environment*) unitTestEnvironment:(NSArray*)testingAndLegacyOptions; ++ (Environment *)unitTestEnvironment:(NSArray *)testingAndLegacyOptions; -+(DH3KKeyAgreementProtocol*) supportedDH3KKeyAgreementProtocol; ++ (DH3KKeyAgreementProtocol *)supportedDH3KKeyAgreementProtocol; @end diff --git a/Signal/src/environment/Release.m b/Signal/src/environment/Release.m index 48d6f1502..ef241cb8e 100644 --- a/Signal/src/environment/Release.m +++ b/Signal/src/environment/Release.m @@ -1,8 +1,8 @@ -#import "Release.h" #import "DiscardingLog.h" #import "PhoneManager.h" #import "PhoneNumberUtil.h" #import "RecentCallManager.h" +#import "Release.h" #define RELEASE_ZRTP_CLIENT_ID @"Whisper 000 ".encodedAsAscii #define RELEASE_ZRTP_VERSION_ID @"1.10".encodedAsAscii @@ -10,121 +10,95 @@ #define TESTING_ZRTP_CLIENT_ID @"RedPhone 019 ".encodedAsAscii #define TESTING_ZRTP_VERSION_ID @"1.10".encodedAsAscii -static unsigned char DH3K_PRIME[]={ - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2, - 0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67, - 0xCC,0x74,0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E, - 0x34,0x04,0xDD,0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D, - 0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5, - 0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF, - 0x5C,0xB6,0xF4,0x06,0xB7,0xED,0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE, - 0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D, - 0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3, - 0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,0x83,0x65,0x5D,0x23,0xDC,0xA3, - 0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07,0x70, - 0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,0xF1,0x74,0x6C,0x08, - 0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,0xE3,0x9E,0x77, - 0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,0xB5,0xC5, - 0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,0x39, - 0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10, - 0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A, - 0x33,0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB, - 0xEF,0x0A,0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6, - 0xE1,0xE4,0xC7,0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0, - 0x4A,0x25,0x61,0x9D,0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA, - 0x06,0xD9,0x8A,0x08,0x64,0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F, - 0x2B,0x18,0x17,0x7B,0x20,0x0C,0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77, - 0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31, - 0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,0x4B,0x82,0xD1,0x20,0xA9,0x3A,0xD2, - 0xCA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF -}; +static unsigned char DH3K_PRIME[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, + 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, + 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, + 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, + 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, + 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, + 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, + 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, + 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, + 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, + 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, + 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, + 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, + 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, + 0xE1, 0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, + 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, + 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, + 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF}; #define DH3K_GENERATOR 2 @implementation Release -+(Environment*) releaseEnvironmentWithLogging:(id)logging { - //ErrorHandlerBlock errorDiscarder = ^(id error, id relatedInfo, bool causedTermination) {}; - ErrorHandlerBlock errorNoter = ^(id error, id relatedInfo, bool causedTermination) {DDLogError(@"%@: %@, %d", error, relatedInfo, causedTermination); }; - - NSString *defaultRegion; -#if TARGET_OS_IPHONE - defaultRegion = [[PhoneNumberUtil sharedInstance].nbPhoneNumberUtil countryCodeByCarrier]; - - if ([defaultRegion isEqualToString:@"ZZ"]) { - defaultRegion = [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode]; - } -#else - defaultRegion = [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode]; -#endif - - - NSAssert([defaultRegion isKindOfClass:[NSString class]], @""); - - return [Environment environmentWithLogging:logging - andErrorNoter:errorNoter - andServerPort:31337 - andMasterServerHostName:@"master.whispersystems.org" - andDefaultRelayName:@"relay" - andRelayServerHostNameSuffix:@"whispersystems.org" - andCertificate:[Certificate certificateFromResourcePath:@"redphone" ofType:@"cer"] - andCurrentRegionCodeForPhoneNumbers:defaultRegion - andSupportedKeyAgreementProtocols:[self supportedKeyAgreementProtocols] - andPhoneManager:[PhoneManager phoneManagerWithErrorHandler:errorNoter] - andRecentCallManager:[RecentCallManager new] - andTestingAndLegacyOptions:@[ENVIRONMENT_LEGACY_OPTION_RTP_PADDING_BIT_IMPLIES_EXTENSION_BIT_AND_TWELVE_EXTRA_ZERO_BYTES_IN_HEADER] - andZrtpClientId:RELEASE_ZRTP_CLIENT_ID - andZrtpVersionId:RELEASE_ZRTP_VERSION_ID - andContactsManager:[ContactsManager new]]; ++ (Environment *)releaseEnvironmentWithLogging:(id)logging { + // ErrorHandlerBlock errorDiscarder = ^(id error, id relatedInfo, bool causedTermination) {}; + ErrorHandlerBlock errorNoter = ^(id error, id relatedInfo, bool causedTermination) { + DDLogError(@"%@: %@, %d", error, relatedInfo, causedTermination); + }; + + return [Environment + environmentWithLogging:logging + andErrorNoter:errorNoter + andServerPort:31337 + andMasterServerHostName:@"master.whispersystems.org" + andDefaultRelayName:@"relay" + andRelayServerHostNameSuffix:@"whispersystems.org" + andCertificate:[Certificate certificateFromResourcePath:@"redphone" ofType:@"cer"] + andSupportedKeyAgreementProtocols:[self supportedKeyAgreementProtocols] + andPhoneManager:[PhoneManager phoneManagerWithErrorHandler:errorNoter] + andRecentCallManager:[RecentCallManager new] + andTestingAndLegacyOptions:@[ + ENVIRONMENT_LEGACY_OPTION_RTP_PADDING_BIT_IMPLIES_EXTENSION_BIT_AND_TWELVE_EXTRA_ZERO_BYTES_IN_HEADER + ] + andZrtpClientId:RELEASE_ZRTP_CLIENT_ID + andZrtpVersionId:RELEASE_ZRTP_VERSION_ID + andContactsManager:[ContactsManager new]]; } -+(Environment*) stagingEnvironmentWithLogging:(id)logging { - ErrorHandlerBlock errorNoter = ^(id error, id relatedInfo, bool causedTermination) {DDLogError(@"%@: %@, %d", error, relatedInfo, causedTermination); }; - - NSString *defaultRegion; -#if TARGET_OS_IPHONE - defaultRegion = [[PhoneNumberUtil sharedInstance].nbPhoneNumberUtil countryCodeByCarrier]; - - if ([defaultRegion isEqualToString:@"ZZ"]) { - defaultRegion = [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode]; - } -#else - defaultRegion = [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode]; -#endif - - - NSAssert([defaultRegion isKindOfClass:[NSString class]], @""); - - return [Environment environmentWithLogging:logging - andErrorNoter:errorNoter - andServerPort:31337 - andMasterServerHostName:@"redphone-staging.whispersystems.org" - andDefaultRelayName:@"redphone-staging-relay" - andRelayServerHostNameSuffix:@"whispersystems.org" - andCertificate:[Certificate certificateFromResourcePath:@"redphone" ofType:@"cer"] - andCurrentRegionCodeForPhoneNumbers:defaultRegion - andSupportedKeyAgreementProtocols:[self supportedKeyAgreementProtocols] - andPhoneManager:[PhoneManager phoneManagerWithErrorHandler:errorNoter] - andRecentCallManager:[RecentCallManager new] - andTestingAndLegacyOptions:@[ENVIRONMENT_LEGACY_OPTION_RTP_PADDING_BIT_IMPLIES_EXTENSION_BIT_AND_TWELVE_EXTRA_ZERO_BYTES_IN_HEADER] - andZrtpClientId:RELEASE_ZRTP_CLIENT_ID - andZrtpVersionId:RELEASE_ZRTP_VERSION_ID - andContactsManager:[ContactsManager new]]; ++ (Environment *)stagingEnvironmentWithLogging:(id)logging { + ErrorHandlerBlock errorNoter = ^(id error, id relatedInfo, bool causedTermination) { + DDLogError(@"%@: %@, %d", error, relatedInfo, causedTermination); + }; + + return [Environment + environmentWithLogging:logging + andErrorNoter:errorNoter + andServerPort:31337 + andMasterServerHostName:@"redphone-staging.whispersystems.org" + andDefaultRelayName:@"redphone-staging-relay" + andRelayServerHostNameSuffix:@"whispersystems.org" + andCertificate:[Certificate certificateFromResourcePath:@"redphone" ofType:@"cer"] + andSupportedKeyAgreementProtocols:[self supportedKeyAgreementProtocols] + andPhoneManager:[PhoneManager phoneManagerWithErrorHandler:errorNoter] + andRecentCallManager:[RecentCallManager new] + andTestingAndLegacyOptions:@[ + ENVIRONMENT_LEGACY_OPTION_RTP_PADDING_BIT_IMPLIES_EXTENSION_BIT_AND_TWELVE_EXTRA_ZERO_BYTES_IN_HEADER + ] + andZrtpClientId:RELEASE_ZRTP_CLIENT_ID + andZrtpVersionId:RELEASE_ZRTP_VERSION_ID + andContactsManager:[ContactsManager new]]; } -+(Environment*) unitTestEnvironment:(NSArray*)testingAndLegacyOptions { - NSArray* keyAgreementProtocols = self.supportedKeyAgreementProtocols; ++ (Environment *)unitTestEnvironment:(NSArray *)testingAndLegacyOptions { + NSArray *keyAgreementProtocols = self.supportedKeyAgreementProtocols; if ([testingAndLegacyOptions containsObject:TESTING_OPTION_USE_DH_FOR_HANDSHAKE]) { - keyAgreementProtocols = @[[Release supportedDH3KKeyAgreementProtocol]]; + keyAgreementProtocols = @[ [Release supportedDH3KKeyAgreementProtocol] ]; } - + return [Environment environmentWithLogging:[DiscardingLog discardingLog] - andErrorNoter:^(id error, id relatedInfo, bool causedTermination) {} + andErrorNoter:^(id error, id relatedInfo, bool causedTermination) { + } andServerPort:31337 andMasterServerHostName:@"master.whispersystems.org" andDefaultRelayName:@"relay" andRelayServerHostNameSuffix:@"whispersystems.org" andCertificate:[Certificate certificateFromResourcePath:@"redphone" ofType:@"cer"] - andCurrentRegionCodeForPhoneNumbers:@"US" andSupportedKeyAgreementProtocols:keyAgreementProtocols andPhoneManager:nil andRecentCallManager:nil @@ -134,16 +108,13 @@ static unsigned char DH3K_PRIME[]={ andContactsManager:nil]; } -+(NSArray*) supportedKeyAgreementProtocols { - return @[ - [EC25KeyAgreementProtocol new], - [Release supportedDH3KKeyAgreementProtocol] - ]; ++ (NSArray *)supportedKeyAgreementProtocols { + return @[ [EC25KeyAgreementProtocol new], [Release supportedDH3KKeyAgreementProtocol] ]; } -+(DH3KKeyAgreementProtocol*) supportedDH3KKeyAgreementProtocol { - NSData* prime = [NSData dataWithBytes:DH3K_PRIME length:sizeof(DH3K_PRIME)]; - NSData* generator = [NSData dataWithSingleByte:DH3K_GENERATOR]; ++ (DH3KKeyAgreementProtocol *)supportedDH3KKeyAgreementProtocol { + NSData *prime = [NSData dataWithBytes:DH3K_PRIME length:sizeof(DH3K_PRIME)]; + NSData *generator = [NSData dataWithSingleByte:DH3K_GENERATOR]; return [DH3KKeyAgreementProtocol protocolWithModulus:prime andGenerator:generator]; } diff --git a/Signal/src/environment/SignalKeyingStorage.h b/Signal/src/environment/SignalKeyingStorage.h index bf2362db5..b01b04711 100644 --- a/Signal/src/environment/SignalKeyingStorage.h +++ b/Signal/src/environment/SignalKeyingStorage.h @@ -15,44 +15,34 @@ #define SAVED_PASSWORD_KEY @"Password" #define SIGNALING_MAC_KEY @"Signaling Mac Key" #define SIGNALING_CIPHER_KEY @"Signaling Cipher Key" -#define ZID_KEY @"ZID" -#define ZID_LENGTH 12 #define SIGNALING_EXTRA_KEY @"Signaling Extra Key" @interface SignalKeyingStorage : NSObject -+(void)generateSignaling; -+(void)generateServerAuthPassword; - -#pragma mark Registered Phone Number - -+(PhoneNumber*)localNumber; -+(void)setLocalNumberTo:(PhoneNumber*)localNumber; ++ (void)generateSignaling; ++ (void)generateServerAuthPassword; #pragma mark Signaling Key -+(int64_t)getAndIncrementOneTimeCounter; - -#pragma mark Zid - -+(Zid*)zid; ++ (int64_t)getAndIncrementOneTimeCounter; #pragma mark Server Auth -+(NSString*)serverAuthPassword; ++ (NSString *)serverAuthPassword; #pragma mark Signaling -+(NSData*)signalingMacKey; -+(NSData*)signalingCipherKey; ++ (NSData *)signalingMacKey; ++ (NSData *)signalingCipherKey; /** - * Returns the extra keying material generated at registration. - ⚠️ Warning: Users of older versions of Signal (<= 2.1.1) might have the signaling cipher key as extra keing material. + * Returns the extra keying material generated at registration. + ⚠️ Warning: Users of older versions of Signal (<= 2.1.1) might have the signaling cipher key as extra keing + material. * * @return Extra keying material from registration time */ -+(NSData*)signalingExtraKey; ++ (NSData *)signalingExtraKey; @end diff --git a/Signal/src/environment/SignalKeyingStorage.m b/Signal/src/environment/SignalKeyingStorage.m index 1e31537b4..f0313875e 100644 --- a/Signal/src/environment/SignalKeyingStorage.m +++ b/Signal/src/environment/SignalKeyingStorage.m @@ -5,111 +5,88 @@ // Created by Frederic Jacobs on 09/07/14. // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // +#import "Constraints.h" #import "CryptoTools.h" #import "SignalKeyingStorage.h" -#import "Constraints.h" #import "TSStorageManager.h" #import "Util.h" #define SignalKeyingCollection @"SignalKeyingCollection" -#define SIGNALING_MAC_KEY_LENGTH 20 +#define SIGNALING_MAC_KEY_LENGTH 20 #define SIGNALING_CIPHER_KEY_LENGTH 16 #define SAVED_PASSWORD_LENGTH 18 #define SIGNALING_EXTRA_KEY_LENGTH 4 @implementation SignalKeyingStorage -+ (void)generateServerAuthPassword{ - [self storeString:[[CryptoTools generateSecureRandomData:SAVED_PASSWORD_LENGTH] encodedAsBase64] forKey:SAVED_PASSWORD_KEY]; ++ (void)generateServerAuthPassword { + [self storeString:[[CryptoTools generateSecureRandomData:SAVED_PASSWORD_LENGTH] encodedAsBase64] + forKey:SAVED_PASSWORD_KEY]; } -+ (void)generateSignaling{ ++ (void)generateSignaling { [self storeData:[CryptoTools generateSecureRandomData:SIGNALING_MAC_KEY_LENGTH] forKey:SIGNALING_MAC_KEY]; [self storeData:[CryptoTools generateSecureRandomData:SIGNALING_CIPHER_KEY_LENGTH] forKey:SIGNALING_CIPHER_KEY]; [self storeData:[CryptoTools generateSecureRandomData:SIGNALING_EXTRA_KEY_LENGTH] forKey:SIGNALING_EXTRA_KEY]; - [self storeData:[CryptoTools generateSecureRandomData:ZID_LENGTH] forKey:ZID_KEY]; } -+(int64_t) getAndIncrementOneTimeCounter { ++ (int64_t)getAndIncrementOneTimeCounter { __block int64_t oldCounter; - oldCounter = [[self stringForKey:PASSWORD_COUNTER_KEY] longLongValue]; - int64_t newCounter = (oldCounter == INT64_MAX)?INT64_MIN:(oldCounter + 1); + oldCounter = [[self stringForKey:PASSWORD_COUNTER_KEY] longLongValue]; + int64_t newCounter = (oldCounter == INT64_MAX) ? INT64_MIN : (oldCounter + 1); [self storeString:[@(newCounter) stringValue] forKey:PASSWORD_COUNTER_KEY]; return newCounter; } -+ (void)setLocalNumberTo:(PhoneNumber *)localNumber{ - require(localNumber != nil); - require(localNumber.toE164!= nil); - - NSString *e164 = localNumber.toE164; - [self storeString:e164 forKey:LOCAL_NUMBER_KEY]; -} - -+ (PhoneNumber *)localNumber{ - NSString *lnString = [self stringForKey:LOCAL_NUMBER_KEY]; - checkOperation(lnString != nil ); - PhoneNumber *num = [PhoneNumber tryParsePhoneNumberFromE164:lnString]; - return lnString?num:nil; -} - -+(Zid *)zid{ - NSData *data = [self dataForKey:ZID_KEY]; - if (data.length != ZID_LENGTH) { - DDLogError(@"ZID length is incorrect. Is %lu, should be %d", (unsigned long)data.length, ZID_LENGTH); - } - Zid *zid = [Zid zidWithData:data]; - return zid; -} - - -+(NSData *)signalingCipherKey{ ++ (NSData *)signalingCipherKey { return [self dataForKey:SIGNALING_CIPHER_KEY andVerifyLength:SIGNALING_CIPHER_KEY_LENGTH]; } -+(NSData *)signalingMacKey{ ++ (NSData *)signalingMacKey { return [self dataForKey:SIGNALING_MAC_KEY andVerifyLength:SIGNALING_MAC_KEY_LENGTH]; } -+ (NSData *)signalingExtraKey{ ++ (NSData *)signalingExtraKey { return [self dataForKey:SIGNALING_EXTRA_KEY andVerifyLength:SIGNALING_EXTRA_KEY_LENGTH]; } -+(NSString *)serverAuthPassword{ ++ (NSString *)serverAuthPassword { NSString *password = [self stringForKey:SAVED_PASSWORD_KEY]; - NSData *data = [password decodedAsBase64Data]; + NSData *data = [password decodedAsBase64Data]; if (data.length != SAVED_PASSWORD_LENGTH) { - DDLogError(@"The server password has incorrect length. Is %lu but should be %d", (unsigned long)data.length, SAVED_PASSWORD_LENGTH); + DDLogError(@"The server password has incorrect length. Is %lu but should be %d", + (unsigned long)data.length, + SAVED_PASSWORD_LENGTH); } return password; } #pragma mark Keychain wrapper methods -+(void)storeData:(NSData*)data forKey:(NSString*)key{ ++ (void)storeData:(NSData *)data forKey:(NSString *)key { [TSStorageManager.sharedManager setObject:data forKey:key inCollection:SignalKeyingCollection]; } -+(NSData*)dataForKey:(NSString*)key andVerifyLength:(uint)length{ ++ (NSData *)dataForKey:(NSString *)key andVerifyLength:(uint)length { NSData *data = [self dataForKey:key]; - + if (data.length != length) { DDLogError(@"Length of data not matching. Got %lu, expected %u", (unsigned long)data.length, length); } - + return data; } -+(NSData*)dataForKey:(NSString*)key{ ++ (NSData *)dataForKey:(NSString *)key { return [TSStorageManager.sharedManager dataForKey:key inCollection:SignalKeyingCollection]; } -+(NSString*)stringForKey:(NSString*)key{ ++ (NSString *)stringForKey:(NSString *)key { return [TSStorageManager.sharedManager stringForKey:key inCollection:SignalKeyingCollection]; } -+(void)storeString:(NSString*)string forKey:(NSString*)key{ ++ (void)storeString:(NSString *)string forKey:(NSString *)key { [TSStorageManager.sharedManager setObject:string forKey:key inCollection:SignalKeyingCollection]; } diff --git a/Signal/src/environment/VersionMigrations.m b/Signal/src/environment/VersionMigrations.m index c2f6f107e..e64add923 100644 --- a/Signal/src/environment/VersionMigrations.m +++ b/Signal/src/environment/VersionMigrations.m @@ -12,124 +12,134 @@ #import "LockInteractionController.h" #import "PreferencesUtil.h" #import "PushManager.h" -#import "TSAccountManager.h" -#import "TSNetworkManager.h" #import "RecentCallManager.h" #import "SignalKeyingStorage.h" +#import "TSAccountManager.h" +#import "TSNetworkManager.h" -#define NEEDS_TO_REGISTER_PUSH_KEY @"Register For Push" +#define NEEDS_TO_REGISTER_PUSH_KEY @"Register For Push" #define NEEDS_TO_REGISTER_ATTRIBUTES @"Register Attributes" -@interface SignalKeyingStorage(VersionMigrations) +@interface SignalKeyingStorage (VersionMigrations) -+(void)storeString:(NSString*)string forKey:(NSString*)key; -+(void)storeData:(NSData*)data forKey:(NSString*)key; ++ (void)storeString:(NSString *)string forKey:(NSString *)key; ++ (void)storeData:(NSData *)data forKey:(NSString *)key; @end @implementation VersionMigrations #pragma mark Utility methods -+ (void)performUpdateCheck{ - NSString *previousVersion = Environment.preferences.lastRanVersion; - NSString *currentVersion = [Environment.preferences setAndGetCurrentVersion]; - BOOL VOIPRegistration = [[PushManager sharedManager] supportsVOIPPush] - && ![Environment.preferences hasRegisteredVOIPPush]; - ++ (void)performUpdateCheck { + NSString *previousVersion = Environment.preferences.lastRanVersion; + NSString *currentVersion = [Environment.preferences setAndGetCurrentVersion]; + BOOL VOIPRegistration = + [[PushManager sharedManager] supportsVOIPPush] && ![Environment.preferences hasRegisteredVOIPPush]; + if (!previousVersion) { DDLogError(@"No previous version found. Possibly first launch since install."); return; } - - if(([self isVersion:previousVersion atLeast:@"1.0.2" andLessThan:@"2.0"])) { + + if (([self isVersion:previousVersion atLeast:@"1.0.2" andLessThan:@"2.0"])) { // We don't migrate from RedPhone anymore, too painful to maintain. // Resetting the app data and quitting. [Environment resetAppData]; exit(0); } - + // VOIP Push might need to be enabled because 1) user ran old version 2) Update to compatible iOS version if (VOIPRegistration && [TSAccountManager isRegistered]) { [self nonBlockingPushRegistration]; } - + if ([self isVersion:previousVersion atLeast:@"2.0.0" andLessThan:@"2.1.70"] && [TSAccountManager isRegistered]) { [self clearVideoCache]; [self blockingAttributesUpdate]; } - + if ([self isVersion:previousVersion atLeast:@"2.0.0" andLessThan:@"2.3.0"] && [TSAccountManager isRegistered]) { NSFileManager *fm = [NSFileManager defaultManager]; - NSArray *cachesDir = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); - NSString *bloomFilterPath = [[cachesDir objectAtIndex:0] stringByAppendingPathComponent:@"bloomfilter"]; - [fm removeItemAtPath:bloomFilterPath error:nil]; - [[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction * _Nonnull transaction) { - [transaction removeAllObjectsInCollection:@"TSRecipient"]; + NSArray *cachesDir = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); + NSString *bloomFilterPath = [[cachesDir objectAtIndex:0] stringByAppendingPathComponent:@"bloomfilter"]; + [fm removeItemAtPath:bloomFilterPath error:nil]; + [[TSStorageManager sharedManager] + .dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { + [transaction removeAllObjectsInCollection:@"TSRecipient"]; }]; } } -+ (BOOL) isVersion:(NSString *)thisVersionString atLeast:(NSString *)openLowerBoundVersionString andLessThan:(NSString *)closedUpperBoundVersionString { - return [self isVersion:thisVersionString atLeast:openLowerBoundVersionString] && [self isVersion:thisVersionString lessThan:closedUpperBoundVersionString]; ++ (BOOL)isVersion:(NSString *)thisVersionString + atLeast:(NSString *)openLowerBoundVersionString + andLessThan:(NSString *)closedUpperBoundVersionString { + return [self isVersion:thisVersionString atLeast:openLowerBoundVersionString] && + [self isVersion:thisVersionString lessThan:closedUpperBoundVersionString]; } -+ (BOOL) isVersion:(NSString *)thisVersionString atLeast:(NSString *)thatVersionString { ++ (BOOL)isVersion:(NSString *)thisVersionString atLeast:(NSString *)thatVersionString { return [thisVersionString compare:thatVersionString options:NSNumericSearch] != NSOrderedAscending; } -+ (BOOL) isVersion:(NSString *)thisVersionString lessThan:(NSString *)thatVersionString { ++ (BOOL)isVersion:(NSString *)thisVersionString lessThan:(NSString *)thatVersionString { return [thisVersionString compare:thatVersionString options:NSNumericSearch] == NSOrderedAscending; } #pragma mark Upgrading to 2.1 - Needs to register VOIP token + Removing video cache folder -+ (void)nonBlockingPushRegistration{ - __block failedVerificationBlock failedBlock = ^(NSError *error) { - DDLogError(@"Failed to register VOIP push token: %@", error.debugDescription); ++ (void)nonBlockingPushRegistration { + __block failedBlock failedBlock = ^(NSError *error) { + DDLogError(@"Failed to register VOIP push token: %@", error.debugDescription); }; - [[PushManager sharedManager] requestPushTokenWithSuccess:^(NSData *pushToken, NSData *voipToken) { - [TSAccountManager registerForPushNotifications:pushToken voipToken:voipToken success:^{ - DDLogWarn(@"Registered for VOIP Push."); - } failure:failedBlock]; - } failure:failedBlock]; - + [[PushManager sharedManager] requestPushTokenWithSuccess:^(NSString *pushToken, NSString *voipToken) { + [TSAccountManager registerForPushNotifications:pushToken + voipToken:voipToken + success:^{ + DDLogWarn(@"Registered for VOIP Push."); + } + failure:failedBlock]; + } + failure:failedBlock]; } -+ (void)blockingPushRegistration{ - LIControllerBlockingOperation blockingOperation = ^BOOL(void){ - [[NSUserDefaults standardUserDefaults] setObject:@YES forKey:NEEDS_TO_REGISTER_PUSH_KEY]; - - __block dispatch_semaphore_t sema = dispatch_semaphore_create(0); - - __block BOOL success; - - __block failedVerificationBlock failedBlock = ^(NSError *error) { - success = NO; - dispatch_semaphore_signal(sema); - }; - - [[PushManager sharedManager] requestPushTokenWithSuccess:^(NSData *pushToken, NSData *voipToken) { - [TSAccountManager registerForPushNotifications:pushToken voipToken:voipToken success:^{ - success = YES; - dispatch_semaphore_signal(sema); - } failure:failedBlock]; - } failure:failedBlock]; - - dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); - - return success; ++ (void)blockingPushRegistration { + LIControllerBlockingOperation blockingOperation = ^BOOL(void) { + [[NSUserDefaults standardUserDefaults] setObject:@YES forKey:NEEDS_TO_REGISTER_PUSH_KEY]; + + __block dispatch_semaphore_t sema = dispatch_semaphore_create(0); + + __block BOOL success; + + __block failedBlock failedBlock = ^(NSError *error) { + success = NO; + dispatch_semaphore_signal(sema); + }; + + [[PushManager sharedManager] requestPushTokenWithSuccess:^(NSString *pushToken, NSString *voipToken) { + [TSAccountManager registerForPushNotifications:pushToken + voipToken:voipToken + success:^{ + success = YES; + dispatch_semaphore_signal(sema); + } + failure:failedBlock]; + } + failure:failedBlock]; + + dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); + + return success; }; - + LIControllerRetryBlock retryBlock = [LockInteractionController defaultNetworkRetry]; - + [LockInteractionController performBlock:blockingOperation completionBlock:^{ - [[NSUserDefaults standardUserDefaults] removeObjectForKey:NEEDS_TO_REGISTER_PUSH_KEY]; - DDLogWarn(@"Successfully migrated to 2.1"); + [[NSUserDefaults standardUserDefaults] removeObjectForKey:NEEDS_TO_REGISTER_PUSH_KEY]; + DDLogWarn(@"Successfully migrated to 2.1"); } retryBlock:retryBlock usesNetwork:YES]; - } + (BOOL)needsRegisterPush { @@ -137,15 +147,15 @@ } + (void)clearVideoCache { - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil; - basePath = [basePath stringByAppendingPathComponent:@"videos"]; - + basePath = [basePath stringByAppendingPathComponent:@"videos"]; + NSError *error; - if([[NSFileManager defaultManager] fileExistsAtPath:basePath]){ + if ([[NSFileManager defaultManager] fileExistsAtPath:basePath]) { [NSFileManager.defaultManager removeItemAtPath:basePath error:&error]; } - + if (error) { DDLogError(@"An error occured while removing the videos cache folder from old location: %@", error.debugDescription); @@ -159,46 +169,47 @@ } + (void)blockingAttributesUpdate { - LIControllerBlockingOperation blockingOperation = ^BOOL(void){ - [[NSUserDefaults standardUserDefaults] setObject:@YES forKey:NEEDS_TO_REGISTER_ATTRIBUTES]; - - __block dispatch_semaphore_t sema = dispatch_semaphore_create(0); - - __block BOOL success; - - TSUpdateAttributesRequest *request = [[TSUpdateAttributesRequest alloc] initWithUpdatedAttributes]; - [[TSNetworkManager sharedManager] queueAuthenticatedRequest:request success:^(NSURLSessionDataTask *task, id responseObject) { + LIControllerBlockingOperation blockingOperation = ^BOOL(void) { + [[NSUserDefaults standardUserDefaults] setObject:@YES forKey:NEEDS_TO_REGISTER_ATTRIBUTES]; + + __block dispatch_semaphore_t sema = dispatch_semaphore_create(0); + + __block BOOL success; + + TSUpdateAttributesRequest *request = [[TSUpdateAttributesRequest alloc] initWithUpdatedAttributesWithVoice:YES]; + [[TSNetworkManager sharedManager] makeRequest:request + success:^(NSURLSessionDataTask *task, id responseObject) { success = YES; dispatch_semaphore_signal(sema); - } failure:^(NSURLSessionDataTask *task, NSError *error) { + } + failure:^(NSURLSessionDataTask *task, NSError *error) { success = NO; DDLogError(@"Updating attributess failed with error: %@", error.description); dispatch_semaphore_signal(sema); - }]; - - - dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); - - return success; + }]; + + + dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); + + return success; }; - + LIControllerRetryBlock retryBlock = [LockInteractionController defaultNetworkRetry]; - + [LockInteractionController performBlock:blockingOperation completionBlock:^{ - [[NSUserDefaults standardUserDefaults] removeObjectForKey:NEEDS_TO_REGISTER_ATTRIBUTES]; - DDLogWarn(@"Successfully updated attributes."); + [[NSUserDefaults standardUserDefaults] removeObjectForKey:NEEDS_TO_REGISTER_ATTRIBUTES]; + DDLogWarn(@"Successfully updated attributes."); } retryBlock:retryBlock usesNetwork:YES]; - } #pragma mark Util -+ (BOOL)userDefaultsBoolForKey:(NSString*)key { ++ (BOOL)userDefaultsBoolForKey:(NSString *)key { NSNumber *num = [[NSUserDefaults standardUserDefaults] objectForKey:key]; - + if (!num) { return NO; } else { diff --git a/Signal/src/environment/iOSVersions.h b/Signal/src/environment/iOSVersions.h index 5f0e0d447..a8ebb772f 100644 --- a/Signal/src/environment/iOSVersions.h +++ b/Signal/src/environment/iOSVersions.h @@ -100,21 +100,3 @@ #ifdef NSFoundationVersionNumber_iOS_9 #define _iOS_9 NSFoundationVersionNumber_iOS_9 #endif - -/** - Add a Singelton implementation to the .m File - */ - -#define MacrosSingletonImplemention \ -+ (instancetype)sharedInstance { \ -\ -static dispatch_once_t onceToken; \ -static id sharedInstance = nil; \ -dispatch_once(&onceToken, ^{ \ -sharedInstance = [self.class new]; \ -}); \ -\ -return sharedInstance; \ -} - -#define MacrosSingletonInterface + (instancetype)sharedInstance; diff --git a/Signal/src/network/AFSecurityOWSPolicy.h b/Signal/src/network/AFSecurityOWSPolicy.h deleted file mode 100644 index 85e104510..000000000 --- a/Signal/src/network/AFSecurityOWSPolicy.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// AFSecurityPolicyNone.h -// Signal -// -// Created by Fred on 01/09/15. -// Copyright © 2015 Open Whisper Systems. All rights reserved. -// - -#import "AFSecurityPolicy.h" -#import - -@interface AFSecurityOWSPolicy : AFSecurityPolicy - -+ (instancetype)OWS_PinningPolicy; - -@end diff --git a/Signal/src/network/AFSecurityOWSPolicy.m b/Signal/src/network/AFSecurityOWSPolicy.m deleted file mode 100644 index 7607ae249..000000000 --- a/Signal/src/network/AFSecurityOWSPolicy.m +++ /dev/null @@ -1,100 +0,0 @@ -// -// AFSecurityPolicyNone.m -// Signal -// -// Created by Fred on 01/09/15. -// Copyright © 2015 Open Whisper Systems. All rights reserved. -// - -#import "AFSecurityOWSPolicy.h" -#import - -@implementation AFSecurityOWSPolicy - -+ (instancetype)OWS_PinningPolicy { - static AFSecurityOWSPolicy *sharedMyManager = nil; - @synchronized(self) { - if (sharedMyManager == nil) - sharedMyManager = [[self alloc] initWithOWSPolicy]; - } - return sharedMyManager; -} - -- (instancetype)initWithOWSPolicy { - self = [[super class] defaultPolicy]; - - if (self) { - self.pinnedCertificates = @[[self certificateDataForService:@"textsecure"], - [self certificateDataForService:@"redphone"]]; - } - - return self; -} - -- (NSArray*)certs { - return @[(__bridge id)[self certificateForService:@"textsecure"]]; -} - -- (NSData*)certificateDataForService:(NSString*)service -{ - SecCertificateRef certRef = [self certificateForService:service]; - return (__bridge_transfer NSData *)SecCertificateCopyData(certRef); -} - -- (SecCertificateRef)certificateForService:(NSString*)service { - NSString *path = [NSBundle.mainBundle pathForResource:service ofType:@"cer"]; - - if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { - @throw [NSException exceptionWithName:@"Missing server certificate" - reason:[NSString stringWithFormat:@"Missing signing certificate for service %@", service] - userInfo:nil]; - } - - NSData *certificateData = [NSData dataWithContentsOfFile:path]; - return SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(certificateData)); -} - - - -- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust - forDomain:(NSString *)domain -{ - NSMutableArray *policies = [NSMutableArray array]; - [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)]; - - if (SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies) != errSecSuccess){ - DDLogError(@"The trust policy couldn't be set."); - return NO; - } - - NSMutableArray *pinnedCertificates = [NSMutableArray array]; - for (NSData *certificateData in self.pinnedCertificates) { - [pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData)]; - } - - if (SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates) != errSecSuccess){ - DDLogError(@"The anchor certificates couldn't be set."); - return NO; - } - - if (!AFServerTrustIsValid(serverTrust)) { - NSLog(@"Fuck it, not trusted"); - return NO; - } - - return YES; -} - - -static BOOL AFServerTrustIsValid(SecTrustRef serverTrust) { - BOOL isValid = NO; - SecTrustResultType result; - __Require_noErr_Quiet(SecTrustEvaluate(serverTrust, &result), _out); - - isValid = (result == kSecTrustResultUnspecified); - -_out: - return isValid; -} - -@end diff --git a/Signal/src/network/IpAddress.m b/Signal/src/network/IpAddress.m index b1ec686ba..9f278d419 100644 --- a/Signal/src/network/IpAddress.m +++ b/Signal/src/network/IpAddress.m @@ -10,20 +10,20 @@ return [IpAddress ipv4AddressFromString:LOCAL_HOST_IP]; } +(IpAddress*) ipAddressFromString:(NSString*)text { - require(text != nil); + ows_require(text != nil); if ([IpAddress isIpv4Text:text]) return [IpAddress ipv4AddressFromString:text]; if ([IpAddress isIpv6Text:text]) return [IpAddress ipv6AddressFromString:text]; [BadArgument raise:[NSString stringWithFormat:@"Invalid IP address: %@", text]]; return nil; } +(IpAddress*) tryGetIpAddressFromString:(NSString*)text { - require(text != nil); + ows_require(text != nil); if ([IpAddress isIpv4Text:text]) return [IpAddress ipv4AddressFromString:text]; if ([IpAddress isIpv6Text:text]) return [IpAddress ipv6AddressFromString:text]; return nil; } +(IpAddress*) ipv4AddressFromString:(NSString*)text { - require(text != nil); + ows_require(text != nil); IpAddress* a = [IpAddress new]; @@ -45,7 +45,7 @@ return a; } +(IpAddress*) ipv6AddressFromString:(NSString*)text { - require(text != nil); + ows_require(text != nil); IpAddress* a = [IpAddress new]; @@ -112,12 +112,12 @@ } +(bool) isIpv4Text:(NSString*)text { - require(text != nil); + ows_require(text != nil); struct sockaddr_in s; return inet_pton(AF_INET, [text UTF8String], &(s.sin_addr)) == 1; } +(bool) isIpv6Text:(NSString*)text { - require(text != nil); + ows_require(text != nil); struct sockaddr_in6 s; return inet_pton(AF_INET6, [text UTF8String], &(s.sin6_addr)) == 1; } diff --git a/Signal/src/network/IpEndPoint.m b/Signal/src/network/IpEndPoint.m index db13d573d..a6fd85ef9 100644 --- a/Signal/src/network/IpEndPoint.m +++ b/Signal/src/network/IpEndPoint.m @@ -7,7 +7,7 @@ +(IpEndPoint*) ipEndPointAtAddress:(IpAddress*)address onPort:(in_port_t)port { - require(address != nil); + ows_require(address != nil); IpEndPoint* p = [IpEndPoint new]; p->address = address; p->port = port; @@ -28,8 +28,8 @@ } +(IpEndPoint*) ipEndPointFromSockaddrData:(NSData*)sockaddrData { - require(sockaddrData != nil); - require(sockaddrData.length >= sizeof(struct sockaddr)); + ows_require(sockaddrData != nil); + ows_require(sockaddrData.length >= sizeof(struct sockaddr)); struct sockaddr s; memcpy(&s, [sockaddrData bytes], sizeof(struct sockaddr)); @@ -41,8 +41,8 @@ return nil; } +(IpEndPoint*) ipv4EndPointFromSockaddrData:(NSData*)sockaddrData { - require(sockaddrData != nil); - require(sockaddrData.length >= sizeof(struct sockaddr_in)); + ows_require(sockaddrData != nil); + ows_require(sockaddrData.length >= sizeof(struct sockaddr_in)); struct sockaddr_in s; memcpy(&s, [sockaddrData bytes], sizeof(struct sockaddr_in)); @@ -50,8 +50,8 @@ return [[IpAddress ipv4AddressFromSockaddr:s] withPort:ntohs(s.sin_port)]; } +(IpEndPoint*) ipv6EndPointFromSockaddrData:(NSData*)sockaddrData { - require(sockaddrData != nil); - require(sockaddrData.length >= sizeof(struct sockaddr_in6)); + ows_require(sockaddrData != nil); + ows_require(sockaddrData.length >= sizeof(struct sockaddr_in6)); struct sockaddr_in6 s; memcpy(&s, [sockaddrData bytes], sizeof(struct sockaddr_in6)); diff --git a/Signal/src/network/PacketHandler.m b/Signal/src/network/PacketHandler.m index 4e472eb07..1e763421c 100644 --- a/Signal/src/network/PacketHandler.m +++ b/Signal/src/network/PacketHandler.m @@ -8,8 +8,8 @@ +(PacketHandler*) packetHandler:(PacketHandlerBlock)dataHandler withErrorHandler:(ErrorHandlerBlock)errorHandler { - require(dataHandler != nil); - require(errorHandler != nil); + ows_require(dataHandler != nil); + ows_require(errorHandler != nil); PacketHandler* p = [PacketHandler new]; p->dataHandler = [dataHandler copy]; diff --git a/Signal/src/network/PushManager.h b/Signal/src/network/PushManager.h index 7095a3399..0f1adb672 100644 --- a/Signal/src/network/PushManager.h +++ b/Signal/src/network/PushManager.h @@ -9,26 +9,25 @@ #import #import -#define Signal_Thread_UserInfo_Key @"Signal_Thread_Id" -#define Signal_Message_UserInfo_Key @"Signal_Message_Id" +#define Signal_Thread_UserInfo_Key @"Signal_Thread_Id" +#define Signal_Message_UserInfo_Key @"Signal_Message_Id" -#define Signal_Call_UserInfo_Key @"Signal_Call_Id" +#define Signal_Call_UserInfo_Key @"Signal_Call_Id" -#define Signal_Call_Accept_Identifier @"Signal_Call_Accept" -#define Signal_Call_Decline_Identifier @"Signal_Call_Decline" +#define Signal_Call_Accept_Identifier @"Signal_Call_Accept" +#define Signal_Call_Decline_Identifier @"Signal_Call_Decline" -#define Signal_CallBack_Identifier @"Signal_CallBack" +#define Signal_CallBack_Identifier @"Signal_CallBack" -#define Signal_Call_Category @"Signal_IncomingCall" -#define Signal_Full_New_Message_Category @"Signal_Full_New_Message" -#define Signal_CallBack_Category @"Signal_CallBack" +#define Signal_Call_Category @"Signal_IncomingCall" +#define Signal_Full_New_Message_Category @"Signal_Full_New_Message" +#define Signal_CallBack_Category @"Signal_CallBack" -#define Signal_Message_Reply_Identifier @"Signal_New_Message_Reply" +#define Signal_Message_Reply_Identifier @"Signal_New_Message_Reply" #define Signal_Message_MarkAsRead_Identifier @"Signal_Message_MarkAsRead" -typedef void(^failedPushRegistrationBlock)(NSError *error); -typedef void (^pushTokensSuccessBlock)(NSData *pushToken, NSData *voipToken); -typedef void (^registrationTokensSuccessBlock)(NSData *pushToken, NSData *voipToken, NSString *signupToken); +typedef void (^failedPushRegistrationBlock)(NSError *error); +typedef void (^pushTokensSuccessBlock)(NSString *pushToken, NSString *voipToken); /** * The Push Manager is responsible for registering the device for Signal push notifications. @@ -36,16 +35,7 @@ typedef void (^registrationTokensSuccessBlock)(NSData *pushToken, NSData *voipTo @interface PushManager : NSObject -+ (PushManager*)sharedManager; - -/** - * Registers the push token with the RedPhone server, then returns the push token and a signup token to be used to register with TextSecure. - * - * @param success Success completion block - registering with TextSecure server - * @param failure Failure completion block - */ - -- (void)registrationAndRedPhoneTokenRequestWithSuccess:(registrationTokensSuccessBlock)success failure:(failedPushRegistrationBlock)failure; ++ (PushManager *)sharedManager; /** * Returns the Push Notification Token of this device @@ -54,10 +44,11 @@ typedef void (^registrationTokensSuccessBlock)(NSData *pushToken, NSData *voipTo * @param failure Failure block, executed when failed to get push token */ -- (void)requestPushTokenWithSuccess:(pushTokensSuccessBlock)success failure:(void(^)(NSError *))failure; +- (void)requestPushTokenWithSuccess:(pushTokensSuccessBlock)success failure:(void (^)(NSError *))failure; /** - * Registers for Users Notifications. By doing this on launch, we are sure that the correct categories of user notifications is registered. + * Registers for Users Notifications. By doing this on launch, we are sure that the correct categories of user + * notifications is registered. */ - (void)validateUserNotificationSettings; @@ -70,17 +61,26 @@ typedef void (^registrationTokensSuccessBlock)(NSData *pushToken, NSData *voipTo @property TOCFutureSource *userNotificationFutureSource; @property TOCFutureSource *pushKitNotificationFutureSource; --(TOCFuture*)registerPushKitNotificationFuture; +- (TOCFuture *)registerPushKitNotificationFuture; - (BOOL)supportsVOIPPush; -- (UILocalNotification*)closeVOIPBackgroundTask; -- (void)presentNotification:(UILocalNotification*)notification; +- (UILocalNotification *)closeVOIPBackgroundTask; +- (void)presentNotification:(UILocalNotification *)notification; #pragma mark Push Notifications Delegate Methods - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo; -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler; -- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler; +- (void)application:(UIApplication *)application + didReceiveRemoteNotification:(NSDictionary *)userInfo + fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler; +- (void)application:(UIApplication *)application + handleActionWithIdentifier:(NSString *)identifier + forLocalNotification:(UILocalNotification *)notification + completionHandler:(void (^)())completionHandler; - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification; -- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler; +- (void)application:(UIApplication *)application + handleActionWithIdentifier:(NSString *)identifier + forLocalNotification:(UILocalNotification *)notification + withResponseInfo:(NSDictionary *)responseInfo + completionHandler:(void (^)())completionHandler; @end diff --git a/Signal/src/network/PushManager.m b/Signal/src/network/PushManager.m index c42a5467e..601be9791 100644 --- a/Signal/src/network/PushManager.m +++ b/Signal/src/network/PushManager.m @@ -11,21 +11,21 @@ #import "AppDelegate.h" #import "ContactsManager.h" #import "InCallViewController.h" +#import "NSData+ows_StripToken.h" #import "NSDate+millisecondTimeStamp.h" -#import "TSMessagesManager+sendMessages.h" #import "NotificationTracker.h" - #import "PreferencesUtil.h" #import "PushManager.h" #import "RPServerRequestsManager.h" +#import "TSMessagesManager+sendMessages.h" #import "TSSocketManager.h" #define pushManagerDomain @"org.whispersystems.pushmanager" @interface PushManager () -@property TOCFutureSource *registerWithServerFutureSource; -@property UIAlertView *missingPermissionsAlertView; +@property TOCFutureSource *registerWithServerFutureSource; +@property UIAlertView *missingPermissionsAlertView; @property (nonatomic, strong) NotificationTracker *notificationTracker; @property UILocalNotification *lastCallNotification; @property (nonatomic, retain) NSMutableArray *currentNotifications; @@ -35,28 +35,26 @@ @implementation PushManager -+ (instancetype)sharedManager -{ ++ (instancetype)sharedManager { static PushManager *sharedManager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - sharedManager = [self new]; + sharedManager = [self new]; }); return sharedManager; } -- (instancetype)init -{ +- (instancetype)init { self = [super init]; if (self) { self.notificationTracker = [NotificationTracker notificationTracker]; self.missingPermissionsAlertView = - [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"ACTION_REQUIRED_TITLE", @"") - message:NSLocalizedString(@"PUSH_SETTINGS_MESSAGE", @"") - delegate:nil - cancelButtonTitle:NSLocalizedString(@"OK", @"") - otherButtonTitles:nil, nil]; - _callBackgroundTask = UIBackgroundTaskInvalid; + [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"ACTION_REQUIRED_TITLE", @"") + message:NSLocalizedString(@"PUSH_SETTINGS_MESSAGE", @"") + delegate:nil + cancelButtonTitle:NSLocalizedString(@"OK", @"") + otherButtonTitles:nil, nil]; + _callBackgroundTask = UIBackgroundTaskInvalid; self.currentNotifications = [NSMutableArray array]; } return self; @@ -64,55 +62,58 @@ #pragma mark Manage Incoming Push --(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { if ([self isRedPhonePush:userInfo]) { - ResponderSessionDescriptor* call; - if (![self.notificationTracker shouldProcessNotification:userInfo]){ + ResponderSessionDescriptor *call; + if (![self.notificationTracker shouldProcessNotification:userInfo]) { return; } - + @try { call = [ResponderSessionDescriptor responderSessionDescriptorFromEncryptedRemoteNotification:userInfo]; DDLogDebug(@"Received remote notification. Parsed session descriptor: %@.", call); - } @catch (OperationFailed* ex) { + } @catch (OperationFailed *ex) { DDLogError(@"Error parsing remote notification. Error: %@.", ex); return; } - + if (!call) { DDLogError(@"Decryption of session descriptor failed"); return; } - + [Environment.phoneManager incomingCallWithSession:call]; - + if (![self applicationIsActive]) { UILocalNotification *notification = [[UILocalNotification alloc] init]; - - NSString *callerId = call.initiatorNumber.toE164; + + NSString *callerId = call.initiatorNumber.toE164; NSString *nameString = [[Environment getCurrent].contactsManager nameStringForPhoneIdentifier:callerId]; - - NSString *displayName = nameString?nameString:callerId; + + NSString *displayName = nameString ? nameString : callerId; PropertyListPreferences *prefs = [Environment preferences]; - + notification.alertBody = @"☎️ "; - + if ([prefs notificationPreviewType] == NotificationNoNameNoPreview) { - notification.alertBody = [notification.alertBody stringByAppendingString:NSLocalizedString(@"INCOMING_CALL", nil)]; + notification.alertBody = + [notification.alertBody stringByAppendingString:NSLocalizedString(@"INCOMING_CALL", nil)]; } else { - notification.alertBody = [notification.alertBody stringByAppendingString:[NSString stringWithFormat:NSLocalizedString(@"INCOMING_CALL_FROM", nil), displayName]]; + notification.alertBody = [notification.alertBody + stringByAppendingString:[NSString stringWithFormat:NSLocalizedString(@"INCOMING_CALL_FROM", nil), + displayName]]; } - + notification.category = Signal_Call_Category; notification.soundName = @"r.caf"; - + [[PushManager sharedManager] presentNotification:notification]; _lastCallNotification = notification; - + if (_callBackgroundTask == UIBackgroundTaskInvalid) { _callBackgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ - [Environment.phoneManager backgroundTimeExpired]; - [self closeVOIPBackgroundTask]; + [Environment.phoneManager backgroundTimeExpired]; + [self closeVOIPBackgroundTask]; }]; } } @@ -123,30 +124,32 @@ } } -- (UILocalNotification*)closeVOIPBackgroundTask { +- (UILocalNotification *)closeVOIPBackgroundTask { [[UIApplication sharedApplication] endBackgroundTask:_callBackgroundTask]; _callBackgroundTask = UIBackgroundTaskInvalid; - + UILocalNotification *notif = _lastCallNotification; _lastCallNotification = nil; - + return notif; } /** - * This code should in principle never be called. The only cases where it would be called are with the old-style "content-available:1" pushes if there is no "voip" token registered + * This code should in principle never be called. The only cases where it would be called are with the old-style + * "content-available:1" pushes if there is no "voip" token registered * */ -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { +- (void)application:(UIApplication *)application + didReceiveRemoteNotification:(NSDictionary *)userInfo + fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { if ([self isRedPhonePush:userInfo]) { [self application:application didReceiveRemoteNotification:userInfo]; } - - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 20 * NSEC_PER_SEC), - dispatch_get_main_queue(), ^{ - completionHandler(UIBackgroundFetchResultNewData); - }); + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 20 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + completionHandler(UIBackgroundFetchResultNewData); + }); } - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { @@ -156,99 +159,118 @@ } } -- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler { - [self application:application handleActionWithIdentifier:identifier forLocalNotification:notification withResponseInfo:@{} completionHandler:completionHandler]; +- (void)application:(UIApplication *)application + handleActionWithIdentifier:(NSString *)identifier + forLocalNotification:(UILocalNotification *)notification + completionHandler:(void (^)())completionHandler { + [self application:application + handleActionWithIdentifier:identifier + forLocalNotification:notification + withResponseInfo:@{} + completionHandler:completionHandler]; } -- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler { - - +- (void)application:(UIApplication *)application + handleActionWithIdentifier:(NSString *)identifier + forLocalNotification:(UILocalNotification *)notification + withResponseInfo:(NSDictionary *)responseInfo + completionHandler:(void (^)())completionHandler { if ([identifier isEqualToString:Signal_Message_Reply_Identifier]) { NSString *threadId = notification.userInfo[Signal_Thread_UserInfo_Key]; - + if (threadId) { TSThread *thread = [TSThread fetchObjectWithUniqueID:threadId]; - TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:thread messageBody:responseInfo[UIUserNotificationActionResponseTypedTextKey] attachments:nil]; - [[TSMessagesManager sharedManager] sendMessage:message inThread:thread success:^{ - [self markAllInThreadAsRead:notification.userInfo completionHandler:completionHandler]; - [[[[Environment getCurrent] signalsViewController] tableView] reloadData]; - } failure:^{ - UILocalNotification *failedSendNotif = [[UILocalNotification alloc] init]; - failedSendNotif.alertBody = [NSString stringWithFormat:NSLocalizedString(@"NOTIFICATION_SEND_FAILED", nil), [thread name]]; - failedSendNotif.userInfo = @{Signal_Thread_UserInfo_Key:thread.uniqueId}; - [[PushManager sharedManager] presentNotification:failedSendNotif]; - completionHandler(); - }]; + TSOutgoingMessage *message = + [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] + inThread:thread + messageBody:responseInfo[UIUserNotificationActionResponseTypedTextKey] + attachments:nil]; + [[TSMessagesManager sharedManager] sendMessage:message + inThread:thread + success:^{ + [self markAllInThreadAsRead:notification.userInfo completionHandler:completionHandler]; + [[[[Environment getCurrent] signalsViewController] tableView] reloadData]; + } + failure:^{ + UILocalNotification *failedSendNotif = [[UILocalNotification alloc] init]; + failedSendNotif.alertBody = + [NSString stringWithFormat:NSLocalizedString(@"NOTIFICATION_SEND_FAILED", nil), [thread name]]; + failedSendNotif.userInfo = @{Signal_Thread_UserInfo_Key : thread.uniqueId}; + [[PushManager sharedManager] presentNotification:failedSendNotif]; + completionHandler(); + }]; } } else if ([identifier isEqualToString:Signal_Call_Accept_Identifier]) { [Environment.phoneManager answerCall]; - + completionHandler(); - } else if ([identifier isEqualToString:Signal_Call_Decline_Identifier]){ + } else if ([identifier isEqualToString:Signal_Call_Decline_Identifier]) { [Environment.phoneManager hangupOrDenyCall]; - - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), - dispatch_get_main_queue(), ^{ - completionHandler(); - }); - } else if([identifier isEqualToString:Signal_CallBack_Identifier]){ - NSString * contactId = notification.userInfo[Signal_Call_UserInfo_Key]; - PhoneNumber *number = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:contactId]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + completionHandler(); + }); + } else if ([identifier isEqualToString:Signal_CallBack_Identifier]) { + NSString *contactId = notification.userInfo[Signal_Call_UserInfo_Key]; + PhoneNumber *number = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:contactId]; Contact *contact = [[Environment.getCurrent contactsManager] latestContactForPhoneNumber:number]; [Environment.phoneManager initiateOutgoingCallToContact:contact atRemoteNumber:number]; - } else if ([identifier isEqualToString:Signal_Message_MarkAsRead_Identifier]){ + } else if ([identifier isEqualToString:Signal_Message_MarkAsRead_Identifier]) { [self markAllInThreadAsRead:notification.userInfo completionHandler:completionHandler]; } else { NSString *threadId = notification.userInfo[Signal_Thread_UserInfo_Key]; [Environment messageThreadId:threadId]; completionHandler(); } - } -- (void)markAllInThreadAsRead:(NSDictionary*)userInfo completionHandler:(void (^)())completionHandler { +- (void)markAllInThreadAsRead:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler { NSString *threadId = userInfo[Signal_Thread_UserInfo_Key]; - + TSThread *thread = [TSThread fetchObjectWithUniqueID:threadId]; - [[TSStorageManager sharedManager].dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction * _Nonnull transaction) { - [thread markAllAsReadWithTransaction:transaction]; - } completionBlock:^{ - [[[Environment getCurrent] signalsViewController] updateInboxCountLabel]; - [self cancelNotificationsWithThreadId:threadId]; - - completionHandler(); - }]; + [[TSStorageManager sharedManager] + .dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { + [thread markAllAsReadWithTransaction:transaction]; + } + completionBlock:^{ + [[[Environment getCurrent] signalsViewController] updateInboxCountLabel]; + [self cancelNotificationsWithThreadId:threadId]; + + completionHandler(); + }]; } -- (BOOL)isRedPhonePush:(NSDictionary*)pushDict { +- (BOOL)isRedPhonePush:(NSDictionary *)pushDict { NSDictionary *aps = pushDict[@"aps"]; NSString *category = aps[@"category"]; - + if ([category isEqualToString:Signal_Call_Category]) { return YES; - } else{ + } else { return NO; } } #pragma mark PushKit -- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type -{ - [[PushManager sharedManager].pushKitNotificationFutureSource trySetResult:credentials.token]; +- (void)pushRegistry:(PKPushRegistry *)registry + didUpdatePushCredentials:(PKPushCredentials *)credentials + forType:(NSString *)type { + [[PushManager sharedManager].pushKitNotificationFutureSource trySetResult:[credentials.token ows_tripToken]]; } --(void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type -{ +- (void)pushRegistry:(PKPushRegistry *)registry + didReceiveIncomingPushWithPayload:(PKPushPayload *)payload + forType:(NSString *)type { [self application:[UIApplication sharedApplication] didReceiveRemoteNotification:payload.dictionaryPayload]; } -- (TOCFuture*)registerPushKitNotificationFuture{ +- (TOCFuture *)registerPushKitNotificationFuture { if ([self supportsVOIPPush]) { self.pushKitNotificationFutureSource = [TOCFutureSource new]; - PKPushRegistry* voipRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()]; - voipRegistry.delegate = self; - voipRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP]; + PKPushRegistry *voipRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()]; + voipRegistry.delegate = self; + voipRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP]; return self.pushKitNotificationFutureSource.future; } else { TOCFutureSource *futureSource = [TOCFutureSource new]; @@ -268,253 +290,163 @@ #pragma mark Register device for Push Notification locally -- (TOCFuture *)registerPushNotificationFuture -{ +- (TOCFuture *)registerPushNotificationFuture { self.pushNotificationFutureSource = [TOCFutureSource new]; [UIApplication.sharedApplication registerForRemoteNotifications]; - return self.pushNotificationFutureSource.future; } -- (void)requestPushTokenWithSuccess:(pushTokensSuccessBlock)success failure:(failedPushRegistrationBlock)failure -{ - TOCFuture *requestPushTokenFuture = [self registerPushNotificationFuture]; - - [requestPushTokenFuture catchDo:^(id failureObj) { - [self.missingPermissionsAlertView show]; - failure(failureObj); - DDLogError(@"This should not happen on iOS8. No push token was provided"); - }]; - - [requestPushTokenFuture thenDo:^(NSData *pushToken) { - TOCFuture *voipPushTokenFuture = [self registerPushKitNotificationFuture]; - - [voipPushTokenFuture finallyDo:^(TOCFuture *completed) { - NSData *voipPushToken = completed.hasResult?completed.forceGetResult:nil; - - TOCFuture *registerPushTokenFuture = [self registerForPushFutureWithToken:pushToken voipToken:voipPushToken]; - - [registerPushTokenFuture catchDo:^(id failureObj) { - failure(failureObj); - }]; - - [registerPushTokenFuture thenDo:^(id value) { - TOCFuture *userRegistration = [self registerForUserNotificationsFuture]; - - [userRegistration thenDo:^(UIUserNotificationSettings *userNotificationSettings) { - success(pushToken, voipPushToken); - }]; - }]; - }]; - }]; -} - -- (void)registrationAndRedPhoneTokenRequestWithSuccess:(registrationTokensSuccessBlock)success - failure:(failedPushRegistrationBlock)failure -{ +- (void)requestPushTokenWithSuccess:(pushTokensSuccessBlock)success failure:(failedPushRegistrationBlock)failure { if (!self.wantRemoteNotifications) { - NSData *fakeToken = [@"Fake PushToken" dataUsingEncoding:NSUTF8StringEncoding]; - [self registerTokenWithRedPhoneServer:fakeToken - voipToken:fakeToken - withSuccess:success - failure:failure]; - + success(@"FakeToken", @"FakePushToken"); return; } - - [self requestPushTokenWithSuccess:^(NSData *pushToken, NSData *voipToken) { - [self registerTokenWithRedPhoneServer:pushToken voipToken:voipToken withSuccess:success failure:failure]; - } failure:^(NSError *error) { - [self.missingPermissionsAlertView show]; - failure([NSError errorWithDomain:pushManagerDomain code:400 userInfo:@{}]); + + TOCFuture *requestPushTokenFuture = [self registerPushNotificationFuture]; + + [requestPushTokenFuture thenDo:^(NSData *pushTokenData) { + NSString *pushToken = [pushTokenData ows_tripToken]; + TOCFuture *pushKit = [self registerPushKitNotificationFuture]; + + [pushKit thenDo:^(NSString *voipToken) { + success(pushToken, voipToken); + }]; + + [pushKit catchDo:^(NSError *error) { + failure(error); + }]; + }]; + + [requestPushTokenFuture catchDo:^(NSError *error) { + failure(error); }]; } -- (void)registerTokenWithRedPhoneServer:(NSData*)pushToken - voipToken:(NSData*)voipToken - withSuccess:(registrationTokensSuccessBlock)success - failure:(failedPushRegistrationBlock)failure -{ - [RPServerRequestsManager.sharedInstance performRequest:[RPAPICall requestTextSecureVerificationCode] - success:^(NSURLSessionDataTask *task, id responseObject) { - NSError *error; - - NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:&error]; - NSString *tsToken = dictionary[@"token"]; - - if (!tsToken || !pushToken || error) { - failure(error); - return; - } - - success(pushToken, voipToken, tsToken); - } - failure:^(NSURLSessionDataTask *task, NSError *error) { - failure(error); - }]; -} - -- (TOCFuture *)registerForUserNotificationsFuture -{ +- (TOCFuture *)registerForUserNotificationsFuture { self.userNotificationFutureSource = [TOCFutureSource new]; - + UIUserNotificationSettings *settings = - [UIUserNotificationSettings settingsForTypes:(UIUserNotificationType)[self allNotificationTypes] - categories:[NSSet setWithObjects:[self userNotificationsCallCategory], - [self fullNewMessageNotificationCategory], - [self userNotificationsCallBackCategory], nil]]; - + [UIUserNotificationSettings settingsForTypes:(UIUserNotificationType)[self allNotificationTypes] + categories:[NSSet setWithObjects:[self userNotificationsCallCategory], + [self fullNewMessageNotificationCategory], + [self userNotificationsCallBackCategory], + nil]]; + [UIApplication.sharedApplication registerUserNotificationSettings:settings]; return self.userNotificationFutureSource.future; } -- (UIUserNotificationCategory*)fullNewMessageNotificationCategory { +- (UIUserNotificationCategory *)fullNewMessageNotificationCategory { UIMutableUserNotificationAction *action_markRead = [UIMutableUserNotificationAction new]; action_markRead.identifier = Signal_Message_MarkAsRead_Identifier; action_markRead.title = NSLocalizedString(@"PUSH_MANAGER_MARKREAD", nil); action_markRead.destructive = NO; action_markRead.authenticationRequired = NO; action_markRead.activationMode = UIUserNotificationActivationModeBackground; - - UIMutableUserNotificationAction *action_reply = [UIMutableUserNotificationAction new]; - action_reply.identifier = Signal_Message_Reply_Identifier; - action_reply.title = NSLocalizedString(@"PUSH_MANAGER_REPLY", @""); - action_reply.destructive = NO; - action_reply.authenticationRequired = NO; // Since YES is broken in iOS 9 GM + + UIMutableUserNotificationAction *action_reply = [UIMutableUserNotificationAction new]; + action_reply.identifier = Signal_Message_Reply_Identifier; + action_reply.title = NSLocalizedString(@"PUSH_MANAGER_REPLY", @""); + action_reply.destructive = NO; + action_reply.authenticationRequired = NO; // Since YES is broken in iOS 9 GM if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(_iOS_9)) { - action_reply.behavior = UIUserNotificationActionBehaviorTextInput; - action_reply.activationMode = UIUserNotificationActivationModeBackground; + action_reply.behavior = UIUserNotificationActionBehaviorTextInput; + action_reply.activationMode = UIUserNotificationActivationModeBackground; } else { - action_reply.activationMode = UIUserNotificationActivationModeForeground; + action_reply.activationMode = UIUserNotificationActivationModeForeground; } - + UIMutableUserNotificationCategory *messageCategory = [UIMutableUserNotificationCategory new]; - messageCategory.identifier = Signal_Full_New_Message_Category; - [messageCategory setActions:@[action_markRead, action_reply] forContext:UIUserNotificationActionContextMinimal]; + messageCategory.identifier = Signal_Full_New_Message_Category; + [messageCategory setActions:@[ action_markRead, action_reply ] forContext:UIUserNotificationActionContextMinimal]; [messageCategory setActions:@[] forContext:UIUserNotificationActionContextDefault]; - + return messageCategory; } -- (UIUserNotificationCategory*)userNotificationsCallCategory{ +- (UIUserNotificationCategory *)userNotificationsCallCategory { UIMutableUserNotificationAction *action_accept = [UIMutableUserNotificationAction new]; action_accept.identifier = Signal_Call_Accept_Identifier; action_accept.title = NSLocalizedString(@"ANSWER_CALL_BUTTON_TITLE", @""); action_accept.activationMode = UIUserNotificationActivationModeForeground; action_accept.destructive = NO; action_accept.authenticationRequired = NO; - + UIMutableUserNotificationAction *action_decline = [UIMutableUserNotificationAction new]; action_decline.identifier = Signal_Call_Decline_Identifier; action_decline.title = NSLocalizedString(@"REJECT_CALL_BUTTON_TITLE", @""); action_decline.activationMode = UIUserNotificationActivationModeBackground; action_decline.destructive = NO; action_decline.authenticationRequired = NO; - + UIMutableUserNotificationCategory *callCategory = [UIMutableUserNotificationCategory new]; - callCategory.identifier = Signal_Call_Category; - [callCategory setActions:@[action_accept, action_decline] forContext:UIUserNotificationActionContextMinimal]; - [callCategory setActions:@[action_accept, action_decline] forContext:UIUserNotificationActionContextDefault]; - + callCategory.identifier = Signal_Call_Category; + [callCategory setActions:@[ action_accept, action_decline ] forContext:UIUserNotificationActionContextMinimal]; + [callCategory setActions:@[ action_accept, action_decline ] forContext:UIUserNotificationActionContextDefault]; + return callCategory; } -- (UIUserNotificationCategory*)userNotificationsCallBackCategory{ +- (UIUserNotificationCategory *)userNotificationsCallBackCategory { UIMutableUserNotificationAction *action_accept = [UIMutableUserNotificationAction new]; action_accept.identifier = Signal_CallBack_Identifier; action_accept.title = NSLocalizedString(@"CALLBACK_BUTTON_TITLE", @""); action_accept.activationMode = UIUserNotificationActivationModeForeground; action_accept.destructive = NO; action_accept.authenticationRequired = NO; - + UIMutableUserNotificationCategory *callCategory = [UIMutableUserNotificationCategory new]; - callCategory.identifier = Signal_CallBack_Category; - [callCategory setActions:@[action_accept] forContext:UIUserNotificationActionContextMinimal]; - [callCategory setActions:@[action_accept] forContext:UIUserNotificationActionContextDefault]; - + callCategory.identifier = Signal_CallBack_Category; + [callCategory setActions:@[ action_accept ] forContext:UIUserNotificationActionContextMinimal]; + [callCategory setActions:@[ action_accept ] forContext:UIUserNotificationActionContextDefault]; + return callCategory; } -- (BOOL)needToRegisterForRemoteNotifications -{ +- (BOOL)needToRegisterForRemoteNotifications { return self.wantRemoteNotifications && (!UIApplication.sharedApplication.isRegisteredForRemoteNotifications); } -- (BOOL)wantRemoteNotifications -{ - BOOL isSimulator = [UIDevice.currentDevice.model.lowercaseString rangeOfString:@"simulator"].location != NSNotFound; - - if (isSimulator) { - // Simulator is used for debugging but can't receive push notifications, so don't bother trying to get them - return NO; - } - +- (BOOL)wantRemoteNotifications { +#if TARGET_IPHONE_SIMULATOR + return NO; +#else return YES; +#endif } -- (int)allNotificationTypes -{ +- (int)allNotificationTypes { return UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge; } -- (void)validateUserNotificationSettings -{ +- (void)validateUserNotificationSettings { [[self registerForUserNotificationsFuture] thenDo:^(id value){ // Nothing to do, just making sure we are registered for User Notifications. }]; } -#pragma mark Register Push Notification Token with RedPhone server - -- (TOCFuture *)registerForPushFutureWithToken:(NSData *)pushToken voipToken:(NSData*)voipToken -{ - self.registerWithServerFutureSource = [TOCFutureSource new]; - - [RPServerRequestsManager.sharedInstance performRequest:[RPAPICall registerPushNotificationWithPushToken:pushToken voipToken:voipToken] - success:^(NSURLSessionDataTask *task, id responseObject) { - if ([task.response isKindOfClass:NSHTTPURLResponse.class]) { - NSInteger statusCode = [(NSHTTPURLResponse *)task.response statusCode]; - if (statusCode == 200) { - [self.registerWithServerFutureSource trySetResult:@YES]; - } else { - DDLogError(@"The server returned %@ instead of a 200 status code", task.response); - [self.registerWithServerFutureSource - trySetFailure:[NSError errorWithDomain:pushManagerDomain code:500 userInfo:nil]]; - } - } else { - [self.registerWithServerFutureSource trySetFailure:task.response]; - } - - } - failure:^(NSURLSessionDataTask *task, NSError *error) { - [self.registerWithServerFutureSource trySetFailure:error]; - }]; - - return self.registerWithServerFutureSource.future; -} - - (BOOL)applicationIsActive { UIApplication *app = [UIApplication sharedApplication]; - + if (app.applicationState == UIApplicationStateActive) { return YES; } - + return NO; } -- (void)presentNotification:(UILocalNotification*)notification { +- (void)presentNotification:(UILocalNotification *)notification { [[UIApplication sharedApplication] scheduleLocalNotification:notification]; [self.currentNotifications addObject:notification]; } -- (void)cancelNotificationsWithThreadId:(NSString*)threadId { +- (void)cancelNotificationsWithThreadId:(NSString *)threadId { NSMutableArray *toDelete = [NSMutableArray array]; [self.currentNotifications enumerateObjectsUsingBlock:^(UILocalNotification *notif, NSUInteger idx, BOOL *stop) { - if ([notif.userInfo[Signal_Thread_UserInfo_Key] isEqualToString:threadId]) { - [[UIApplication sharedApplication] cancelLocalNotification:notif]; - [toDelete addObject:notif]; - } + if ([notif.userInfo[Signal_Thread_UserInfo_Key] isEqualToString:threadId]) { + [[UIApplication sharedApplication] cancelLocalNotification:notif]; + [toDelete addObject:notif]; + } }]; [self.currentNotifications removeObjectsInArray:toDelete]; } diff --git a/Signal/src/network/dns/DnsManager.m b/Signal/src/network/dns/DnsManager.m index dc557147c..b38e26ab5 100644 --- a/Signal/src/network/dns/DnsManager.m +++ b/Signal/src/network/dns/DnsManager.m @@ -41,7 +41,7 @@ void handleDnsCompleted(CFHostRef hostRef, CFHostInfoType typeInfo, const CFStre +(TOCFuture*) asyncQueryAddressesForDomainName:(NSString*)domainName unlessCancelled:(TOCCancelToken*)unlessCancelledToken { - require(domainName != nil); + ows_require(domainName != nil); CFHostRef hostRef = CFHostCreateWithName(kCFAllocatorDefault, (__bridge CFStringRef)domainName); checkOperation(hostRef != nil); diff --git a/Signal/src/network/dns/HostNameEndPoint.m b/Signal/src/network/dns/HostNameEndPoint.m index 34e032c0b..725635296 100644 --- a/Signal/src/network/dns/HostNameEndPoint.m +++ b/Signal/src/network/dns/HostNameEndPoint.m @@ -8,8 +8,8 @@ +(HostNameEndPoint*) hostNameEndPointWithHostName:(NSString*)hostname andPort:(in_port_t)port { - require(hostname != nil); - require(port > 0); + ows_require(hostname != nil); + ows_require(port > 0); HostNameEndPoint* h = [HostNameEndPoint new]; h->hostname = hostname.copy; // avoid mutability diff --git a/Signal/src/network/http/AFHTTPSessionManager+SignalMethods.m b/Signal/src/network/http/AFHTTPSessionManager+SignalMethods.m index a8b72f135..c60a2f0db 100644 --- a/Signal/src/network/http/AFHTTPSessionManager+SignalMethods.m +++ b/Signal/src/network/http/AFHTTPSessionManager+SignalMethods.m @@ -23,27 +23,24 @@ - (NSURLSessionDataTask *)BUSY:(NSString *)URLString parameters:(id)parameters success:(void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure{ - - NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"BUSY" URLString:URLString parameters:parameters success:success failure:failure]; + failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { + NSURLSessionDataTask *dataTask = + [self dataTaskWithHTTPMethod:@"BUSY" URLString:URLString parameters:parameters success:success failure:failure]; [dataTask resume]; - + return dataTask; - } - (NSURLSessionDataTask *)RING:(NSString *)URLString parameters:(id)parameters success:(void (^)(NSURLSessionDataTask *task, id responseObject))success - failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure{ - - NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"RING" URLString:URLString parameters:parameters success:success failure:failure]; + failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { + NSURLSessionDataTask *dataTask = + [self dataTaskWithHTTPMethod:@"RING" URLString:URLString parameters:parameters success:success failure:failure]; [dataTask resume]; - + return dataTask; - } - @end diff --git a/Signal/src/network/http/HttpManager.m b/Signal/src/network/http/HttpManager.m index e946f5a7c..fa17010d5 100644 --- a/Signal/src/network/http/HttpManager.m +++ b/Signal/src/network/http/HttpManager.m @@ -5,7 +5,7 @@ +(HttpManager*) httpManagerFor:(HttpSocket*)httpSocket untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(httpSocket != nil); + ows_require(httpSocket != nil); HttpManager* m = [HttpManager new]; m->httpChannel = httpSocket; @@ -16,7 +16,7 @@ } +(HttpManager*) startWithEndPoint:(id)endPoint untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(endPoint != nil); + ows_require(endPoint != nil); NetworkStream* dataChannel = [NetworkStream networkStreamToEndPoint:endPoint]; @@ -28,7 +28,7 @@ -(TOCFuture*) asyncResponseForRequest:(HttpRequest*)request unlessCancelled:(TOCCancelToken*)unlessCancelledToken { - require(request != nil); + ows_require(request != nil); requireState(isStarted); @try { @@ -48,8 +48,8 @@ +(TOCFuture*) asyncOkResponseFromMasterServer:(HttpRequest*)request unlessCancelled:(TOCCancelToken*)unlessCancelledToken andErrorHandler:(ErrorHandlerBlock)errorHandler { - require(request != nil); - require(errorHandler != nil); + ows_require(request != nil); + ows_require(errorHandler != nil); HttpManager* manager = [HttpManager startWithEndPoint:Environment.getMasterServerSecureEndPoint untilCancelled:unlessCancelledToken]; @@ -67,7 +67,7 @@ -(TOCFuture*) asyncOkResponseForRequest:(HttpRequest*)request unlessCancelled:(TOCCancelToken*)unlessCancelledToken { - require(request != nil); + ows_require(request != nil); TOCFuture* futureResponse = [self asyncResponseForRequest:request unlessCancelled:unlessCancelledToken]; @@ -79,7 +79,7 @@ } -(void) startWithRejectingRequestHandlerAndErrorHandler:(ErrorHandlerBlock)errorHandler untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(errorHandler != nil); + ows_require(errorHandler != nil); HttpResponse*(^requestHandler)(HttpRequest* remoteRequest) = ^(HttpRequest* remoteRequest) { errorHandler(@"Rejecting Requests", remoteRequest, false); @@ -95,8 +95,8 @@ andErrorHandler:(ErrorHandlerBlock)errorHandler untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(requestHandler != nil); - require(errorHandler != nil); + ows_require(requestHandler != nil); + ows_require(errorHandler != nil); @synchronized(self) { requireState(!isStarted); @@ -109,8 +109,8 @@ }; PacketHandlerBlock httpHandler = ^(HttpRequestOrResponse* requestOrResponse) { - require(requestOrResponse != nil); - require([requestOrResponse isKindOfClass:HttpRequestOrResponse.class]); + ows_require(requestOrResponse != nil); + ows_require([requestOrResponse isKindOfClass:HttpRequestOrResponse.class]); @synchronized (self) { if (requestOrResponse.isRequest) { HttpResponse* response = requestHandler([requestOrResponse request]); diff --git a/Signal/src/network/http/HttpRequest.h b/Signal/src/network/http/HttpRequest.h index 775106cbc..e2ef832b0 100644 --- a/Signal/src/network/http/HttpRequest.h +++ b/Signal/src/network/http/HttpRequest.h @@ -3,43 +3,42 @@ @interface HttpRequest : NSObject -+(HttpRequest*)httpRequestUnauthenticatedWithMethod:(NSString*)method - andLocation:(NSString*)location - andOptionalBody:(NSString*)optionalBody; ++ (HttpRequest *)httpRequestUnauthenticatedWithMethod:(NSString *)method + andLocation:(NSString *)location + andOptionalBody:(NSString *)optionalBody; -+(HttpRequest*)httpRequestWithBasicAuthenticationAndMethod:(NSString*)method - andLocation:(NSString*)location - andOptionalBody:(NSString*)optionalBody - andLocalNumber:(PhoneNumber*)localNumber - andPassword:(NSString*)password; ++ (HttpRequest *)httpRequestWithBasicAuthenticationAndMethod:(NSString *)method + andLocation:(NSString *)location + andOptionalBody:(NSString *)optionalBody + andLocalNumber:(NSString *)localNumber + andPassword:(NSString *)password; -+(HttpRequest*)httpRequestWithOtpAuthenticationAndMethod:(NSString*)method - andLocation:(NSString*)location - andOptionalBody:(NSString*)optionalBody - andLocalNumber:(PhoneNumber*)localNumber - andPassword:(NSString*)password - andCounter:(int64_t)counter; ++ (HttpRequest *)httpRequestWithOtpAuthenticationAndMethod:(NSString *)method + andLocation:(NSString *)location + andOptionalBody:(NSString *)optionalBody + andLocalNumber:(NSString *)localNumber + andPassword:(NSString *)password + andCounter:(int64_t)counter; -+(HttpRequest*) httpRequestFromData:(NSData*)data; -+(HttpRequest*)httpRequestWithMethod:(NSString*)method - andLocation:(NSString*)location - andHeaders:(NSDictionary*)headers - andOptionalBody:(NSString*)optionalBody; ++ (HttpRequest *)httpRequestFromData:(NSData *)data; ++ (HttpRequest *)httpRequestWithMethod:(NSString *)method + andLocation:(NSString *)location + andHeaders:(NSDictionary *)headers + andOptionalBody:(NSString *)optionalBody; --(NSString*) toHttp; --(NSData*) serialize; --(NSString*) method; --(NSString*) location; --(NSString*) optionalBody; --(NSDictionary*) headers; +- (NSString *)toHttp; +- (NSData *)serialize; +- (NSString *)method; +- (NSString *)location; +- (NSString *)optionalBody; +- (NSDictionary *)headers; --(bool) isEqualToHttpRequest:(HttpRequest*)other; +- (bool)isEqualToHttpRequest:(HttpRequest *)other; -+(NSString*) computeOtpAuthorizationTokenForLocalNumber:(PhoneNumber*)localNumber - andCounterValue:(int64_t)counterValue - andPassword:(NSString*)password; ++ (NSString *)computeOtpAuthorizationTokenForLocalNumber:(NSString *)localNumber + andCounterValue:(int64_t)counterValue + andPassword:(NSString *)password; -+(NSString*) computeBasicAuthorizationTokenForLocalNumber:(PhoneNumber*)localNumber - andPassword:(NSString*)password; ++ (NSString *)computeBasicAuthorizationTokenForLocalNumber:(NSString *)localNumber andPassword:(NSString *)password; @end diff --git a/Signal/src/network/http/HttpRequest.m b/Signal/src/network/http/HttpRequest.m index abefe1307..0acf5cba9 100644 --- a/Signal/src/network/http/HttpRequest.m +++ b/Signal/src/network/http/HttpRequest.m @@ -1,162 +1,167 @@ -#import "HttpRequest.h" -#import "Util.h" #import "CryptoTools.h" +#import "HttpRequest.h" #import "HttpRequestOrResponse.h" +#import "Util.h" @interface HttpRequest () -@property NSString* method; -@property NSString* location; -@property NSString* optionalBody; -@property NSDictionary* headers; +@property NSString *method; +@property NSString *location; +@property NSString *optionalBody; +@property NSDictionary *headers; @end @implementation HttpRequest -+(HttpRequest*)httpRequestWithMethod:(NSString*)method andLocation:(NSString*)location andHeaders:(NSDictionary*)headers andOptionalBody:(NSString*)optionalBody { - require(method != nil); - require(location != nil); - require(headers != nil); - require((optionalBody == nil) == (headers[@"Content-Length"] == nil)); - require(optionalBody == nil || [[@(optionalBody.length) description] isEqualToString:headers[@"Content-Length"]]); - - HttpRequest* s = [HttpRequest new]; - s->_method = method; - s->_location = location; ++ (HttpRequest *)httpRequestWithMethod:(NSString *)method + andLocation:(NSString *)location + andHeaders:(NSDictionary *)headers + andOptionalBody:(NSString *)optionalBody { + ows_require(method != nil); + ows_require(location != nil); + ows_require(headers != nil); + ows_require((optionalBody == nil) == (headers[@"Content-Length"] == nil)); + ows_require(optionalBody == nil || [[@(optionalBody.length) description] isEqualToString:headers[@"Content-Length"]]); + + HttpRequest *s = [HttpRequest new]; + s->_method = method; + s->_location = location; s->_optionalBody = optionalBody; - s->_headers = headers; + s->_headers = headers; return s; } -+(HttpRequest*)httpRequestUnauthenticatedWithMethod:(NSString*)method - andLocation:(NSString*)location - andOptionalBody:(NSString*)optionalBody { - require(method != nil); - require(location != nil); - - NSMutableDictionary* headers = [NSMutableDictionary dictionary]; ++ (HttpRequest *)httpRequestUnauthenticatedWithMethod:(NSString *)method + andLocation:(NSString *)location + andOptionalBody:(NSString *)optionalBody { + ows_require(method != nil); + ows_require(location != nil); + + NSMutableDictionary *headers = [NSMutableDictionary dictionary]; if (optionalBody != nil) { headers[@"Content-Length"] = [@(optionalBody.length) stringValue]; } - - HttpRequest* s = [HttpRequest new]; - s->_method = method; - s->_location = location; + + HttpRequest *s = [HttpRequest new]; + s->_method = method; + s->_location = location; s->_optionalBody = optionalBody; - s->_headers = headers; + s->_headers = headers; return s; } -+(HttpRequest*)httpRequestWithBasicAuthenticationAndMethod:(NSString*)method - andLocation:(NSString*)location - andOptionalBody:(NSString*)optionalBody - andLocalNumber:(PhoneNumber*)localNumber - andPassword:(NSString*)password { - require(method != nil); - require(location != nil); - require(password != nil); - require(localNumber != nil); - - NSMutableDictionary* headers = [NSMutableDictionary dictionary]; ++ (HttpRequest *)httpRequestWithBasicAuthenticationAndMethod:(NSString *)method + andLocation:(NSString *)location + andOptionalBody:(NSString *)optionalBody + andLocalNumber:(NSString *)localNumber + andPassword:(NSString *)password { + ows_require(method != nil); + ows_require(location != nil); + ows_require(password != nil); + ows_require(localNumber != nil); + + NSMutableDictionary *headers = [NSMutableDictionary dictionary]; if (optionalBody != nil) { headers[@"Content-Length"] = [@(optionalBody.length) stringValue]; } - headers[@"Authorization"] = [HttpRequest computeBasicAuthorizationTokenForLocalNumber:localNumber andPassword:password]; - - HttpRequest* s = [HttpRequest new]; - s->_method = method; - s->_location = location; + headers[@"Authorization"] = + [HttpRequest computeBasicAuthorizationTokenForLocalNumber:localNumber andPassword:password]; + + HttpRequest *s = [HttpRequest new]; + s->_method = method; + s->_location = location; s->_optionalBody = optionalBody; - s->_headers = headers; + s->_headers = headers; return s; } -+(HttpRequest*)httpRequestWithOtpAuthenticationAndMethod:(NSString*)method - andLocation:(NSString*)location - andOptionalBody:(NSString*)optionalBody - andLocalNumber:(PhoneNumber*)localNumber - andPassword:(NSString*)password - andCounter:(int64_t)counter { - require(method != nil); - require(location != nil); - require(password != nil); - - NSMutableDictionary* headers = [NSMutableDictionary dictionary]; ++ (HttpRequest *)httpRequestWithOtpAuthenticationAndMethod:(NSString *)method + andLocation:(NSString *)location + andOptionalBody:(NSString *)optionalBody + andLocalNumber:(NSString *)localNumber + andPassword:(NSString *)password + andCounter:(int64_t)counter { + ows_require(method != nil); + ows_require(location != nil); + ows_require(password != nil); + + NSMutableDictionary *headers = [NSMutableDictionary dictionary]; if (optionalBody != nil) { headers[@"Content-Length"] = [@(optionalBody.length) stringValue]; } - headers[@"Authorization"] = [HttpRequest computeOtpAuthorizationTokenForLocalNumber:localNumber andCounterValue:counter andPassword:password]; - - HttpRequest* s = [HttpRequest new]; - s->_method = method; - s->_location = location; + headers[@"Authorization"] = [HttpRequest computeOtpAuthorizationTokenForLocalNumber:localNumber + andCounterValue:counter + andPassword:password]; + + HttpRequest *s = [HttpRequest new]; + s->_method = method; + s->_location = location; s->_optionalBody = optionalBody; - s->_headers = headers; + s->_headers = headers; return s; } -+(HttpRequest*) httpRequestFromData:(NSData*)data { - require(data != nil); ++ (HttpRequest *)httpRequestFromData:(NSData *)data { + ows_require(data != nil); NSUInteger requestSize; - HttpRequestOrResponse* http = [HttpRequestOrResponse tryExtractFromPartialData:data usedLengthOut:&requestSize]; + HttpRequestOrResponse *http = [HttpRequestOrResponse tryExtractFromPartialData:data usedLengthOut:&requestSize]; checkOperation(http.isRequest && requestSize == data.length); return [http request]; } -+(NSString*) computeOtpAuthorizationTokenForLocalNumber:(PhoneNumber*)localNumber - andCounterValue:(int64_t)counterValue - andPassword:(NSString*)password { - require(localNumber != nil); - require(password != nil); - - NSString* rawToken = [NSString stringWithFormat:@"%@:%@:%lld", - localNumber.toE164, - [CryptoTools computeOtpWithPassword:password andCounter:counterValue], - counterValue]; ++ (NSString *)computeOtpAuthorizationTokenForLocalNumber:(PhoneNumber *)localNumber + andCounterValue:(int64_t)counterValue + andPassword:(NSString *)password { + ows_require(localNumber != nil); + ows_require(password != nil); + + NSString *rawToken = + [NSString stringWithFormat:@"%@:%@:%lld", + localNumber, + [CryptoTools computeOtpWithPassword:password andCounter:counterValue], + counterValue]; return [@"OTP " stringByAppendingString:rawToken.encodedAsUtf8.encodedAsBase64]; } -+(NSString*) computeBasicAuthorizationTokenForLocalNumber:(PhoneNumber*)localNumber andPassword:(NSString*)password { - NSString* rawToken = [NSString stringWithFormat:@"%@:%@", - localNumber.toE164, - password]; ++ (NSString *)computeBasicAuthorizationTokenForLocalNumber:(NSString *)localNumber andPassword:(NSString *)password { + NSString *rawToken = [NSString stringWithFormat:@"%@:%@", localNumber, password]; return [@"Basic " stringByAppendingString:rawToken.encodedAsUtf8.encodedAsBase64]; } --(NSString*) toHttp { - NSMutableArray* r = [NSMutableArray array]; - +- (NSString *)toHttp { + NSMutableArray *r = [NSMutableArray array]; + [r addObject:self.method]; [r addObject:@" "]; [r addObject:self.location]; [r addObject:@" HTTP/1.0\r\n"]; - - for (NSString* key in self.headers) { + + for (NSString *key in self.headers) { [r addObject:key]; [r addObject:@": "]; [r addObject:(self.headers)[key]]; [r addObject:@"\r\n"]; } - + [r addObject:@"\r\n"]; - if (self.optionalBody != nil) [r addObject:self.optionalBody]; - + if (self.optionalBody != nil) + [r addObject:self.optionalBody]; + return [r componentsJoinedByString:@""]; } --(NSData*) serialize { +- (NSData *)serialize { return self.toHttp.encodedAsUtf8; } --(bool) isEqualToHttpRequest:(HttpRequest *)other { - return [self.toHttp isEqualToString:other.toHttp] - && [self.method isEqualToString:other.method] - && [self.location isEqualToString:other.location] - && (self.optionalBody == other.optionalBody || [self.optionalBody isEqualToString:[other optionalBody]]) - && [self.headers isEqualToDictionary:other.headers]; +- (bool)isEqualToHttpRequest:(HttpRequest *)other { + return [self.toHttp isEqualToString:other.toHttp] && [self.method isEqualToString:other.method] && + [self.location isEqualToString:other.location] && + (self.optionalBody == other.optionalBody || [self.optionalBody isEqualToString:[other optionalBody]]) && + [self.headers isEqualToDictionary:other.headers]; } --(NSString*) description { - return [NSString stringWithFormat:@"%@ %@%@", - self.method, - self.location, - self.optionalBody == nil ? @"" - : self.optionalBody.length == 0 ? @" [empty body]" - : @" [...body...]"]; +- (NSString *)description { + return + [NSString stringWithFormat:@"%@ %@%@", + self.method, + self.location, + self.optionalBody == nil ? @"" : self.optionalBody.length == 0 ? @" [empty body]" + : @" [...body...]"]; } diff --git a/Signal/src/network/http/HttpRequestOrResponse.m b/Signal/src/network/http/HttpRequestOrResponse.m index ff83d36d4..89740698f 100644 --- a/Signal/src/network/http/HttpRequestOrResponse.m +++ b/Signal/src/network/http/HttpRequestOrResponse.m @@ -5,11 +5,11 @@ @implementation HttpRequestOrResponse +(HttpRequestOrResponse*) httpRequestOrResponse:(id)requestOrResponse { - require(requestOrResponse != nil); + ows_require(requestOrResponse != nil); HttpRequestOrResponse* h = [HttpRequestOrResponse new]; h->requestOrResponse = requestOrResponse; - require(h.isResponse || h.isRequest); + ows_require(h.isResponse || h.isRequest); return h; } -(bool) isRequest { @@ -31,7 +31,7 @@ } +(HttpRequestOrResponse*) tryExtractFromPartialData:(NSData*)data usedLengthOut:(NSUInteger*)usedLengthPtr { - require(data != nil); + ows_require(data != nil); // first line should contain HTTP checkOperation([data tryFindIndexOf:@"\r\n".encodedAsAscii] == nil || [data tryFindIndexOf:@"HTTP".encodedAsAscii] != nil); diff --git a/Signal/src/network/http/HttpRequestUtil.m b/Signal/src/network/http/HttpRequestUtil.m index bffd01100..da45d36b9 100644 --- a/Signal/src/network/http/HttpRequestUtil.m +++ b/Signal/src/network/http/HttpRequestUtil.m @@ -1,44 +1,36 @@ #import "HttpRequestUtil.h" #import "SignalKeyingStorage.h" +#import "TSAccountManager.h" @implementation HttpRequest (HttpRequestUtil) -+(HttpRequest*)httpRequestWithBasicAuthenticationAndMethod:(NSString*)method - andLocation:(NSString*)location { - return [HttpRequest httpRequestWithBasicAuthenticationAndMethod:method - andLocation:location - andOptionalBody:nil]; ++ (HttpRequest *)httpRequestWithBasicAuthenticationAndMethod:(NSString *)method andLocation:(NSString *)location { + return [HttpRequest httpRequestWithBasicAuthenticationAndMethod:method andLocation:location andOptionalBody:nil]; } -+(HttpRequest*)httpRequestWithBasicAuthenticationAndMethod:(NSString*)method - andLocation:(NSString*)location - andOptionalBody:(NSString*)optionalBody { ++ (HttpRequest *)httpRequestWithBasicAuthenticationAndMethod:(NSString *)method + andLocation:(NSString *)location + andOptionalBody:(NSString *)optionalBody { return [HttpRequest httpRequestWithBasicAuthenticationAndMethod:method andLocation:location andOptionalBody:optionalBody - andLocalNumber:SignalKeyingStorage.localNumber + andLocalNumber:[TSAccountManager localNumber] andPassword:SignalKeyingStorage.serverAuthPassword]; } -+(HttpRequest*)httpRequestWithOtpAuthenticationAndMethod:(NSString*)method - andLocation:(NSString*)location { - return [HttpRequest httpRequestWithOtpAuthenticationAndMethod:method - andLocation:location - andOptionalBody:nil]; ++ (HttpRequest *)httpRequestWithOtpAuthenticationAndMethod:(NSString *)method andLocation:(NSString *)location { + return [HttpRequest httpRequestWithOtpAuthenticationAndMethod:method andLocation:location andOptionalBody:nil]; } -+(HttpRequest*)httpRequestWithOtpAuthenticationAndMethod:(NSString*)method - andLocation:(NSString*)location - andOptionalBody:(NSString*)optionalBody { ++ (HttpRequest *)httpRequestWithOtpAuthenticationAndMethod:(NSString *)method + andLocation:(NSString *)location + andOptionalBody:(NSString *)optionalBody { return [HttpRequest httpRequestWithOtpAuthenticationAndMethod:method andLocation:location andOptionalBody:optionalBody - andLocalNumber:SignalKeyingStorage.localNumber + andLocalNumber:[TSAccountManager localNumber] andPassword:SignalKeyingStorage.serverAuthPassword andCounter:[SignalKeyingStorage getAndIncrementOneTimeCounter]]; } -+(HttpRequest*)httpRequestUnauthenticatedWithMethod:(NSString*)method - andLocation:(NSString*)location { - return [HttpRequest httpRequestUnauthenticatedWithMethod:method - andLocation:location - andOptionalBody:nil]; ++ (HttpRequest *)httpRequestUnauthenticatedWithMethod:(NSString *)method andLocation:(NSString *)location { + return [HttpRequest httpRequestUnauthenticatedWithMethod:method andLocation:location andOptionalBody:nil]; } @end diff --git a/Signal/src/network/http/HttpResponse.m b/Signal/src/network/http/HttpResponse.m index dc357ddc7..ddb3caefd 100644 --- a/Signal/src/network/http/HttpResponse.m +++ b/Signal/src/network/http/HttpResponse.m @@ -9,9 +9,9 @@ andHeaders:(NSDictionary*)headers andOptionalBodyText:(NSString*)optionalBody { - require(headers != nil); - require(statusText != nil); - require(headers != nil); + ows_require(headers != nil); + ows_require(statusText != nil); + ows_require(headers != nil); HttpResponse* s = [HttpResponse new]; s->statusCode = statusCode; @@ -25,9 +25,9 @@ andHeaders:(NSDictionary*)headers andOptionalBodyData:(NSData*)optionalBody { - require(headers != nil); - require(statusText != nil); - require(headers != nil); + ows_require(headers != nil); + ows_require(statusText != nil); + ows_require(headers != nil); HttpResponse* s = [HttpResponse new]; s->statusCode = statusCode; @@ -37,7 +37,7 @@ return s; } +(HttpResponse*) httpResponseFromData:(NSData*)data { - require(data != nil); + ows_require(data != nil); NSUInteger responseSize; HttpRequestOrResponse* http = [HttpRequestOrResponse tryExtractFromPartialData:data usedLengthOut:&responseSize]; checkOperation(http.isResponse && responseSize == data.length); diff --git a/Signal/src/network/http/HttpSocket.m b/Signal/src/network/http/HttpSocket.m index b705f5274..ec961446d 100644 --- a/Signal/src/network/http/HttpSocket.m +++ b/Signal/src/network/http/HttpSocket.m @@ -6,7 +6,7 @@ @implementation HttpSocket +(HttpSocket*) httpSocketOver:(NetworkStream*)rawDataChannel { - require(rawDataChannel != nil); + ows_require(rawDataChannel != nil); HttpSocket* h = [HttpSocket new]; h->rawDataChannelTcp = rawDataChannel; @@ -16,7 +16,7 @@ return h; } +(HttpSocket*) httpSocketOverUdp:(UdpSocket*)rawDataChannel { - require(rawDataChannel != nil); + ows_require(rawDataChannel != nil); HttpSocket* h = [HttpSocket new]; h->rawDataChannelUdp = rawDataChannel; @@ -27,7 +27,7 @@ } -(void) sendHttpRequestOrResponse:(HttpRequestOrResponse*)requestOrResponse { - require(requestOrResponse != nil); + ows_require(requestOrResponse != nil); requireState(httpSignalResponseHandler != nil); [sentPacketsLogger markOccurrence:requestOrResponse]; NSData* data = [requestOrResponse serialize]; @@ -38,29 +38,29 @@ } } -(void) sendHttpRequest:(HttpRequest*)request { - require(request != nil); + ows_require(request != nil); [self sendHttpRequestOrResponse:[HttpRequestOrResponse httpRequestOrResponse:request]]; } -(void) sendHttpResponse:(HttpResponse*)response { - require(response != nil); + ows_require(response != nil); [self sendHttpRequestOrResponse:[HttpRequestOrResponse httpRequestOrResponse:response]]; } -(void) send:(HttpRequestOrResponse*)packet { - require(packet != nil); + ows_require(packet != nil); [self sendHttpRequestOrResponse:packet]; } -(void) startWithHandler:(PacketHandler*)handler untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(handler != nil); + ows_require(handler != nil); requireState(httpSignalResponseHandler == nil); httpSignalResponseHandler = handler; TOCCancelTokenSource* lifetime = [TOCCancelTokenSource cancelTokenSourceUntil:untilCancelledToken]; PacketHandler* packetHandler = [PacketHandler packetHandler:^(id packet) { - require(packet != nil); - require([packet isKindOfClass:NSData.class]); + ows_require(packet != nil); + ows_require([packet isKindOfClass:NSData.class]); NSData* data = packet; [partialDataBuffer replaceBytesInRange:NSMakeRange(partialDataBuffer.length, data.length) withBytes:[data bytes]]; diff --git a/Signal/src/network/http/RPAPICall.h b/Signal/src/network/http/RPAPICall.h index e92a428b9..08152c4e1 100644 --- a/Signal/src/network/http/RPAPICall.h +++ b/Signal/src/network/http/RPAPICall.h @@ -6,41 +6,26 @@ // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // -#import #import +#import @class PhoneNumber; @interface RPAPICall : NSObject -typedef NS_ENUM(NSInteger, HTTPMethod) { - HTTP_GET, - HTTP_POST, - HTTP_PUT, - HTTP_DELETE, - SIGNAL_RING, - SIGNAL_BUSY -}; +typedef NS_ENUM(NSInteger, HTTPMethod) { HTTP_GET, HTTP_POST, HTTP_PUT, HTTP_DELETE, SIGNAL_RING, SIGNAL_BUSY }; #pragma mark API Call Properties @property (nonatomic, readonly) NSString *endPoint; @property (nonatomic, readonly) HTTPMethod method; @property (nonatomic, readonly) NSDictionary *parameters; -@property (nonatomic, readonly) AFHTTPRequestSerializer *requestSerializer; -@property (nonatomic, readonly) AFHTTPResponseSerializer *responseSerializer; +@property (nonatomic, readonly) AFHTTPRequestSerializer *requestSerializer; +@property (nonatomic, readonly) AFHTTPResponseSerializer *responseSerializer; #pragma mark API Call Contstructors -+ (RPAPICall*)requestVerificationCode; -+ (RPAPICall*)requestVerificationCodeWithVoice; -+ (RPAPICall*)verifyVerificationCode:(NSString*)verificationCode; -+ (RPAPICall*)registerPushNotificationWithPushToken:(NSData*)pushToken voipToken:(NSData*)voipToken; -+ (RPAPICall*)requestTextSecureVerificationCode; -+ (RPAPICall*)unregisterWithPushToken:(NSData*)pushToken; - -//+ (RPAPICall*)requestToOpenPortWithSessionId:(int64_t)sessionId; -//+ (RPAPICall*)requestToRingWithSessionId:(int64_t)sessionId; -//+ (RPAPICall*)requestToSignalBusyWithSessionId:(int64_t)sessionId; -//+ (RPAPICall*)requestToInitiateToRemoteNumber:(PhoneNumber*)remoteNumber; ++ (RPAPICall *)registerPushNotificationWithPushToken:(NSData *)pushToken voipToken:(NSData *)voipToken; ++ (RPAPICall *)unregisterWithPushToken:(NSData *)pushToken; ++ (RPAPICall *)verifyWithTSToken:(NSString *)tsToken attributesParameters:(NSDictionary *)attributes; @end diff --git a/Signal/src/network/http/RPAPICall.m b/Signal/src/network/http/RPAPICall.m index da463641f..1a5219e80 100644 --- a/Signal/src/network/http/RPAPICall.m +++ b/Signal/src/network/http/RPAPICall.m @@ -6,13 +6,14 @@ // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // +#import #import "Constraints.h" #import "CryptoTools.h" +#import "NSData+ows_StripToken.h" #import "PhoneNumber.h" #import "RPAPICall.h" #import "SignalKeyingStorage.h" #import "Util.h" -#import "NSData+ows_StripToken.h" #define CLAIMED_INTEROP_VERSION_IN_INITIATE_SIGNAL 1 @@ -20,13 +21,13 @@ @property (nonatomic, readwrite) NSString *endPoint; @property (nonatomic, readwrite) HTTPMethod method; @property (nonatomic, readwrite) NSDictionary *parameters; -@property (nonatomic, readwrite) AFHTTPRequestSerializer *requestSerializer; -@property (nonatomic, readwrite) AFHTTPResponseSerializer *responseSerializer; +@property (nonatomic, readwrite) AFHTTPRequestSerializer *requestSerializer; +@property (nonatomic, readwrite) AFHTTPResponseSerializer *responseSerializer; @end @implementation RPAPICall -+ (RPAPICall*)defaultAPICall { ++ (RPAPICall *)defaultAPICall { RPAPICall *apiCall = [[RPAPICall alloc] init]; apiCall.parameters = @{}; apiCall.requestSerializer = [self basicAuthenticationSerializer]; @@ -34,65 +35,38 @@ return apiCall; } - -+ (RPAPICall*)requestVerificationCode { - [SignalKeyingStorage generateServerAuthPassword]; ++ (RPAPICall *)verifyWithTSToken:(NSString *)tsToken attributesParameters:(NSDictionary *)attributes { RPAPICall *apiCall = [self defaultAPICall]; - apiCall.method = HTTP_GET; - apiCall.endPoint = @"/users/verification/sms?client=ios"; - return apiCall; -} -+ (RPAPICall*)requestVerificationCodeWithVoice { - RPAPICall *apiCall = [self requestVerificationCode]; - apiCall.endPoint = @"/users/verification/voice?client=ios"; - return apiCall; -} - -+ (RPAPICall*)verifyVerificationCode:(NSString*)verificationCode { - RPAPICall *apiCall = [self defaultAPICall]; - [SignalKeyingStorage generateSignaling]; - apiCall.method = HTTP_PUT; - apiCall.endPoint = [NSString stringWithFormat:@"/users/verification/%@", SignalKeyingStorage.localNumber]; - - NSData* signalingCipherKey = SignalKeyingStorage.signalingCipherKey; - NSData* signalingMacKey = SignalKeyingStorage.signalingMacKey; - NSData* signalingExtraKeyData = SignalKeyingStorage.signalingExtraKey; - NSString* encodedSignalingKey = @[signalingCipherKey, signalingMacKey, signalingExtraKeyData].ows_concatDatas.encodedAsBase64; - apiCall.parameters = @{@"key" : encodedSignalingKey, @"challenge" : verificationCode}; + apiCall.method = HTTP_PUT; + apiCall.endPoint = [NSString stringWithFormat:@"/api/v1/accounts/token/%@", tsToken]; + apiCall.parameters = attributes; return apiCall; } -+ (RPAPICall*)registerPushNotificationWithPushToken:(NSData*)pushToken voipToken:(NSData*)voipToken { ++ (RPAPICall *)registerPushNotificationWithPushToken:(NSData *)pushToken voipToken:(NSData *)voipToken { RPAPICall *apiCall = [self defaultAPICall]; if (voipToken) { - apiCall.parameters = @{@"voip":[voipToken ows_tripToken]}; + apiCall.parameters = @{ @"voip" : [voipToken ows_tripToken] }; } else { DDLogWarn(@"No VoIP push token registered, might experience some issues while in background."); } - apiCall.method = HTTP_PUT; - apiCall.endPoint = [NSString stringWithFormat:@"/apn/%@", [pushToken ows_tripToken]]; + apiCall.method = HTTP_PUT; + apiCall.endPoint = [NSString stringWithFormat:@"/apn/%@", [pushToken ows_tripToken]]; return apiCall; } -+ (RPAPICall*)requestTextSecureVerificationCode{ - RPAPICall *apiCall = [self defaultAPICall]; - apiCall.method = HTTP_GET; - apiCall.endPoint = [NSString stringWithFormat:@"/users/verification/textsecure"]; ++ (RPAPICall *)unregisterWithPushToken:(NSData *)pushToken { + RPAPICall *apiCall = [self defaultAPICall]; + apiCall.method = HTTP_DELETE; + apiCall.endPoint = [NSString stringWithFormat:@"/apn/%@", pushToken.encodedAsHexString]; + apiCall.parameters = nil; + apiCall.requestSerializer = [self basicAuthenticationSerializer]; return apiCall; } -+ (RPAPICall*)unregisterWithPushToken:(NSData*)pushToken { - RPAPICall *apiCall = [self defaultAPICall]; - apiCall.method = HTTP_DELETE; - apiCall.endPoint = [NSString stringWithFormat:@"/apn/%@", pushToken.encodedAsHexString]; - apiCall.parameters = nil; - apiCall.requestSerializer = [self basicAuthenticationSerializer]; - return apiCall; -} - -+ (RPAPICall*)requestToOpenPortWithSessionId:(int64_t)sessionId { ++ (RPAPICall *)requestToOpenPortWithSessionId:(int64_t)sessionId { RPAPICall *apiCall = [self defaultAPICall]; apiCall.method = HTTP_GET; apiCall.endPoint = [NSString stringWithFormat:@"/open/%lld", sessionId]; @@ -101,73 +75,123 @@ return apiCall; } -+ (RPAPICall*)requestToRingWithSessionId:(int64_t)sessionId { - RPAPICall *apiCall = [self defaultAPICall]; - apiCall.method = SIGNAL_RING; - apiCall.endPoint = [NSString stringWithFormat:@"/session/%lld", sessionId]; - apiCall.requestSerializer = [self otpAuthenticationSerializer]; ++ (RPAPICall *)requestToRingWithSessionId:(int64_t)sessionId { + RPAPICall *apiCall = [self defaultAPICall]; + apiCall.method = SIGNAL_RING; + apiCall.endPoint = [NSString stringWithFormat:@"/session/%lld", sessionId]; + apiCall.requestSerializer = [self otpAuthenticationSerializer]; return apiCall; } -+ (RPAPICall*)requestToSignalBusyWithSessionId:(int64_t)sessionId { - RPAPICall *apiCall = [self defaultAPICall]; - apiCall.method = SIGNAL_BUSY; - apiCall.endPoint = [NSString stringWithFormat:@"/session/%lld", sessionId]; - apiCall.requestSerializer = [self otpAuthenticationSerializer]; ++ (RPAPICall *)requestToSignalBusyWithSessionId:(int64_t)sessionId { + RPAPICall *apiCall = [self defaultAPICall]; + apiCall.method = SIGNAL_BUSY; + apiCall.endPoint = [NSString stringWithFormat:@"/session/%lld", sessionId]; + apiCall.requestSerializer = [self otpAuthenticationSerializer]; return apiCall; } -+ (RPAPICall*)requestToInitiateToRemoteNumber:(PhoneNumber*)remoteNumber { - RPAPICall *apiCall = [self defaultAPICall]; ++ (RPAPICall *)requestToInitiateToRemoteNumber:(PhoneNumber *)remoteNumber { + RPAPICall *apiCall = [self defaultAPICall]; - require(remoteNumber != nil); + ows_require(remoteNumber != nil); - NSString* formattedRemoteNumber = remoteNumber.toE164; - NSString* interopVersionInsert = (CLAIMED_INTEROP_VERSION_IN_INITIATE_SIGNAL == 0)? @"" : [NSString stringWithFormat:@"/%d", CLAIMED_INTEROP_VERSION_IN_INITIATE_SIGNAL]; + NSString *formattedRemoteNumber = remoteNumber.toE164; + NSString *interopVersionInsert = + (CLAIMED_INTEROP_VERSION_IN_INITIATE_SIGNAL == 0) + ? @"" + : [NSString stringWithFormat:@"/%d", CLAIMED_INTEROP_VERSION_IN_INITIATE_SIGNAL]; - apiCall.method = HTTP_GET; - apiCall.endPoint = [NSString stringWithFormat:@"/session%@/%@", interopVersionInsert, formattedRemoteNumber]; - apiCall.requestSerializer = [self otpAuthenticationSerializer]; + apiCall.method = HTTP_GET; + apiCall.endPoint = [NSString stringWithFormat:@"/session%@/%@", interopVersionInsert, formattedRemoteNumber]; + apiCall.requestSerializer = [self otpAuthenticationSerializer]; return apiCall; } #pragma mark Authorization Headers -+ (AFHTTPRequestSerializer*)basicAuthenticationSerializer { ++ (AFHTTPRequestSerializer *)basicAuthenticationSerializer { AFHTTPRequestSerializer *serializer = [AFJSONRequestSerializer serializerWithWritingOptions:0]; - [serializer setValue:[self computeBasicAuthorizationTokenForLocalNumber:SignalKeyingStorage.localNumber andPassword:SignalKeyingStorage.serverAuthPassword]forHTTPHeaderField:@"Authorization"]; + [serializer setValue:[self computeBasicAuthorizationTokenForLocalNumber:[TSAccountManager localNumber] + andPassword:SignalKeyingStorage.serverAuthPassword] + forHTTPHeaderField:@"Authorization"]; return serializer; } -+ (AFHTTPRequestSerializer*)otpAuthenticationSerializer { ++ (AFHTTPRequestSerializer *)otpAuthenticationSerializer { AFHTTPRequestSerializer *serializer = [AFJSONRequestSerializer serializerWithWritingOptions:0]; - [serializer setValue:[self computeOtpAuthorizationTokenForLocalNumber:SignalKeyingStorage.localNumber andCounterValue:[SignalKeyingStorage getAndIncrementOneTimeCounter] andPassword:SignalKeyingStorage.serverAuthPassword] forHTTPHeaderField:@"Authorization"]; + [serializer setValue:[self computeOtpAuthorizationTokenForLocalNumber:[TSAccountManager localNumber] + andCounterValue:[SignalKeyingStorage + getAndIncrementOneTimeCounter] + andPassword:SignalKeyingStorage.serverAuthPassword] + forHTTPHeaderField:@"Authorization"]; return serializer; } -+ (AFHTTPRequestSerializer*)unauthenticatedSerializer { ++ (AFHTTPRequestSerializer *)unauthenticatedSerializer { AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer]; return serializer; } -+ (NSString*) computeOtpAuthorizationTokenForLocalNumber:(PhoneNumber*)localNumber - andCounterValue:(int64_t)counterValue - andPassword:(NSString*)password { - require(localNumber != nil); - require(password != nil); - - NSString* rawToken = [NSString stringWithFormat:@"%@:%@:%lld", - localNumber.toE164, - [CryptoTools computeOtpWithPassword:password andCounter:counterValue], - counterValue]; ++ (NSString *)computeOtpAuthorizationTokenForLocalNumber:(NSString *)localNumber + andCounterValue:(int64_t)counterValue + andPassword:(NSString *)password { + ows_require(localNumber != nil); + ows_require(password != nil); + + NSString *rawToken = + [NSString stringWithFormat:@"%@:%@:%lld", + localNumber, + [CryptoTools computeOtpWithPassword:password andCounter:counterValue], + counterValue]; return [@"OTP " stringByAppendingString:rawToken.encodedAsUtf8.encodedAsBase64]; } -+ (NSString*) computeBasicAuthorizationTokenForLocalNumber:(PhoneNumber*)localNumber andPassword:(NSString*)password { - NSString* rawToken = [NSString stringWithFormat:@"%@:%@", - localNumber.toE164, - password]; ++ (NSString *)computeBasicAuthorizationTokenForLocalNumber:(NSString *)localNumber andPassword:(NSString *)password { + NSString *rawToken = [NSString stringWithFormat:@"%@:%@", localNumber, password]; return [@"Basic " stringByAppendingString:rawToken.encodedAsUtf8.encodedAsBase64]; } +/* <---> Registering with on RP server is soon going to be deprecated + + + (RPAPICall*)requestVerificationCode { + [SignalKeyingStorage generateServerAuthPassword]; + RPAPICall *apiCall = [self defaultAPICall]; + apiCall.method = HTTP_GET; + apiCall.endPoint = @"/users/verification/sms?client=ios"; + return apiCall; + } + + + (RPAPICall*)requestVerificationCodeWithVoice { + RPAPICall *apiCall = [self requestVerificationCode]; + apiCall.endPoint = @"/users/verification/voice?client=ios"; + return apiCall; + } + + + + + (RPAPICall *)verifyVerificationCode:(NSString *)verificationCode { + RPAPICall *apiCall = [self defaultAPICall]; + [SignalKeyingStorage generateSignaling]; + apiCall.method = HTTP_PUT; + apiCall.endPoint = [NSString stringWithFormat:@"/users/verification/%@", SignalKeyingStorage.localNumber]; + + NSData *signalingCipherKey = SignalKeyingStorage.signalingCipherKey; + NSData *signalingMacKey = SignalKeyingStorage.signalingMacKey; + NSData *signalingExtraKeyData = SignalKeyingStorage.signalingExtraKey; + NSString *encodedSignalingKey = + @[ signalingCipherKey, signalingMacKey, signalingExtraKeyData ].ows_concatDatas.encodedAsBase64; + apiCall.parameters = @{ @"key" : encodedSignalingKey, @"challenge" : verificationCode }; + + return apiCall; + } + + + (RPAPICall *)requestTextSecureVerificationCode { + RPAPICall *apiCall = [self defaultAPICall]; + apiCall.method = HTTP_GET; + apiCall.endPoint = [NSString stringWithFormat:@"/users/verification/textsecure"]; + return apiCall; + } + */ + @end diff --git a/Signal/src/network/http/RPServerRequestsManager.h b/Signal/src/network/http/RPServerRequestsManager.h index 4b48b62b3..e4a42dd77 100644 --- a/Signal/src/network/http/RPServerRequestsManager.h +++ b/Signal/src/network/http/RPServerRequestsManager.h @@ -13,12 +13,12 @@ @interface RPServerRequestsManager : NSObject -MacrosSingletonInterface ++ (instancetype)sharedManager; -- (void)performRequest:(RPAPICall*)apiCall +- (void)performRequest:(RPAPICall *)apiCall success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; -- (TOCFuture*)futureForRequest:(RPAPICall*)apiCall; +- (TOCFuture *)futureForRequest:(RPAPICall *)apiCall; @end diff --git a/Signal/src/network/http/RPServerRequestsManager.m b/Signal/src/network/http/RPServerRequestsManager.m index 3cb0cea37..1e77965ed 100644 --- a/Signal/src/network/http/RPServerRequestsManager.m +++ b/Signal/src/network/http/RPServerRequestsManager.m @@ -5,77 +5,99 @@ // Created by Frederic Jacobs on 31/07/14. // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // -#import "RPServerRequestsManager.h" #import "Environment.h" +#import "RPServerRequestsManager.h" #import "AFHTTPSessionManager+SignalMethods.h" #import "AFSecurityOWSPolicy.h" @interface RPServerRequestsManager () -@property (nonatomic, retain)AFHTTPSessionManager *operationManager; +@property (nonatomic, strong) AFHTTPSessionManager *operationManager; @end @implementation RPServerRequestsManager -MacrosSingletonImplemention ++ (instancetype)sharedManager { + static RPServerRequestsManager *sharedManager = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedManager = [self new]; + }); + return sharedManager; +} -- (id)init{ +- (id)init { self = [super init]; - + if (self) { NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; - HostNameEndPoint *endpoint = Environment.getCurrent.masterServerSecureEndPoint.hostNameEndPoint; - NSURL *endPointURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://%@:%hu", endpoint.hostname, endpoint.port]]; - self.operationManager = [[AFHTTPSessionManager alloc] initWithBaseURL:endPointURL sessionConfiguration:sessionConfig]; + HostNameEndPoint *endpoint = Environment.getCurrent.masterServerSecureEndPoint.hostNameEndPoint; + NSURL *endPointURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://%@:%d", endpoint.hostname, 443]]; + self.operationManager = + [[AFHTTPSessionManager alloc] initWithBaseURL:endPointURL sessionConfiguration:sessionConfig]; self.operationManager.securityPolicy = [AFSecurityOWSPolicy OWS_PinningPolicy]; } return self; } -- (void)performRequest:(RPAPICall*)apiCall success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure{ - +- (void)performRequest:(RPAPICall *)apiCall + success:(void (^)(NSURLSessionDataTask *task, id responseObject))success + failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { self.operationManager.requestSerializer = apiCall.requestSerializer; self.operationManager.responseSerializer = apiCall.responseSerializer; - + switch (apiCall.method) { case HTTP_GET: - [self.operationManager GET:apiCall.endPoint parameters:apiCall.parameters success:success failure:failure]; + [self.operationManager GET:apiCall.endPoint + parameters:apiCall.parameters + progress:nil + success:success + failure:failure]; break; - + case HTTP_PUT: [self.operationManager PUT:apiCall.endPoint parameters:apiCall.parameters success:success failure:failure]; break; - + case HTTP_POST: - [self.operationManager POST:apiCall.endPoint parameters:apiCall.parameters success:success failure:failure]; + [self.operationManager POST:apiCall.endPoint + parameters:apiCall.parameters + progress:nil + success:success + failure:failure]; break; - + case HTTP_DELETE: - [self.operationManager DELETE:apiCall.endPoint parameters:apiCall.parameters success:success failure:failure]; + [self.operationManager DELETE:apiCall.endPoint + parameters:apiCall.parameters + success:success + failure:failure]; break; - + case SIGNAL_BUSY: [self.operationManager BUSY:apiCall.endPoint parameters:apiCall.parameters success:success failure:failure]; break; - + case SIGNAL_RING: [self.operationManager RING:apiCall.endPoint parameters:apiCall.parameters success:success failure:failure]; break; } } -- (TOCFuture*)futureForRequest:(RPAPICall*)apiCall{ +- (TOCFuture *)futureForRequest:(RPAPICall *)apiCall { TOCFutureSource *requestFutureSource = [TOCFutureSource new]; - - [self performRequest:apiCall success:^(NSURLSessionDataTask *task, id responseObject) { - [requestFutureSource trySetResult:task.response]; - } failure:^(NSURLSessionDataTask *task, NSError *error) { - [requestFutureSource trySetFailure:error]; - }]; - + + [self performRequest:apiCall + success:^(NSURLSessionDataTask *task, id responseObject) { + [requestFutureSource trySetResult:task.response]; + } + failure:^(NSURLSessionDataTask *task, NSError *error) { + [requestFutureSource trySetFailure:error]; + }]; + return [requestFutureSource future]; } diff --git a/Signal/src/network/rtp/RtpPacket.m b/Signal/src/network/rtp/RtpPacket.m index 4390a078a..bfe511421 100644 --- a/Signal/src/network/rtp/RtpPacket.m +++ b/Signal/src/network/rtp/RtpPacket.m @@ -41,7 +41,7 @@ const uint8_t PACKET_VERSION = 2; @synthesize wasAdjustedDueToInteropIssues; +(RtpPacket*) rtpPacketWithDefaultsAndSequenceNumber:(uint16_t)sequenceNumber andPayload:(NSData *)payload { - require(payload != nil); + ows_require(payload != nil); return [RtpPacket rtpPacketWithVersion:PACKET_VERSION andPadding:0 andContributingSourceIdentifiers:@[] @@ -64,13 +64,13 @@ andSynchronizationSourceIdentifier:(uint32_t)synchronizedSourceIdentifier andTimeStamp:(uint32_t)timeStamp andPayload:(NSData*)payload { - require((version & ~0x3) == 0); - require((payloadType & ~0x7F) == 0); - require(extensionData != nil); - require(extensionData.length < 0x10000); - require(contributingSourceIdentifiers != nil); - require(contributingSourceIdentifiers.count < 0x10); - require(payload != nil); + ows_require((version & ~0x3) == 0); + ows_require((payloadType & ~0x7F) == 0); + ows_require(extensionData != nil); + ows_require(extensionData.length < 0x10000); + ows_require(contributingSourceIdentifiers != nil); + ows_require(contributingSourceIdentifiers.count < 0x10); + ows_require(payload != nil); RtpPacket* p = [RtpPacket new]; p->version = version; @@ -97,11 +97,11 @@ andSynchronizationSourceIdentifier:(uint32_t)synchronizedSourceIdentifier andTimeStamp:(uint32_t)timeStamp andPayload:(NSData*)payload { - require((version & ~0x3) == 0); - require((payloadType & ~0x7F) == 0); - require(contributingSourceIdentifiers != nil); - require(contributingSourceIdentifiers.count < 0x10); - require(payload != nil); + ows_require((version & ~0x3) == 0); + ows_require((payloadType & ~0x7F) == 0); + ows_require(contributingSourceIdentifiers != nil); + ows_require(contributingSourceIdentifiers.count < 0x10); + ows_require(payload != nil); RtpPacket* p = [RtpPacket new]; p->version = version; @@ -215,7 +215,7 @@ andSynchronizationSourceIdentifier:(uint32_t)synchronizedSourceIdentifier checkOperationDescribe(packetData.length >= *minSize, @"Rtp packet overlaps header and padding."); } +(RtpPacket*) rtpPacketParsedFromPacketData:(NSData*)packetData { - require(packetData != nil); + ows_require(packetData != nil); NSUInteger minSize = MINIMUM_RTP_HEADER_LENGTH; checkOperationDescribe(packetData.length >= minSize, @"Rtp packet ends before header finished."); diff --git a/Signal/src/network/rtp/RtpSocket.m b/Signal/src/network/rtp/RtpSocket.m index e2f2b1aea..386b2f322 100644 --- a/Signal/src/network/rtp/RtpSocket.m +++ b/Signal/src/network/rtp/RtpSocket.m @@ -5,8 +5,8 @@ @implementation RtpSocket +(RtpSocket*) rtpSocketOverUdp:(UdpSocket*)udpSocket interopOptions:(NSArray*)interopOptions { - require(udpSocket != nil); - require(interopOptions != nil); + ows_require(udpSocket != nil); + ows_require(interopOptions != nil); RtpSocket* s = [RtpSocket new]; s->udpSocket = udpSocket; @@ -15,7 +15,7 @@ } -(void) startWithHandler:(PacketHandler*)handler untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(handler != nil); + ows_require(handler != nil); @synchronized(self) { bool isFirstTime = currentHandler == nil; currentHandler = handler; @@ -23,8 +23,8 @@ } PacketHandlerBlock valueHandler = ^(id packet) { - require(packet != nil); - require([packet isKindOfClass:NSData.class]); + ows_require(packet != nil); + ows_require([packet isKindOfClass:NSData.class]); NSData* data = packet; RtpPacket* rtpPacket = [RtpPacket rtpPacketParsedFromPacketData:data]; @@ -64,7 +64,7 @@ } -(void) send:(RtpPacket*)packet { - require(packet != nil); + ows_require(packet != nil); [udpSocket send:[packet rawPacketDataUsingInteropOptions:interopOptions]]; } diff --git a/Signal/src/network/rtp/srtp/SrtpSocket.m b/Signal/src/network/rtp/srtp/SrtpSocket.m index 5c743c2ef..3626c780b 100644 --- a/Signal/src/network/rtp/srtp/SrtpSocket.m +++ b/Signal/src/network/rtp/srtp/SrtpSocket.m @@ -10,13 +10,13 @@ andOutgoingCipherKey:(NSData*)outgoingCipherKey andOutgoingMacKey:(NSData*)outgoingMacKey andOutgoingSalt:(NSData*)outgoingSalt { - require(rtpSocket != nil); - require(incomingCipherKey != nil); - require(incomingMacKey != nil); - require(incomingSalt != nil); - require(outgoingCipherKey != nil); - require(outgoingMacKey != nil); - require(outgoingSalt != nil); + ows_require(rtpSocket != nil); + ows_require(incomingCipherKey != nil); + ows_require(incomingMacKey != nil); + ows_require(incomingSalt != nil); + ows_require(outgoingCipherKey != nil); + ows_require(outgoingMacKey != nil); + ows_require(outgoingSalt != nil); SrtpSocket* s = [SrtpSocket new]; s->incomingContext = [SrtpStream srtpStreamWithCipherKey:incomingCipherKey andMacKey:incomingMacKey andCipherIvSalt:incomingSalt]; @@ -27,22 +27,22 @@ } -(RtpPacket*) decryptAndAuthenticateReceived:(RtpPacket*)securedRtpPacket { - require(securedRtpPacket != nil); + ows_require(securedRtpPacket != nil); return [incomingContext verifyAuthenticationAndDecryptSecuredRtpPacket:securedRtpPacket]; } -(RtpPacket*) encryptAndAuthenticateToSend:(RtpPacket*)normalRtpPacket { - require(normalRtpPacket != nil); + ows_require(normalRtpPacket != nil); return [outgoingContext encryptAndAuthenticateNormalRtpPacket:normalRtpPacket]; } -(void) startWithHandler:(PacketHandler*)handler untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(handler != nil); + ows_require(handler != nil); requireState(!hasBeenStarted); hasBeenStarted = true; PacketHandlerBlock packetHandler = ^(id packet) { - require(packet != nil); - require([packet isKindOfClass:RtpPacket.class]); + ows_require(packet != nil); + ows_require([packet isKindOfClass:RtpPacket.class]); RtpPacket* decryptedPacket; @try { @@ -60,7 +60,7 @@ } -(void) secureAndSendRtpPacket:(RtpPacket *)packet { - require(packet != nil); + ows_require(packet != nil); [rtpSocket send:[self encryptAndAuthenticateToSend:packet]]; } @end diff --git a/Signal/src/network/rtp/srtp/SrtpStream.m b/Signal/src/network/rtp/srtp/SrtpStream.m index a8f5e4951..f1bdd0024 100644 --- a/Signal/src/network/rtp/srtp/SrtpStream.m +++ b/Signal/src/network/rtp/srtp/SrtpStream.m @@ -8,10 +8,10 @@ @implementation SrtpStream +(SrtpStream*) srtpStreamWithCipherKey:(NSData*)cipherKey andMacKey:(NSData*)macKey andCipherIvSalt:(NSData*)cipherIvSalt { - require(cipherKey != nil); - require(macKey != nil); - require(cipherIvSalt != nil); - require(cipherIvSalt.length == IV_SALT_LENGTH); + ows_require(cipherKey != nil); + ows_require(macKey != nil); + ows_require(cipherIvSalt != nil); + ows_require(cipherIvSalt.length == IV_SALT_LENGTH); SrtpStream* s = [SrtpStream new]; s->cipherIvSalt = cipherIvSalt; @@ -22,7 +22,7 @@ } -(RtpPacket*) encryptAndAuthenticateNormalRtpPacket:(RtpPacket*)normalRtpPacket { - require(normalRtpPacket != nil); + ows_require(normalRtpPacket != nil); NSData* payload = [normalRtpPacket payload]; NSData* iv = [self getIvForSequenceNumber:[normalRtpPacket sequenceNumber] andSynchronizationSourceIdentifier:[normalRtpPacket synchronizationSourceIdentifier]]; @@ -36,7 +36,7 @@ } -(RtpPacket*) verifyAuthenticationAndDecryptSecuredRtpPacket:(RtpPacket*)securedRtpPacket { - require(securedRtpPacket != nil); + ows_require(securedRtpPacket != nil); checkOperationDescribe([[securedRtpPacket payload] length] >= HMAC_LENGTH, @"Payload not long enough to include hmac"); NSData* authenticatedData = [securedRtpPacket rawPacketDataUsingInteropOptions:nil]; diff --git a/Signal/src/network/rtp/zrtp/HashChain.m b/Signal/src/network/rtp/zrtp/HashChain.m index d6ea67711..c96d5d7ac 100644 --- a/Signal/src/network/rtp/zrtp/HashChain.m +++ b/Signal/src/network/rtp/zrtp/HashChain.m @@ -7,8 +7,8 @@ @synthesize h0,h1,h2,h3; +(HashChain*) hashChainWithSeed:(NSData*)seed { - require(seed != nil); - require(seed.length == HASH_CHAIN_ITEM_LENGTH); + ows_require(seed != nil); + ows_require(seed.length == HASH_CHAIN_ITEM_LENGTH); HashChain* s = [HashChain new]; s->h0 = seed; s->h1 = [s->h0 hashWithSha256]; diff --git a/Signal/src/network/rtp/zrtp/MasterSecret.m b/Signal/src/network/rtp/zrtp/MasterSecret.m index 4641dee0c..2b7736812 100644 --- a/Signal/src/network/rtp/zrtp/MasterSecret.m +++ b/Signal/src/network/rtp/zrtp/MasterSecret.m @@ -1,164 +1,164 @@ #import "MasterSecret.h" #import "ShortAuthenticationStringGenerator.h" -#define INITIATOR_SRTP_KEY_LABEL @"Initiator SRTP master key" -#define RESPONDER_SRTP_KEY_LABEL @"Responder SRTP master key" +#define INITIATOR_SRTP_KEY_LABEL @"Initiator SRTP master key" +#define RESPONDER_SRTP_KEY_LABEL @"Responder SRTP master key" #define INITIATOR_SRTP_SALT_LABEL @"Initiator SRTP master salt" #define RESPONDER_SRTP_SALT_LABEL @"Responder SRTP master salt" -#define INITIATOR_MAC_KEY_LABEL @"Initiator HMAC key" -#define RESPONDER_MAC_KEY_LABEL @"Responder HMAC key" -#define INITIATOR_ZRTP_KEY_LABEL @"Initiator ZRTP key" -#define RESPONDER_ZRTP_KEY_LABEL @"Responder ZRTP key" -#define SAS_LABEL @"SAS" +#define INITIATOR_MAC_KEY_LABEL @"Initiator HMAC key" +#define RESPONDER_MAC_KEY_LABEL @"Responder HMAC key" +#define INITIATOR_ZRTP_KEY_LABEL @"Initiator ZRTP key" +#define RESPONDER_ZRTP_KEY_LABEL @"Responder ZRTP key" +#define SAS_LABEL @"SAS" -#define INITIATOR_SRTP_KEY_LENGTH 16 -#define RESPONDER_SRTP_KEY_LENGTH 16 +#define INITIATOR_SRTP_KEY_LENGTH 16 +#define RESPONDER_SRTP_KEY_LENGTH 16 #define INITIATOR_SRTP_SALT_LENGTH 14 #define RESPONDER_SRTP_SALT_LENGTH 14 -#define INITIATOR_MAC_KEY_LENGTH 20 -#define RESPONDER_MAC_KEY_LENGTH 20 -#define INITIATOR_ZRTP_KEY_LENGTH 16 -#define RESPONDER_ZRTP_KEY_LENGTH 16 -#define SAS_LENGTH 4 +#define INITIATOR_MAC_KEY_LENGTH 20 +#define RESPONDER_MAC_KEY_LENGTH 20 +#define INITIATOR_ZRTP_KEY_LENGTH 16 +#define RESPONDER_ZRTP_KEY_LENGTH 16 +#define SAS_LENGTH 4 @implementation MasterSecret -@synthesize initiatorMacKey, initiatorSrtpSalt, initiatorZrtpKey, initiatorSrtpKey, initiatorZid, - responderMacKey, responderSrtpSalt, responderZrtpKey, responderSrtpKey, responderZid, - shortAuthenticationStringData, sharedSecret, totalHash, counter; +@synthesize initiatorMacKey, initiatorSrtpSalt, initiatorZrtpKey, initiatorSrtpKey, initiatorZid, responderMacKey, + responderSrtpSalt, responderZrtpKey, responderSrtpKey, responderZid, shortAuthenticationStringData, sharedSecret, + totalHash, counter; -+(MasterSecret*) masterSecretFromDhResult:(NSData*)dhResult - andInitiatorHello:(HelloPacket*)initiatorHello - andResponderHello:(HelloPacket*)responderHello - andCommit:(CommitPacket*)commit - andDhPart1:(DhPacket*)dhPart1 - andDhPart2:(DhPacket*)dhPart2 { - require(dhResult != nil); - require(initiatorHello != nil); - require(responderHello != nil); - require(commit != nil); - require(dhPart1 != nil); - require(dhPart2 != nil); - - NSData* totalHash = [self calculateTotalHashFromResponderHello:responderHello ++ (MasterSecret *)masterSecretFromDhResult:(NSData *)dhResult + andInitiatorHello:(HelloPacket *)initiatorHello + andResponderHello:(HelloPacket *)responderHello + andCommit:(CommitPacket *)commit + andDhPart1:(DhPacket *)dhPart1 + andDhPart2:(DhPacket *)dhPart2 { + ows_require(dhResult != nil); + ows_require(initiatorHello != nil); + ows_require(responderHello != nil); + ows_require(commit != nil); + ows_require(dhPart1 != nil); + ows_require(dhPart2 != nil); + + NSData *totalHash = [self calculateTotalHashFromResponderHello:responderHello andCommit:commit andDhPart1:dhPart1 andDhPart2:dhPart2]; - - NSData* sharedSecret = [self calculateSharedSecretFromDhResult:dhResult + + NSData *sharedSecret = [self calculateSharedSecretFromDhResult:dhResult andTotalHash:totalHash andInitiatorZid:[initiatorHello zid] andResponderZid:[responderHello zid]]; - + return [MasterSecret masterSecretFromSharedSecret:sharedSecret andTotalHash:totalHash andInitiatorZid:[initiatorHello zid] andResponderZid:[responderHello zid]]; - } -+(NSData*) calculateSharedSecretFromDhResult:(NSData*)dhResult - andTotalHash:(NSData*)totalHash - andInitiatorZid:(Zid*)initiatorZid - andResponderZid:(Zid*)responderZid { - require(dhResult != nil); - require(totalHash != nil); - require(initiatorZid != nil); - require(responderZid != nil); - - NSData* counter = [NSData dataWithBigEndianBytesOfUInt32:1]; - NSData* s1Length = [NSData dataWithBigEndianBytesOfUInt32:0]; - NSData* s2Length = [NSData dataWithBigEndianBytesOfUInt32:0]; - NSData* s3Length = [NSData dataWithBigEndianBytesOfUInt32:0]; - - NSData* data = [@[ - - counter, - dhResult, - @"ZRTP-HMAC-KDF".encodedAsUtf8, - initiatorZid.getData, - responderZid.getData, - totalHash, - s1Length, - s2Length, - s3Length - - ] ows_concatDatas]; - ++ (NSData *)calculateSharedSecretFromDhResult:(NSData *)dhResult + andTotalHash:(NSData *)totalHash + andInitiatorZid:(Zid *)initiatorZid + andResponderZid:(Zid *)responderZid { + ows_require(dhResult != nil); + ows_require(totalHash != nil); + ows_require(initiatorZid != nil); + ows_require(responderZid != nil); + + NSData *counter = [NSData dataWithBigEndianBytesOfUInt32:1]; + NSData *s1Length = [NSData dataWithBigEndianBytesOfUInt32:0]; + NSData *s2Length = [NSData dataWithBigEndianBytesOfUInt32:0]; + NSData *s3Length = [NSData dataWithBigEndianBytesOfUInt32:0]; + + NSData *data = [@[ + + counter, + dhResult, + @"ZRTP-HMAC-KDF".encodedAsUtf8, + initiatorZid.getData, + responderZid.getData, + totalHash, + s1Length, + s2Length, + s3Length + + ] ows_concatDatas]; + return [data hashWithSha256]; } -+(NSData*) calculateTotalHashFromResponderHello:(HelloPacket*)responderHello - andCommit:(CommitPacket*)commit - andDhPart1:(DhPacket*)dhPart1 - andDhPart2:(DhPacket*)dhPart2 { - require(responderHello != nil); - require(commit != nil); - require(dhPart1 != nil); - require(dhPart2 != nil); - - NSData* data = [@[ - - [[responderHello embeddedIntoHandshakePacket] dataUsedForAuthentication], - [[commit embeddedIntoHandshakePacket] dataUsedForAuthentication], - [[dhPart1 embeddedIntoHandshakePacket] dataUsedForAuthentication], - [[dhPart2 embeddedIntoHandshakePacket] dataUsedForAuthentication] - - ] ows_concatDatas]; - ++ (NSData *)calculateTotalHashFromResponderHello:(HelloPacket *)responderHello + andCommit:(CommitPacket *)commit + andDhPart1:(DhPacket *)dhPart1 + andDhPart2:(DhPacket *)dhPart2 { + ows_require(responderHello != nil); + ows_require(commit != nil); + ows_require(dhPart1 != nil); + ows_require(dhPart2 != nil); + + NSData *data = [@[ + + [[responderHello embeddedIntoHandshakePacket] dataUsedForAuthentication], + [[commit embeddedIntoHandshakePacket] dataUsedForAuthentication], + [[dhPart1 embeddedIntoHandshakePacket] dataUsedForAuthentication], + [[dhPart2 embeddedIntoHandshakePacket] dataUsedForAuthentication] + + ] ows_concatDatas]; + return [data hashWithSha256]; - } -+(MasterSecret*) masterSecretFromSharedSecret:(NSData*)sharedSecret - andTotalHash:(NSData*)totalHash - andInitiatorZid:(Zid*)initiatorZid - andResponderZid:(Zid*)responderZid { - require(sharedSecret != nil); - require(totalHash != nil); - require(initiatorZid != nil); - require(responderZid != nil); - - MasterSecret* s = [MasterSecret new]; - - s->initiatorZid = initiatorZid; - s->responderZid = responderZid; - s->totalHash = totalHash; - s->sharedSecret = sharedSecret; - s->counter = [NSData dataWithBigEndianBytesOfUInt32:1]; - - s->initiatorSrtpKey = [s deriveKeyWithLabel:INITIATOR_SRTP_KEY_LABEL andTruncatedLength:INITIATOR_SRTP_KEY_LENGTH]; - s->responderSrtpKey = [s deriveKeyWithLabel:RESPONDER_SRTP_KEY_LABEL andTruncatedLength:RESPONDER_SRTP_KEY_LENGTH]; - s->initiatorSrtpSalt = [s deriveKeyWithLabel:INITIATOR_SRTP_SALT_LABEL andTruncatedLength:INITIATOR_SRTP_SALT_LENGTH]; - s->responderSrtpSalt = [s deriveKeyWithLabel:RESPONDER_SRTP_SALT_LABEL andTruncatedLength:RESPONDER_SRTP_SALT_LENGTH]; - s->initiatorMacKey = [s deriveKeyWithLabel:INITIATOR_MAC_KEY_LABEL andTruncatedLength:INITIATOR_MAC_KEY_LENGTH]; - s->responderMacKey = [s deriveKeyWithLabel:RESPONDER_MAC_KEY_LABEL andTruncatedLength:RESPONDER_MAC_KEY_LENGTH]; - s->initiatorZrtpKey = [s deriveKeyWithLabel:INITIATOR_ZRTP_KEY_LABEL andTruncatedLength:INITIATOR_ZRTP_KEY_LENGTH]; - s->responderZrtpKey = [s deriveKeyWithLabel:RESPONDER_ZRTP_KEY_LABEL andTruncatedLength:RESPONDER_ZRTP_KEY_LENGTH]; - s->shortAuthenticationStringData = [s deriveKeyWithLabel:SAS_LABEL andTruncatedLength:SAS_LENGTH]; - ++ (MasterSecret *)masterSecretFromSharedSecret:(NSData *)sharedSecret + andTotalHash:(NSData *)totalHash + andInitiatorZid:(Zid *)initiatorZid + andResponderZid:(Zid *)responderZid { + ows_require(sharedSecret != nil); + ows_require(totalHash != nil); + ows_require(initiatorZid != nil); + ows_require(responderZid != nil); + + MasterSecret *s = [MasterSecret new]; + + s->initiatorZid = initiatorZid; + s->responderZid = responderZid; + s->totalHash = totalHash; + s->sharedSecret = sharedSecret; + s->counter = [NSData dataWithBigEndianBytesOfUInt32:1]; + + s->initiatorSrtpKey = [s deriveKeyWithLabel:INITIATOR_SRTP_KEY_LABEL andTruncatedLength:INITIATOR_SRTP_KEY_LENGTH]; + s->responderSrtpKey = [s deriveKeyWithLabel:RESPONDER_SRTP_KEY_LABEL andTruncatedLength:RESPONDER_SRTP_KEY_LENGTH]; + s->initiatorSrtpSalt = + [s deriveKeyWithLabel:INITIATOR_SRTP_SALT_LABEL andTruncatedLength:INITIATOR_SRTP_SALT_LENGTH]; + s->responderSrtpSalt = + [s deriveKeyWithLabel:RESPONDER_SRTP_SALT_LABEL andTruncatedLength:RESPONDER_SRTP_SALT_LENGTH]; + s->initiatorMacKey = [s deriveKeyWithLabel:INITIATOR_MAC_KEY_LABEL andTruncatedLength:INITIATOR_MAC_KEY_LENGTH]; + s->responderMacKey = [s deriveKeyWithLabel:RESPONDER_MAC_KEY_LABEL andTruncatedLength:RESPONDER_MAC_KEY_LENGTH]; + s->initiatorZrtpKey = [s deriveKeyWithLabel:INITIATOR_ZRTP_KEY_LABEL andTruncatedLength:INITIATOR_ZRTP_KEY_LENGTH]; + s->responderZrtpKey = [s deriveKeyWithLabel:RESPONDER_ZRTP_KEY_LABEL andTruncatedLength:RESPONDER_ZRTP_KEY_LENGTH]; + s->shortAuthenticationStringData = [s deriveKeyWithLabel:SAS_LABEL andTruncatedLength:SAS_LENGTH]; + return s; } --(NSData*) deriveKeyWithLabel:(NSString*)label andTruncatedLength:(uint16_t)truncatedLength { - NSData* input = @[ - - counter, - label.encodedAsUtf8, - [@[@0] ows_toUint8Data], - initiatorZid.getData, - responderZid.getData, - totalHash, - [NSData dataWithBigEndianBytesOfUInt32:truncatedLength] - - ].ows_concatDatas; - - NSData* digest = [input hmacWithSha256WithKey:sharedSecret]; - +- (NSData *)deriveKeyWithLabel:(NSString *)label andTruncatedLength:(uint16_t)truncatedLength { + NSData *input = @[ + + counter, + label.encodedAsUtf8, + [@[ @0 ] ows_toUint8Data], + initiatorZid.getData, + responderZid.getData, + totalHash, + [NSData dataWithBigEndianBytesOfUInt32:truncatedLength] + + ].ows_concatDatas; + + NSData *digest = [input hmacWithSha256WithKey:sharedSecret]; + return [digest take:truncatedLength]; } --(NSString*) shortAuthenticationString { +- (NSString *)shortAuthenticationString { return [ShortAuthenticationStringGenerator generateFromData:shortAuthenticationStringData]; } diff --git a/Signal/src/network/rtp/zrtp/ShortAuthenticationStringGenerator.m b/Signal/src/network/rtp/zrtp/ShortAuthenticationStringGenerator.m index 7e73b070f..d9583f09f 100644 --- a/Signal/src/network/rtp/zrtp/ShortAuthenticationStringGenerator.m +++ b/Signal/src/network/rtp/zrtp/ShortAuthenticationStringGenerator.m @@ -78,8 +78,8 @@ const char* PGP_LIST_ODD[] = { @implementation ShortAuthenticationStringGenerator +(NSString*) generateFromData:(NSData*)sasBytes { - require(sasBytes != nil); - require(sasBytes.length >= MIN_SAS_BYTES); + ows_require(sasBytes != nil); + ows_require(sasBytes.length >= MIN_SAS_BYTES); uint8_t wordIndexOne = [sasBytes uint8At:0]; uint8_t wordIndexTwo = [sasBytes uint8At:1]; diff --git a/Signal/src/network/rtp/zrtp/ZrtpHandshakeResult.m b/Signal/src/network/rtp/zrtp/ZrtpHandshakeResult.m index 17f24adc7..17399c4e2 100644 --- a/Signal/src/network/rtp/zrtp/ZrtpHandshakeResult.m +++ b/Signal/src/network/rtp/zrtp/ZrtpHandshakeResult.m @@ -5,8 +5,8 @@ @synthesize masterSecret, secureRtpSocket; +(ZrtpHandshakeResult*) zrtpHandshakeResultWithSecureChannel:(SrtpSocket*)secureRtpSocket andMasterSecret:(MasterSecret*)masterSecret { - require(secureRtpSocket != nil); - require(masterSecret != nil); + ows_require(secureRtpSocket != nil); + ows_require(masterSecret != nil); ZrtpHandshakeResult* z = [ZrtpHandshakeResult new]; z->masterSecret = masterSecret; diff --git a/Signal/src/network/rtp/zrtp/ZrtpHandshakeSocket.m b/Signal/src/network/rtp/zrtp/ZrtpHandshakeSocket.m index 497986a82..34766f6a5 100644 --- a/Signal/src/network/rtp/zrtp/ZrtpHandshakeSocket.m +++ b/Signal/src/network/rtp/zrtp/ZrtpHandshakeSocket.m @@ -3,7 +3,7 @@ @implementation ZrtpHandshakeSocket +(ZrtpHandshakeSocket*) zrtpHandshakeSocketOverRtp:(RtpSocket*)rtpSocket { - require(rtpSocket != nil); + ows_require(rtpSocket != nil); ZrtpHandshakeSocket* z = [ZrtpHandshakeSocket new]; z->rtpSocket = rtpSocket; @@ -12,7 +12,7 @@ return z; } -(void) send:(HandshakePacket*)packet { - require(packet != nil); + ows_require(packet != nil); uint16_t sequenceNumber = nextPacketSequenceNumber; nextPacketSequenceNumber += 1; [sentPacketsLogger markOccurrence:packet]; @@ -20,14 +20,14 @@ usingInteropOptions:rtpSocket->interopOptions]]; } -(void) startWithHandler:(PacketHandler*)handler untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(handler != nil); + ows_require(handler != nil); requireState(handshakePacketHandler == nil); handshakePacketHandler = handler; PacketHandlerBlock packetHandler = ^(id packet) { - require(packet != nil); - require([packet isKindOfClass:RtpPacket.class]); + ows_require(packet != nil); + ows_require([packet isKindOfClass:RtpPacket.class]); RtpPacket* rtpPacket = packet; HandshakePacket* handshakePacket = nil; diff --git a/Signal/src/network/rtp/zrtp/ZrtpInitiator.m b/Signal/src/network/rtp/zrtp/ZrtpInitiator.m index defe7849a..d06f1a03a 100644 --- a/Signal/src/network/rtp/zrtp/ZrtpInitiator.m +++ b/Signal/src/network/rtp/zrtp/ZrtpInitiator.m @@ -1,7 +1,7 @@ #import "ConfirmPacket.h" #import "MasterSecret.h" -#import "ZrtpInitiator.h" #import "SignalKeyingStorage.h" +#import "ZrtpInitiator.h" #define DHRS1_LENGTH 8 #define DHRS2_LENGTH 8 @@ -11,157 +11,170 @@ @implementation ZrtpInitiator -+(ZrtpInitiator*) zrtpInitiatorWithCallController:(CallController*)callController { - require(callController != nil); - - ZrtpInitiator* s = [ZrtpInitiator new]; - ++ (ZrtpInitiator *)zrtpInitiatorWithCallController:(CallController *)callController { + ows_require(callController != nil); + + ZrtpInitiator *s = [ZrtpInitiator new]; + s->allowedKeyAgreementProtocols = Environment.getCurrent.keyAgreementProtocolsInDescendingPriority; - s->dhSharedSecretHashes = [DhPacketSharedSecretHashes dhPacketSharedSecretHashesRandomized]; - s->zid = [SignalKeyingStorage zid]; - s->confirmIv = [CryptoTools generateSecureRandomData:IV_LENGTH]; - s->hashChain = [HashChain hashChainWithSecureGeneratedData]; - s->badPacketLogger = [Environment.logging getOccurrenceLoggerForSender:self withKey:@"Bad Packet"]; - s->packetExpectation = EXPECTING_HELLO; - s->callController = callController; - + s->dhSharedSecretHashes = [DhPacketSharedSecretHashes dhPacketSharedSecretHashesRandomized]; + s->zid = [Zid nullZid]; + s->confirmIv = [CryptoTools generateSecureRandomData:IV_LENGTH]; + s->hashChain = [HashChain hashChainWithSecureGeneratedData]; + s->badPacketLogger = [Environment.logging getOccurrenceLoggerForSender:self withKey:@"Bad Packet"]; + s->packetExpectation = EXPECTING_HELLO; + s->callController = callController; + return s; } --(MasterSecret*) getMasterSecret { +- (MasterSecret *)getMasterSecret { requireState(self.hasHandshakeFinishedSuccessfully); return masterSecret; } --(HandshakePacket*) initialPacket { +- (HandshakePacket *)initialPacket { return nil; } --(bool) hasHandshakeFinishedSuccessfully { +- (bool)hasHandshakeFinishedSuccessfully { return packetExpectation == EXPECTING_NOTHING; } --(HandshakePacket*) handlePacket:(HandshakePacket*)packet { +- (HandshakePacket *)handlePacket:(HandshakePacket *)packet { @try { - if (packetExpectation == EXPECTING_NOTHING) return nil; - else if (packetExpectation == EXPECTING_HELLO) return [self handleHello:packet]; - else if (packetExpectation == EXPECTING_HELLO_ACK) return [self handleHelloAck:packet]; - else if (packetExpectation == EXPECTING_DH) return [self handleDH:packet]; - else if (packetExpectation == EXPECTING_CONFIRM) return [self handleConfirmOne:packet]; - else if (packetExpectation == EXPECTING_CONFIRM_ACK) return [self handleConfirmAck:packet]; - else return nil; - - }@catch (SecurityFailure *exception) { - [callController terminateWithReason:CallTerminationType_HandshakeFailed withFailureInfo:exception andRelatedInfo:packet]; + if (packetExpectation == EXPECTING_NOTHING) + return nil; + else if (packetExpectation == EXPECTING_HELLO) + return [self handleHello:packet]; + else if (packetExpectation == EXPECTING_HELLO_ACK) + return [self handleHelloAck:packet]; + else if (packetExpectation == EXPECTING_DH) + return [self handleDH:packet]; + else if (packetExpectation == EXPECTING_CONFIRM) + return [self handleConfirmOne:packet]; + else if (packetExpectation == EXPECTING_CONFIRM_ACK) + return [self handleConfirmAck:packet]; + else + return nil; + + } @catch (SecurityFailure *exception) { + [callController terminateWithReason:CallTerminationType_HandshakeFailed + withFailureInfo:exception + andRelatedInfo:packet]; return nil; - } @catch (OperationFailed* ex) { + } @catch (OperationFailed *ex) { [badPacketLogger markOccurrence:ex]; return nil; } } --(HandshakePacket*) handleHello:(HandshakePacket*) packet { +- (HandshakePacket *)handleHello:(HandshakePacket *)packet { foreignHello = [packet parsedAsHello]; - + [callController advanceCallProgressTo:CallProgressType_Securing]; keyAgreementParticipant = [self retrieveKeyAgreementParticpant]; - - localHello = [HelloPacket helloPacketWithDefaultsAndHashChain:hashChain - andZid:zid - andKeyAgreementProtocols:allowedKeyAgreementProtocols]; - + + localHello = [HelloPacket helloPacketWithDefaultsAndHashChain:hashChain + andZid:zid + andKeyAgreementProtocols:allowedKeyAgreementProtocols]; + packetExpectation = EXPECTING_HELLO_ACK; - + return [localHello embeddedIntoHandshakePacket]; } --(HandshakePacket*) handleHelloAck:(HandshakePacket*) packet { +- (HandshakePacket *)handleHelloAck:(HandshakePacket *)packet { [packet parsedAsHelloAck]; - + [self retrieveKeyAgreementParticpant]; - + localDH = [DhPacket dh2PacketWithHashChain:hashChain andSharedSecretHashes:dhSharedSecretHashes andKeyAgreer:keyAgreementParticipant]; - + commitPacket = [CommitPacket commitPacketWithDefaultSpecsAndKeyAgreementProtocol:keyAgreementParticipant.getProtocol andHashChain:hashChain andZid:zid andCommitmentToHello:foreignHello andDhPart2:localDH]; - + packetExpectation = EXPECTING_DH; - + return [commitPacket embeddedIntoHandshakePacket]; } --(HandshakePacket*) handleDH:(HandshakePacket*) packet { +- (HandshakePacket *)handleDH:(HandshakePacket *)packet { foreignDH = [packet parsedAsDh1]; - + [foreignHello verifyMacWithHashChainH2:[[foreignDH hashChainH1] hashWithSha256]]; - - NSData* dhResult = [keyAgreementParticipant calculateKeyAgreementAgainstRemotePublicKey:[foreignDH publicKeyData]]; - + + NSData *dhResult = [keyAgreementParticipant calculateKeyAgreementAgainstRemotePublicKey:[foreignDH publicKeyData]]; + masterSecret = [MasterSecret masterSecretFromDhResult:dhResult andInitiatorHello:localHello andResponderHello:foreignHello andCommit:commitPacket andDhPart1:foreignDH andDhPart2:localDH]; - + packetExpectation = EXPECTING_CONFIRM; return [localDH embeddedIntoHandshakePacket]; } --(HandshakePacket*) handleConfirmOne:(HandshakePacket*) packet { - ConfirmPacket* confirmPacket = [packet parsedAsConfirm1AuthenticatedWithMacKey:[masterSecret responderMacKey] andCipherKey:[masterSecret responderZrtpKey]]; - - NSData* preimage = [confirmPacket hashChainH0]; +- (HandshakePacket *)handleConfirmOne:(HandshakePacket *)packet { + ConfirmPacket *confirmPacket = [packet parsedAsConfirm1AuthenticatedWithMacKey:[masterSecret responderMacKey] + andCipherKey:[masterSecret responderZrtpKey]]; + + NSData *preimage = [confirmPacket hashChainH0]; [foreignDH verifyMacWithHashChainH0:preimage]; - - packetExpectation = EXPECTING_CONFIRM_ACK; - ConfirmPacket* confirm2Packet = [ConfirmPacket confirm2PacketWithHashChain:hashChain + + packetExpectation = EXPECTING_CONFIRM_ACK; + ConfirmPacket *confirm2Packet = [ConfirmPacket confirm2PacketWithHashChain:hashChain andMacKey:[masterSecret initiatorMacKey] andCipherKey:[masterSecret initiatorZrtpKey] andIv:confirmIv]; return [confirm2Packet embeddedIntoHandshakePacket]; } --(HandshakePacket*) handleConfirmAck:(HandshakePacket*) packet { +- (HandshakePacket *)handleConfirmAck:(HandshakePacket *)packet { [packet parsedAsConfAck]; - + packetExpectation = EXPECTING_NOTHING; return nil; } --(bool) isAuthenticatedAudioDataImplyingConf2Ack:(id)packet { - if (packetExpectation != EXPECTING_CONFIRM_ACK) return false; - if (![packet isKindOfClass:RtpPacket.class]) return false; - +- (bool)isAuthenticatedAudioDataImplyingConf2Ack:(id)packet { + if (packetExpectation != EXPECTING_CONFIRM_ACK) + return false; + if (![packet isKindOfClass:RtpPacket.class]) + return false; + @try { - SrtpStream* incomingContext = [SrtpStream srtpStreamWithCipherKey:[masterSecret responderSrtpKey] + SrtpStream *incomingContext = [SrtpStream srtpStreamWithCipherKey:[masterSecret responderSrtpKey] andMacKey:[masterSecret responderMacKey] andCipherIvSalt:[masterSecret responderSrtpSalt]]; [incomingContext verifyAuthenticationAndDecryptSecuredRtpPacket:packet]; return true; - } @catch (OperationFailed* ex) { + } @catch (OperationFailed *ex) { return false; } } --(id) retrieveKeyAgreementParticpant{ - NSArray* idsOfProtocolsAllowedByPeer = [foreignHello agreeIdsIncludingImplied]; +- (id)retrieveKeyAgreementParticpant { + NSArray *idsOfProtocolsAllowedByPeer = [foreignHello agreeIdsIncludingImplied]; + + id bestCommonKeyAgreementProtocol = + [allowedKeyAgreementProtocols firstMatchingElseNil:^int(id locallyAllowedProtocol) { + return [idsOfProtocolsAllowedByPeer containsObject:locallyAllowedProtocol.getId]; + }]; - id bestCommonKeyAgreementProtocol = [allowedKeyAgreementProtocols firstMatchingElseNil:^int(id locallyAllowedProtocol) { - return [idsOfProtocolsAllowedByPeer containsObject:locallyAllowedProtocol.getId]; - }]; - // Note: should never fail to find a common protocol because DH3k support is required and implied checkOperation(bestCommonKeyAgreementProtocol != nil); return [bestCommonKeyAgreementProtocol generateParticipantWithNewKeys]; } --(SrtpSocket*) useKeysToSecureRtpSocket:(RtpSocket*)rtpSocket { +- (SrtpSocket *)useKeysToSecureRtpSocket:(RtpSocket *)rtpSocket { requireState(self.hasHandshakeFinishedSuccessfully); return [SrtpSocket srtpSocketOverRtp:rtpSocket andIncomingCipherKey:[masterSecret responderSrtpKey] diff --git a/Signal/src/network/rtp/zrtp/ZrtpManager.m b/Signal/src/network/rtp/zrtp/ZrtpManager.m index 106b2b3f5..03b516547 100644 --- a/Signal/src/network/rtp/zrtp/ZrtpManager.m +++ b/Signal/src/network/rtp/zrtp/ZrtpManager.m @@ -15,8 +15,8 @@ +(TOCFuture*) asyncPerformHandshakeOver:(RtpSocket*)rtpSocket andCallController:(CallController*)callController { - require(rtpSocket != nil); - require(callController != nil); + ows_require(rtpSocket != nil); + ows_require(callController != nil); ZrtpHandshakeSocket* handshakeChannel = [ZrtpHandshakeSocket zrtpHandshakeSocketOverRtp:rtpSocket]; @@ -37,10 +37,10 @@ andZrtpRole:(id)zrtpRole andCallController:(CallController*)callController { - require(handshakeSocket != nil); - require(rtpSocket != nil); - require(callController != nil); - require(zrtpRole != nil); + ows_require(handshakeSocket != nil); + ows_require(rtpSocket != nil); + ows_require(callController != nil); + ows_require(zrtpRole != nil); ZrtpManager* manager = [ZrtpManager new]; @@ -63,8 +63,8 @@ -(TOCFuture*) asyncPerformHandshake { PacketHandlerBlock packetHandler = ^(id packet) { - require(packet != nil); - require([packet isKindOfClass:HandshakePacket.class]); + ows_require(packet != nil); + ows_require([packet isKindOfClass:HandshakePacket.class]); [self handleHandshakePacket:(HandshakePacket*)packet]; }; @@ -163,7 +163,7 @@ } -(void) handleHandshakePacket:(HandshakePacket*)packet { - require(packet != nil); + ows_require(packet != nil); if (done) return; HandshakePacket* response = [zrtpRole handlePacket:packet]; diff --git a/Signal/src/network/rtp/zrtp/ZrtpResponder.m b/Signal/src/network/rtp/zrtp/ZrtpResponder.m index b29040ae6..28b15b139 100644 --- a/Signal/src/network/rtp/zrtp/ZrtpResponder.m +++ b/Signal/src/network/rtp/zrtp/ZrtpResponder.m @@ -1,10 +1,10 @@ #import "CommitPacket.h" -#import "ConfirmPacket.h" -#import "MasterSecret.h" -#import "ZrtpResponder.h" -#import "HelloAckPacket.h" #import "ConfirmAckPacket.h" +#import "ConfirmPacket.h" +#import "HelloAckPacket.h" +#import "MasterSecret.h" #import "SignalKeyingStorage.h" +#import "ZrtpResponder.h" #define DHRS1_LENGTH 8 #define DHRS2_LENGTH 8 @@ -14,136 +14,146 @@ @implementation ZrtpResponder -+(ZrtpResponder*) zrtpResponderWithCallController:(CallController*)callController { - require(callController != nil); - - ZrtpResponder* s = [ZrtpResponder new]; - - s->confirmIv = [CryptoTools generateSecureRandomData:IV_LENGTH]; - s->dhSharedSecretHashes = [DhPacketSharedSecretHashes dhPacketSharedSecretHashesRandomized]; ++ (ZrtpResponder *)zrtpResponderWithCallController:(CallController *)callController { + ows_require(callController != nil); + + ZrtpResponder *s = [ZrtpResponder new]; + + s->confirmIv = [CryptoTools generateSecureRandomData:IV_LENGTH]; + s->dhSharedSecretHashes = [DhPacketSharedSecretHashes dhPacketSharedSecretHashesRandomized]; s->allowedKeyAgreementProtocols = Environment.getCurrent.keyAgreementProtocolsInDescendingPriority; - s->hashChain = [HashChain hashChainWithSecureGeneratedData]; - s->badPacketLogger = [Environment.logging getOccurrenceLoggerForSender:self withKey:@"Bad Packet"]; - + s->hashChain = [HashChain hashChainWithSecureGeneratedData]; + s->badPacketLogger = [Environment.logging getOccurrenceLoggerForSender:self withKey:@"Bad Packet"]; + s->localHello = [HelloPacket helloPacketWithDefaultsAndHashChain:s->hashChain - andZid:[SignalKeyingStorage zid] + andZid:[Zid nullZid] andKeyAgreementProtocols:s->allowedKeyAgreementProtocols]; s->packetExpectation = EXPECTING_HELLO; - s->callController = callController; + s->callController = callController; return s; } --(HandshakePacket*) initialPacket { +- (HandshakePacket *)initialPacket { [callController advanceCallProgressTo:CallProgressType_Securing]; return [localHello embeddedIntoHandshakePacket]; } --(bool) hasHandshakeFinishedSuccessfully { +- (bool)hasHandshakeFinishedSuccessfully { return packetExpectation == EXPECTING_NOTHING; } --(HandshakePacket*) handlePacket:(HandshakePacket*)packet { +- (HandshakePacket *)handlePacket:(HandshakePacket *)packet { @try { - if (packetExpectation == EXPECTING_NOTHING){ return nil;} - else if (packetExpectation == EXPECTING_HELLO){ return [self handleHello:packet];} - else if (packetExpectation == EXPECTING_COMMIT){ return [self handleCommit:packet];} - else if (packetExpectation == EXPECTING_DH){ return [self handleDH:packet];} - else if (packetExpectation == EXPECTING_CONFIRM) { return [self handleConfirmTwo:packet];} - else {return nil;} - } @catch (SecurityFailure* ex) { - [callController terminateWithReason:CallTerminationType_HandshakeFailed withFailureInfo:ex andRelatedInfo:packet]; + if (packetExpectation == EXPECTING_NOTHING) { + return nil; + } else if (packetExpectation == EXPECTING_HELLO) { + return [self handleHello:packet]; + } else if (packetExpectation == EXPECTING_COMMIT) { + return [self handleCommit:packet]; + } else if (packetExpectation == EXPECTING_DH) { + return [self handleDH:packet]; + } else if (packetExpectation == EXPECTING_CONFIRM) { + return [self handleConfirmTwo:packet]; + } else { + return nil; + } + } @catch (SecurityFailure *ex) { + [callController terminateWithReason:CallTerminationType_HandshakeFailed + withFailureInfo:ex + andRelatedInfo:packet]; return nil; - } @catch (OperationFailed* ex) { + } @catch (OperationFailed *ex) { [badPacketLogger markOccurrence:ex]; return nil; } } --(HandshakePacket*) handleHello:(HandshakePacket*)packet { +- (HandshakePacket *)handleHello:(HandshakePacket *)packet { foreignHello = [packet parsedAsHello]; - + packetExpectation = EXPECTING_COMMIT; - + return [[HelloAckPacket helloAckPacket] embeddedIntoHandshakePacket]; } --(HandshakePacket*) handleCommit:(HandshakePacket*)packet { - CommitPacket* cp = [packet parsedAsCommitPacket]; +- (HandshakePacket *)handleCommit:(HandshakePacket *)packet { + CommitPacket *cp = [packet parsedAsCommitPacket]; [foreignHello verifyMacWithHashChainH2:[cp h2]]; - + foreignCommit = cp; - + keyAgreementParticipant = [self retrieveKeyAgreementParticipant]; - + localDH = [DhPacket dh1PacketWithHashChain:hashChain andSharedSecretHashes:dhSharedSecretHashes andKeyAgreer:keyAgreementParticipant]; - + packetExpectation = EXPECTING_DH; - + return [localDH embeddedIntoHandshakePacket]; } --(MasterSecret*) getMasterSecret { +- (MasterSecret *)getMasterSecret { requireState(self.hasHandshakeFinishedSuccessfully); return masterSecret; } --(HandshakePacket*) handleDH:(HandshakePacket*)packet { +- (HandshakePacket *)handleDH:(HandshakePacket *)packet { foreignDH = [packet parsedAsDh2]; - + [foreignCommit verifyMacWithHashChainH1:[foreignDH hashChainH1]]; - [foreignCommit verifyCommitmentAgainstHello:localHello - andDhPart2:foreignDH]; - - NSData* dhResult = [keyAgreementParticipant calculateKeyAgreementAgainstRemotePublicKey:[foreignDH publicKeyData]]; - + [foreignCommit verifyCommitmentAgainstHello:localHello andDhPart2:foreignDH]; + + NSData *dhResult = [keyAgreementParticipant calculateKeyAgreementAgainstRemotePublicKey:[foreignDH publicKeyData]]; + masterSecret = [MasterSecret masterSecretFromDhResult:dhResult andInitiatorHello:foreignHello andResponderHello:localHello andCommit:foreignCommit andDhPart1:localDH andDhPart2:foreignDH]; - + packetExpectation = EXPECTING_CONFIRM; - - ConfirmPacket* confirm2Packet = [ConfirmPacket confirm1PacketWithHashChain:hashChain + + ConfirmPacket *confirm2Packet = [ConfirmPacket confirm1PacketWithHashChain:hashChain andMacKey:[masterSecret responderMacKey] andCipherKey:[masterSecret responderZrtpKey] andIv:confirmIv]; - + return [confirm2Packet embeddedIntoHandshakePacket]; } --(HandshakePacket*) handleConfirmTwo:(HandshakePacket*)packet { - ConfirmPacket* confirmPacket = [packet parsedAsConfirm2AuthenticatedWithMacKey:[masterSecret initiatorMacKey] andCipherKey:[masterSecret initiatorZrtpKey]]; - +- (HandshakePacket *)handleConfirmTwo:(HandshakePacket *)packet { + ConfirmPacket *confirmPacket = [packet parsedAsConfirm2AuthenticatedWithMacKey:[masterSecret initiatorMacKey] + andCipherKey:[masterSecret initiatorZrtpKey]]; + [foreignDH verifyMacWithHashChainH0:[confirmPacket hashChainH0]]; - + packetExpectation = EXPECTING_NOTHING; - + if ([Environment hasEnabledTestingOrLegacyOption:ENVIRONMENT_TESTING_OPTION_LOSE_CONF_ACK_ON_PURPOSE]) { return nil; } - + return [[ConfirmAckPacket confirmAckPacket] embeddedIntoHandshakePacket]; } --(bool) isAuthenticatedAudioDataImplyingConf2Ack:(id)packet { +- (bool)isAuthenticatedAudioDataImplyingConf2Ack:(id)packet { return false; // responder doesn't expect to receive Conf2Ack } --(id) retrieveKeyAgreementParticipant{ - id matchingKeyAgreeProtocol = [allowedKeyAgreementProtocols firstMatchingElseNil:^int(id a) { - return [[foreignCommit agreementSpecId] isEqualToData:a.getId]; - }]; - +- (id)retrieveKeyAgreementParticipant { + id matchingKeyAgreeProtocol = + [allowedKeyAgreementProtocols firstMatchingElseNil:^int(id a) { + return [[foreignCommit agreementSpecId] isEqualToData:a.getId]; + }]; + checkOperation(matchingKeyAgreeProtocol != nil); return [matchingKeyAgreeProtocol generateParticipantWithNewKeys]; } --(SrtpSocket*) useKeysToSecureRtpSocket:(RtpSocket*)rtpSocket { +- (SrtpSocket *)useKeysToSecureRtpSocket:(RtpSocket *)rtpSocket { requireState(self.hasHandshakeFinishedSuccessfully); return [SrtpSocket srtpSocketOverRtp:rtpSocket andIncomingCipherKey:[masterSecret initiatorSrtpKey] diff --git a/Signal/src/network/rtp/zrtp/agreement/EvpKeyAgreement.m b/Signal/src/network/rtp/zrtp/agreement/EvpKeyAgreement.m index e4667ed32..fe1e78f67 100644 --- a/Signal/src/network/rtp/zrtp/agreement/EvpKeyAgreement.m +++ b/Signal/src/network/rtp/zrtp/agreement/EvpKeyAgreement.m @@ -182,7 +182,7 @@ enum KeyAgreementType { -(NSData*) serializeEcPublicKey:(EVP_PKEY*)evkey { - require(evkey != NULL); + ows_require(evkey != NULL); EC_KEY* ec_key = NULL; @try { diff --git a/Signal/src/network/rtp/zrtp/packets/CommitPacket.m b/Signal/src/network/rtp/zrtp/packets/CommitPacket.m index 62c3a7454..c52811cb6 100644 --- a/Signal/src/network/rtp/zrtp/packets/CommitPacket.m +++ b/Signal/src/network/rtp/zrtp/packets/CommitPacket.m @@ -27,11 +27,11 @@ andCommitmentToHello:(HelloPacket*)hello andDhPart2:(DhPacket*)dhPart2 { - require(keyAgreementProtocol != nil); - require(hashChain != nil); - require(zid != nil); - require(hello != nil); - require(dhPart2 != nil); + ows_require(keyAgreementProtocol != nil); + ows_require(hashChain != nil); + ows_require(zid != nil); + ows_require(hello != nil); + ows_require(dhPart2 != nil); NSData* dhPart2Data = [[dhPart2 embeddedIntoHandshakePacket] dataUsedForAuthentication]; NSData* helloData = [[hello embeddedIntoHandshakePacket] dataUsedForAuthentication]; @@ -56,22 +56,22 @@ andDhPart2HelloCommitment:(NSData*)dhPart2HelloCommitment andHmacKey:(NSData*)hmacKey { - require(h2 != nil); - require(zid != nil); - require(hashSpecId != nil); - require(cipherSpecId != nil); - require(authSpecId != nil); - require(agreeSpecId != nil); - require(sasSpecId != nil); - require(dhPart2HelloCommitment != nil); - require(hmacKey != nil); + ows_require(h2 != nil); + ows_require(zid != nil); + ows_require(hashSpecId != nil); + ows_require(cipherSpecId != nil); + ows_require(authSpecId != nil); + ows_require(agreeSpecId != nil); + ows_require(sasSpecId != nil); + ows_require(dhPart2HelloCommitment != nil); + ows_require(hmacKey != nil); - require(h2.length == HASH_CHAIN_ITEM_LENGTH); - require(hashSpecId.length == HASH_SPEC_LENGTH); - require(cipherSpecId.length == CIPHER_SPEC_LENGTH); - require(authSpecId.length == AUTH_SPEC_LENGTH); - require(agreeSpecId.length == AGREE_SPEC_LENGTH); - require(sasSpecId.length == SAS_SPEC_LENGTH); + ows_require(h2.length == HASH_CHAIN_ITEM_LENGTH); + ows_require(hashSpecId.length == HASH_SPEC_LENGTH); + ows_require(cipherSpecId.length == CIPHER_SPEC_LENGTH); + ows_require(authSpecId.length == AUTH_SPEC_LENGTH); + ows_require(agreeSpecId.length == AGREE_SPEC_LENGTH); + ows_require(sasSpecId.length == SAS_SPEC_LENGTH); CommitPacket* p = [CommitPacket new]; @@ -90,7 +90,7 @@ } -(HandshakePacket*) embedInHandshakePacketAuthenticatedWith:(NSData*)hmacKey { - require(hmacKey != nil); + ows_require(hmacKey != nil); requireState(h2.length == HASH_CHAIN_ITEM_LENGTH); requireState(hashSpecId.length == HASH_SPEC_LENGTH); requireState(cipherSpecId.length == CIPHER_SPEC_LENGTH); @@ -112,8 +112,8 @@ return [[HandshakePacket handshakePacketWithTypeId:HANDSHAKE_TYPE_COMMIT andPayload:payload] withHmacAppended:hmacKey]; } -(void) verifyCommitmentAgainstHello:(HelloPacket*)hello andDhPart2:(DhPacket*)dhPart2 { - require(hello != nil); - require(dhPart2 != nil); + ows_require(hello != nil); + ows_require(dhPart2 != nil); NSData* expected = [[@[ [[dhPart2 embeddedIntoHandshakePacket] dataUsedForAuthentication], @@ -151,7 +151,7 @@ return [payload subdataWithRange:NSMakeRange(COMMIT_OFFSET, COMMIT_LENGTH)]; } +(CommitPacket*) commitPacketParsedFromHandshakePacket:(HandshakePacket*)handshakePacket { - require(handshakePacket != nil); + ows_require(handshakePacket != nil); checkOperation([[handshakePacket typeId] isEqualToData:HANDSHAKE_TYPE_COMMIT]); NSData* payload = [handshakePacket payload]; checkOperation(payload.length == COMMIT_OFFSET + COMMIT_LENGTH + HANDSHAKE_TRUNCATED_HMAC_LENGTH); diff --git a/Signal/src/network/rtp/zrtp/packets/ConfirmPacket.m b/Signal/src/network/rtp/zrtp/packets/ConfirmPacket.m index 739e551fa..83e10491c 100644 --- a/Signal/src/network/rtp/zrtp/packets/ConfirmPacket.m +++ b/Signal/src/network/rtp/zrtp/packets/ConfirmPacket.m @@ -38,9 +38,9 @@ withMacKey:(NSData*)macKey andCipherKey:(NSData*)cipherKey andIsPart1:(bool)isPart1 { - require(handshakePacket != nil); - require(macKey != nil); - require(cipherKey != nil); + ows_require(handshakePacket != nil); + ows_require(macKey != nil); + ows_require(cipherKey != nil); NSData* expectedConfirmTypeId = isPart1 ? HANDSHAKE_TYPE_CONFIRM_1 : HANDSHAKE_TYPE_CONFIRM_2; checkOperation([[handshakePacket typeId] isEqualToData:expectedConfirmTypeId]); @@ -62,12 +62,12 @@ andCipherKey:(NSData*)cipherKey andIv:(NSData*)iv andIsPart1:(bool)isPart1 { - require(macKey != nil); - require(cipherKey != nil); - require(hashChainH0 != nil); - require(iv != nil); - require(iv.length == CONFIRM_IV_LENGTH); - require(hashChainH0.length == HASH_CHAIN_ITEM_LENGTH); + ows_require(macKey != nil); + ows_require(cipherKey != nil); + ows_require(hashChainH0 != nil); + ows_require(iv != nil); + ows_require(iv.length == CONFIRM_IV_LENGTH); + ows_require(hashChainH0.length == HASH_CHAIN_ITEM_LENGTH); ConfirmPacket* p = [ConfirmPacket new]; p->hashChainH0 = hashChainH0; @@ -80,8 +80,8 @@ } -(HandshakePacket*) generateEmbedding:(NSData*)cipherKey andMacKey:(NSData*)macKey { - require(cipherKey != nil); - require(macKey != nil); + ows_require(cipherKey != nil); + ows_require(macKey != nil); NSData* sensitiveData = [@[ hashChainH0, diff --git a/Signal/src/network/rtp/zrtp/packets/DhPacket.m b/Signal/src/network/rtp/zrtp/packets/DhPacket.m index cc9cc3e76..5e688cd14 100644 --- a/Signal/src/network/rtp/zrtp/packets/DhPacket.m +++ b/Signal/src/network/rtp/zrtp/packets/DhPacket.m @@ -17,9 +17,9 @@ andSharedSecretHashes:(DhPacketSharedSecretHashes*)sharedSecretHashes andKeyAgreer:(id)agreer { - require(hashChain != nil); - require(sharedSecretHashes != nil); - require(agreer != nil); + ows_require(hashChain != nil); + ows_require(sharedSecretHashes != nil); + ows_require(agreer != nil); return [self dhPacketWithHashChainH0:[hashChain h0] andSharedSecretHashes:sharedSecretHashes @@ -31,9 +31,9 @@ andSharedSecretHashes:(DhPacketSharedSecretHashes*)sharedSecretHashes andKeyAgreer:(id)agreer { - require(hashChain != nil); - require(sharedSecretHashes != nil); - require(agreer != nil); + ows_require(hashChain != nil); + ows_require(sharedSecretHashes != nil); + ows_require(agreer != nil); return [self dhPacketWithHashChainH0:[hashChain h0] andSharedSecretHashes:sharedSecretHashes @@ -46,11 +46,11 @@ andPublicKeyData:(NSData*)publicKeyData andIsPart1:(bool)isPart1 { - require(hashChainH0 != nil); - require(sharedSecretHashes != nil); - require(publicKeyData != nil); + ows_require(hashChainH0 != nil); + ows_require(sharedSecretHashes != nil); + ows_require(publicKeyData != nil); - require(hashChainH0.length == HASH_CHAIN_ITEM_LENGTH); + ows_require(hashChainH0.length == HASH_CHAIN_ITEM_LENGTH); DhPacket* p = [DhPacket new]; p->isPart1 = isPart1; @@ -86,7 +86,7 @@ +(DhPacket*) dhPacketFromHandshakePacket:(HandshakePacket*)handshakePacket andIsPart1:(bool)isPart1 { - require(handshakePacket != nil); + ows_require(handshakePacket != nil); NSData* expectedTypeIdDhPacket = isPart1 ? HANDSHAKE_TYPE_DH_1 : HANDSHAKE_TYPE_DH_2; NSData* payload = [handshakePacket payload]; @@ -102,7 +102,7 @@ } -(HandshakePacket*) embedIntoHandshakePacketAuthenticatedWithMacKey:(NSData*)macKey { - require(macKey != nil); + ows_require(macKey != nil); requireState(hashChainH1.length == HASH_CHAIN_ITEM_LENGTH); NSData* typeId = isPart1 ? HANDSHAKE_TYPE_DH_1 : HANDSHAKE_TYPE_DH_2; diff --git a/Signal/src/network/rtp/zrtp/packets/DhPacketSharedSecretHashes.m b/Signal/src/network/rtp/zrtp/packets/DhPacketSharedSecretHashes.m index 852ba5068..aa3649aca 100644 --- a/Signal/src/network/rtp/zrtp/packets/DhPacketSharedSecretHashes.m +++ b/Signal/src/network/rtp/zrtp/packets/DhPacketSharedSecretHashes.m @@ -17,15 +17,15 @@ andRs2:(NSData*)rs2 andAux:(NSData*)aux andPbx:(NSData*)pbx { - require(rs1 != nil); - require(rs2 != nil); - require(aux != nil); - require(pbx != nil); + ows_require(rs1 != nil); + ows_require(rs2 != nil); + ows_require(aux != nil); + ows_require(pbx != nil); - require(rs1.length == DH_RS1_LENGTH); - require(rs2.length == DH_RS2_LENGTH); - require(aux.length == DH_AUX_LENGTH); - require(pbx.length == DH_PBX_LENGTH); + ows_require(rs1.length == DH_RS1_LENGTH); + ows_require(rs2.length == DH_RS2_LENGTH); + ows_require(aux.length == DH_AUX_LENGTH); + ows_require(pbx.length == DH_PBX_LENGTH); DhPacketSharedSecretHashes* h = [DhPacketSharedSecretHashes new]; h->rs1 = rs1; diff --git a/Signal/src/network/rtp/zrtp/packets/HandshakePacket.m b/Signal/src/network/rtp/zrtp/packets/HandshakePacket.m index b8241314e..99713e1ac 100644 --- a/Signal/src/network/rtp/zrtp/packets/HandshakePacket.m +++ b/Signal/src/network/rtp/zrtp/packets/HandshakePacket.m @@ -19,9 +19,9 @@ @synthesize payload, typeId; +(HandshakePacket*) handshakePacketWithTypeId:(NSData*)typeId andPayload:(NSData*)payload { - require(typeId != nil); - require(payload != nil); - require(typeId.length == HANDSHAKE_TYPE_ID_LENGTH); + ows_require(typeId != nil); + ows_require(payload != nil); + ows_require(typeId.length == HANDSHAKE_TYPE_ID_LENGTH); HandshakePacket* p = [HandshakePacket new]; p->typeId = typeId; @@ -39,7 +39,7 @@ return [[[rtpPacket extensionHeaderData] takeLast:HANDSHAKE_CRC_LENGTH] bigEndianUInt32At:0]; } +(HandshakePacket*) handshakePacketParsedFromRtpPacket:(RtpPacket*)rtpPacket { - require(rtpPacket != nil); + ows_require(rtpPacket != nil); checkOperation([rtpPacket timeStamp] == HANDSHAKE_PACKET_TIMESTAMP_COOKIE); checkOperation([rtpPacket version] == 0); checkOperation(rtpPacket.hasExtensionHeader); @@ -61,13 +61,13 @@ } -(HandshakePacket*) withHmacAppended:(NSData*)macKey { - require(macKey != nil); + ows_require(macKey != nil); NSData* digest = [[[self rtpExtensionPayloadUsedForHmacBeforeHmacAppended] hmacWithSha256WithKey:macKey] take:HANDSHAKE_TRUNCATED_HMAC_LENGTH]; NSData* authenticatedPayload = [@[payload, digest] ows_concatDatas]; return [HandshakePacket handshakePacketWithTypeId:typeId andPayload:authenticatedPayload]; } -(HandshakePacket*) withHmacVerifiedAndRemoved:(NSData*)macKey { - require(macKey != nil); + ows_require(macKey != nil); NSData* authenticatedData = [self rtpExtensionHeaderAndPayloadExceptCrc]; diff --git a/Signal/src/network/rtp/zrtp/packets/HelloPacket.m b/Signal/src/network/rtp/zrtp/packets/HelloPacket.m index 01f16d7f9..0c2c12e78 100644 --- a/Signal/src/network/rtp/zrtp/packets/HelloPacket.m +++ b/Signal/src/network/rtp/zrtp/packets/HelloPacket.m @@ -46,16 +46,16 @@ } } - require(hasDH3k); + ows_require(hasDH3k); return agreeSpecIds; } +(HelloPacket*) helloPacketWithDefaultsAndHashChain:(HashChain*)hashChain andZid:(Zid*)zid andKeyAgreementProtocols:(NSArray*)keyAgreementProtocols { - require(hashChain != nil); - require(zid != nil); - require(keyAgreementProtocols != nil); + ows_require(hashChain != nil); + ows_require(zid != nil); + ows_require(keyAgreementProtocols != nil); return [HelloPacket helloPacketWithVersion:Environment.getCurrent.zrtpVersionId andClientId:Environment.getCurrent.zrtpClientId @@ -86,26 +86,26 @@ andSasSpecIds:(NSArray*)sasIds authenticatedWithHmacKey:(NSData*)hmacKey { - require(versionId != nil); - require(clientId != nil); - require(hashChainH3 != nil); - require(hashIds != nil); - require(cipherIds != nil); - require(authIds != nil); - require(agreeIds != nil); - require(sasIds != nil); - require((flags0SMP & ~FLAGS_0SMP_MASK) == 0); - require((flagsUnusedLow4 & ~FLAGS_UNUSED_LOW_MASK) == 0); - require((flagsUnusedHigh4 & ~FLAGS_UNUSED_HIGH_MASK) == 0); + ows_require(versionId != nil); + ows_require(clientId != nil); + ows_require(hashChainH3 != nil); + ows_require(hashIds != nil); + ows_require(cipherIds != nil); + ows_require(authIds != nil); + ows_require(agreeIds != nil); + ows_require(sasIds != nil); + ows_require((flags0SMP & ~FLAGS_0SMP_MASK) == 0); + ows_require((flagsUnusedLow4 & ~FLAGS_UNUSED_LOW_MASK) == 0); + ows_require((flagsUnusedHigh4 & ~FLAGS_UNUSED_HIGH_MASK) == 0); - require(versionId.length == VERSION_ID_LENGTH); - require(clientId.length == CLIENT_ID_LENGTH); - require(hashChainH3.length == HASH_CHAIN_ITEM_LENGTH); - require(hashIds.count <= MAX_SPEC_IDS); - require(cipherIds.count <= MAX_SPEC_IDS); - require(authIds.count <= MAX_SPEC_IDS); - require(agreeIds.count <= MAX_SPEC_IDS); - require(sasIds.count <= MAX_SPEC_IDS); + ows_require(versionId.length == VERSION_ID_LENGTH); + ows_require(clientId.length == CLIENT_ID_LENGTH); + ows_require(hashChainH3.length == HASH_CHAIN_ITEM_LENGTH); + ows_require(hashIds.count <= MAX_SPEC_IDS); + ows_require(cipherIds.count <= MAX_SPEC_IDS); + ows_require(authIds.count <= MAX_SPEC_IDS); + ows_require(agreeIds.count <= MAX_SPEC_IDS); + ows_require(sasIds.count <= MAX_SPEC_IDS); HelloPacket* p = [HelloPacket new]; p->flagsUnusedLow4 = flagsUnusedLow4; @@ -216,7 +216,7 @@ sasIds = specIds[SAS_IDS_INDEX]; } +(HelloPacket*) helloPacketParsedFromHandshakePacket:(HandshakePacket*)handshakePacket { - require(handshakePacket != nil); + ows_require(handshakePacket != nil); checkOperationDescribe([[handshakePacket typeId] isEqualToData:HANDSHAKE_TYPE_HELLO], @"Not a hello packet"); NSData* payload = [handshakePacket payload]; diff --git a/Signal/src/network/tcp/LowLatencyCandidate.m b/Signal/src/network/tcp/LowLatencyCandidate.m index dcb0e6fcb..6b5f67044 100644 --- a/Signal/src/network/tcp/LowLatencyCandidate.m +++ b/Signal/src/network/tcp/LowLatencyCandidate.m @@ -7,7 +7,7 @@ +(LowLatencyCandidate*) lowLatencyCandidateToRemoteEndPoint:(id)remoteEndPoint { - require(remoteEndPoint != nil); + ows_require(remoteEndPoint != nil); LowLatencyCandidate* r = [LowLatencyCandidate new]; r->remoteEndPoint = remoteEndPoint; diff --git a/Signal/src/network/tcp/LowLatencyConnector.m b/Signal/src/network/tcp/LowLatencyConnector.m index 0da8ead42..d35b6bb51 100644 --- a/Signal/src/network/tcp/LowLatencyConnector.m +++ b/Signal/src/network/tcp/LowLatencyConnector.m @@ -8,7 +8,7 @@ +(TOCFuture*) asyncLowLatencyConnectToEndPoint:(id)endPoint untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(endPoint != nil); + ows_require(endPoint != nil); TOCFuture* futureSpecificEndPoints = [endPoint asyncResolveToSpecificEndPointsUnlessCancelled:untilCancelledToken]; @@ -21,7 +21,7 @@ +(TOCFuture*) startConnectingToAll:(NSArray*)specificEndPoints untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(specificEndPoints != nil); + ows_require(specificEndPoints != nil); NSArray* candidates = [specificEndPoints map:^id(id endPoint) { return [LowLatencyCandidate lowLatencyCandidateToRemoteEndPoint:endPoint]; diff --git a/Signal/src/network/tcp/StreamPair.m b/Signal/src/network/tcp/StreamPair.m index c4f28a627..823402f43 100644 --- a/Signal/src/network/tcp/StreamPair.m +++ b/Signal/src/network/tcp/StreamPair.m @@ -5,8 +5,8 @@ @synthesize inputStream, outputStream; +(StreamPair*) streamPairWithInput:(NSInputStream*)input andOutput:(NSOutputStream*)output { - require(input != nil); - require(output != nil); + ows_require(input != nil); + ows_require(output != nil); StreamPair* r = [StreamPair new]; r->inputStream = input; diff --git a/Signal/src/network/tcp/tls/Certificate.h b/Signal/src/network/tcp/tls/Certificate.h index 9353464a1..6bf8942ce 100644 --- a/Signal/src/network/tcp/tls/Certificate.h +++ b/Signal/src/network/tcp/tls/Certificate.h @@ -5,14 +5,13 @@ * Certificate is responsible for loading, exposing, and managing a SecCertificateRef. * */ + @interface Certificate : NSObject -+(Certificate*) certificateFromTrust:(SecTrustRef)trust - atIndex:(CFIndex)index; ++ (Certificate *)certificateFromTrust:(SecTrustRef)trust atIndex:(CFIndex)index; -+(Certificate*) certificateFromResourcePath:(NSString*)resourcePath - ofType:(NSString*)resourceType; ++ (Certificate *)certificateFromResourcePath:(NSString *)resourcePath ofType:(NSString *)resourceType; --(void) setAsAnchorForTrust:(SecTrustRef)trust; +- (void)setAsAnchorForTrust:(SecTrustRef)trust; @end diff --git a/Signal/src/network/tcp/tls/Certificate.m b/Signal/src/network/tcp/tls/Certificate.m index c422a6a83..2721353f7 100644 --- a/Signal/src/network/tcp/tls/Certificate.m +++ b/Signal/src/network/tcp/tls/Certificate.m @@ -9,8 +9,8 @@ +(Certificate*) certificateFromTrust:(SecTrustRef)trust atIndex:(CFIndex)index { - require(trust != nil); - require(index >= 0); + ows_require(trust != nil); + ows_require(index >= 0); SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, index); checkOperation(cert != nil); @@ -23,8 +23,8 @@ +(Certificate*) certificateFromResourcePath:(NSString*)resourcePath ofType:(NSString*)resourceType { - require(resourcePath != nil); - require(resourceType != nil); + ows_require(resourcePath != nil); + ows_require(resourceType != nil); NSString *certPath = [NSBundle.mainBundle pathForResource:resourcePath ofType:resourceType]; NSData *certData = [[NSData alloc] initWithContentsOfFile:certPath]; @@ -43,7 +43,7 @@ } -(void) setAsAnchorForTrust:(SecTrustRef)trust { - require(trust != nil); + ows_require(trust != nil); CFMutableArrayRef anchorCerts = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks); checkOperation(anchorCerts != NULL); diff --git a/Signal/src/network/tcp/tls/NetworkStream.m b/Signal/src/network/tcp/tls/NetworkStream.m index 21d04cf59..1272888c2 100644 --- a/Signal/src/network/tcp/tls/NetworkStream.m +++ b/Signal/src/network/tcp/tls/NetworkStream.m @@ -9,12 +9,12 @@ @implementation NetworkStream +(NetworkStream*) networkStreamToEndPoint:(id)remoteEndPoint { - require(remoteEndPoint != nil); + ows_require(remoteEndPoint != nil); // all connections must be secure, unless testing bool isSecureEndPoint = [remoteEndPoint isKindOfClass:SecureEndPoint.class]; bool allowTestNonSecure = [Environment hasEnabledTestingOrLegacyOption:ENVIRONMENT_TESTING_OPTION_ALLOW_NETWORK_STREAM_TO_NON_SECURE_END_POINTS]; - require(allowTestNonSecure || isSecureEndPoint); + ows_require(allowTestNonSecure || isSecureEndPoint); StreamPair* streams = [remoteEndPoint createStreamPair]; @@ -57,7 +57,7 @@ } } -(void) send:(NSData*)data { - require(data != nil); + ows_require(data != nil); requireState(rawDataHandler != nil); @synchronized(self) { [writeBuffer enqueueData:data]; @@ -97,7 +97,7 @@ } } -(void) startWithHandler:(PacketHandler*)handler { - require(handler != nil); + ows_require(handler != nil); requireState(rawDataHandler == nil); @synchronized(self) { rawDataHandler = handler; @@ -114,7 +114,6 @@ } } - -(void) onNetworkFailure:(id)error { @synchronized(self) { [futureOpenedSource trySetFailure:error]; diff --git a/Signal/src/network/tcp/tls/SecureEndPoint.m b/Signal/src/network/tcp/tls/SecureEndPoint.m index 997362e2b..93cc26b84 100644 --- a/Signal/src/network/tcp/tls/SecureEndPoint.m +++ b/Signal/src/network/tcp/tls/SecureEndPoint.m @@ -7,8 +7,8 @@ +(SecureEndPoint*) secureEndPointForHost:(HostNameEndPoint*)host identifiedByCertificate:(Certificate*)certificate { - require(host != nil); - require(certificate != nil); + ows_require(host != nil); + ows_require(certificate != nil); return [self secureEndPointForHost:host identifiedByCertificate:certificate @@ -19,8 +19,8 @@ identifiedByCertificate:(Certificate*)certificate withOptionalMoreSpecificEndPoint:(id)optionalMoreSpecificEndPoint { - require(host != nil); - require(certificate != nil); + ows_require(host != nil); + ows_require(certificate != nil); SecureEndPoint* s = [SecureEndPoint new]; s->hostNameEndPoint = host; @@ -74,7 +74,7 @@ } -(TOCFuture*)asyncHandleStreamsConnected:(StreamPair *)streamPair { - require(streamPair != nil); + ows_require(streamPair != nil); @try { [self authenticateSslStream:streamPair]; diff --git a/Signal/src/network/udp/UdpSocket.m b/Signal/src/network/udp/UdpSocket.m index dde96450a..024a3b47a 100644 --- a/Signal/src/network/udp/UdpSocket.m +++ b/Signal/src/network/udp/UdpSocket.m @@ -5,7 +5,7 @@ @implementation UdpSocket +(UdpSocket*) udpSocketToFirstSenderOnLocalPort:(in_port_t)localPort { - require(localPort > 0); + ows_require(localPort > 0); UdpSocket* p = [UdpSocket new]; p->specifiedLocalPort = localPort; p->specifiedRemoteEndPoint = nil; @@ -14,9 +14,9 @@ +(UdpSocket*) udpSocketFromLocalPort:(in_port_t)localPort toRemoteEndPoint:(IpEndPoint*)remoteEndPoint { - require(remoteEndPoint != nil); - require([remoteEndPoint port] > 0); - require(localPort > 0); + ows_require(remoteEndPoint != nil); + ows_require([remoteEndPoint port] > 0); + ows_require(localPort > 0); UdpSocket* p = [UdpSocket new]; p->specifiedLocalPort = localPort; @@ -24,8 +24,8 @@ return p; } +(UdpSocket*) udpSocketTo:(IpEndPoint*)remoteEndPoint { - require(remoteEndPoint != nil); - require([remoteEndPoint port] > 0); + ows_require(remoteEndPoint != nil); + ows_require([remoteEndPoint port] > 0); UdpSocket* p = [UdpSocket new]; p->specifiedLocalPort = 0; // passing port 0 to CFSocketAddress means 'pick one for me' @@ -42,7 +42,7 @@ -(void) send:(NSData*)packet { @synchronized(self) { - require(packet != nil); + ows_require(packet != nil); requireState(socket != nil); requireState(self.isRemoteEndPointKnown); @@ -155,7 +155,7 @@ void onReceivedData(CFSocketRef socket, CFSocketCallBackType type, CFDataRef add -(void) startWithHandler:(PacketHandler*)handler untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(handler != nil); + ows_require(handler != nil); @synchronized(self) { bool isFirstTime = currentHandler == nil; diff --git a/Signal/src/phone/PhoneManager.h b/Signal/src/phone/PhoneManager.h index b9edd0b36..168f6580f 100644 --- a/Signal/src/phone/PhoneManager.h +++ b/Signal/src/phone/PhoneManager.h @@ -1,14 +1,14 @@ #import -#import "PhoneNumber.h" -#import "InitiatorSessionDescriptor.h" -#import "Environment.h" -#import "Terminable.h" -#import "Logging.h" -#import "ResponderSessionDescriptor.h" #import "CallAudioManager.h" #import "CallConnectUtil.h" #import "CallController.h" #import "Contact.h" +#import "Environment.h" +#import "InitiatorSessionDescriptor.h" +#import "Logging.h" +#import "PhoneNumber.h" +#import "ResponderSessionDescriptor.h" +#import "Terminable.h" /** * @@ -17,24 +17,27 @@ * User actions like 'make a call' should roughly translate one-to-one with the exposed methods. * */ -@interface PhoneManager : NSObject { -@private ObservableValueController* currentCallControllerObservable; -@private ObservableValueController* currentCallStateObservable; -@private int64_t lastIncomingSessionId; +@interface PhoneManager : NSObject { + @private + ObservableValueController *currentCallControllerObservable; + @private + ObservableValueController *currentCallStateObservable; + @private + int64_t lastIncomingSessionId; } -@property (readonly,nonatomic,copy) ErrorHandlerBlock errorHandler; +@property (readonly, nonatomic, copy) ErrorHandlerBlock errorHandler; --(void) initiateOutgoingCallToRemoteNumber:(PhoneNumber*)remoteNumber; --(void) initiateOutgoingCallToContact:(Contact*)contact atRemoteNumber:(PhoneNumber*)remoteNumber; --(void) incomingCallWithSession:(ResponderSessionDescriptor*)session; --(void) hangupOrDenyCall; --(void) answerCall; --(BOOL) toggleMute; --(void) backgroundTimeExpired; +- (void)initiateOutgoingCallToRemoteNumber:(PhoneNumber *)remoteNumber; +- (void)initiateOutgoingCallToContact:(Contact *)contact atRemoteNumber:(PhoneNumber *)remoteNumber; +- (void)incomingCallWithSession:(ResponderSessionDescriptor *)session; +- (void)hangupOrDenyCall; +- (void)answerCall; +- (BOOL)toggleMute; +- (void)backgroundTimeExpired; --(ObservableValue*) currentCallObservable; +- (ObservableValue *)currentCallObservable; -+(PhoneManager*) phoneManagerWithErrorHandler:(ErrorHandlerBlock)errorHandler; ++ (PhoneManager *)phoneManagerWithErrorHandler:(ErrorHandlerBlock)errorHandler; @end diff --git a/Signal/src/phone/PhoneManager.m b/Signal/src/phone/PhoneManager.m index e4eb5d4ca..120a51bd4 100644 --- a/Signal/src/phone/PhoneManager.m +++ b/Signal/src/phone/PhoneManager.m @@ -5,85 +5,87 @@ @implementation PhoneManager -+(PhoneManager*) phoneManagerWithErrorHandler:(ErrorHandlerBlock)errorHandler { - PhoneManager* m = [PhoneManager new]; - m->_errorHandler = errorHandler; ++ (PhoneManager *)phoneManagerWithErrorHandler:(ErrorHandlerBlock)errorHandler { + PhoneManager *m = [PhoneManager new]; + m->_errorHandler = errorHandler; m->currentCallControllerObservable = [ObservableValueController observableValueControllerWithInitialValue:nil]; - m->currentCallStateObservable = [ObservableValueController observableValueControllerWithInitialValue:nil]; + m->currentCallStateObservable = [ObservableValueController observableValueControllerWithInitialValue:nil]; + + [m->currentCallControllerObservable watchLatestValue:^(CallController *latestValue) { + [m->currentCallStateObservable updateValue:latestValue.callState]; + } + onThread:NSThread.currentThread + untilCancelled:nil]; - [m->currentCallControllerObservable watchLatestValue:^(CallController* latestValue) { - [m->currentCallStateObservable updateValue:latestValue.callState]; - } onThread:NSThread.currentThread untilCancelled:nil]; - return m; } --(ObservableValue*) currentCallObservable { +- (ObservableValue *)currentCallObservable { return currentCallStateObservable; } --(CallController*) cancelExistingCallAndInitNewCallWork:(bool)initiatedLocally - remote:(PhoneNumber*)remoteNumber - optionalContact:(Contact*)contact { - CallController* old = [self curCallController]; - CallController* new = [CallController callControllerForCallInitiatedLocally:initiatedLocally - withRemoteNumber:remoteNumber - andOptionallySpecifiedContact:contact]; - [old terminateWithReason:CallTerminationType_ReplacedByNext - withFailureInfo:nil - andRelatedInfo:nil]; +- (CallController *)cancelExistingCallAndInitNewCallWork:(bool)initiatedLocally + remote:(PhoneNumber *)remoteNumber + optionalContact:(Contact *)contact { + CallController *old = [self curCallController]; + CallController *new = [ + CallController callControllerForCallInitiatedLocally : initiatedLocally withRemoteNumber : remoteNumber + andOptionallySpecifiedContact : contact + ]; + [old terminateWithReason:CallTerminationType_ReplacedByNext withFailureInfo:nil andRelatedInfo:nil]; [currentCallControllerObservable updateValue:new]; return new; } --(void) initiateOutgoingCallToContact:(Contact*)contact atRemoteNumber:(PhoneNumber*)remoteNumber { - require(remoteNumber != nil); +- (void)initiateOutgoingCallToContact:(Contact *)contact atRemoteNumber:(PhoneNumber *)remoteNumber { + ows_require(remoteNumber != nil); [self initiateOutgoingCallToRemoteNumber:remoteNumber withOptionallyKnownContact:contact]; } --(void) initiateOutgoingCallToRemoteNumber:(PhoneNumber*)remoteNumber { - require(remoteNumber != nil); +- (void)initiateOutgoingCallToRemoteNumber:(PhoneNumber *)remoteNumber { + ows_require(remoteNumber != nil); [self initiateOutgoingCallToRemoteNumber:remoteNumber withOptionallyKnownContact:nil]; } --(void) initiateOutgoingCallToRemoteNumber:(PhoneNumber*)remoteNumber withOptionallyKnownContact:(Contact*)contact { - require(remoteNumber != nil); - +- (void)initiateOutgoingCallToRemoteNumber:(PhoneNumber *)remoteNumber withOptionallyKnownContact:(Contact *)contact { + ows_require(remoteNumber != nil); + [[AppAudioManager sharedInstance] requestRequiredPermissionsIfNeededWithCompletion:^(BOOL granted) { - if (granted) { - [self callToRemoteNumber:remoteNumber withOptionallyKnownContact:contact]; - } - } incoming:NO]; + if (granted) { + [self callToRemoteNumber:remoteNumber withOptionallyKnownContact:contact]; + } + } + incoming:NO]; } -- (void)callToRemoteNumber:(PhoneNumber*)remoteNumber withOptionallyKnownContact:(Contact*)contact { - CallController* callController = [self cancelExistingCallAndInitNewCallWork:true - remote:remoteNumber - optionalContact:contact]; +- (void)callToRemoteNumber:(PhoneNumber *)remoteNumber withOptionallyKnownContact:(Contact *)contact { + CallController *callController = + [self cancelExistingCallAndInitNewCallWork:true remote:remoteNumber optionalContact:contact]; [callController acceptCall]; // initiator implicitly accepts call - TOCCancelToken* lifetime = [callController untilCancelledToken]; - - TOCFuture* futureConnected = [CallConnectUtil asyncInitiateCallToRemoteNumber:remoteNumber - andCallController:callController]; - - TOCFuture* futureCalling = [futureConnected thenTry:^id(CallConnectResult* connectResult) { - [callController advanceCallProgressToConversingWithShortAuthenticationString:connectResult.shortAuthenticationString]; - CallAudioManager *cam = [CallAudioManager callAudioManagerStartedWithAudioSocket:connectResult.audioSocket - andErrorHandler:callController.errorHandler - untilCancelled:lifetime]; - [callController setCallAudioManager:cam]; - return nil; + TOCCancelToken *lifetime = [callController untilCancelledToken]; + + TOCFuture *futureConnected = + [CallConnectUtil asyncInitiateCallToRemoteNumber:remoteNumber andCallController:callController]; + + TOCFuture *futureCalling = [futureConnected thenTry:^id(CallConnectResult *connectResult) { + [callController + advanceCallProgressToConversingWithShortAuthenticationString:connectResult.shortAuthenticationString]; + CallAudioManager *cam = [CallAudioManager callAudioManagerStartedWithAudioSocket:connectResult.audioSocket + andErrorHandler:callController.errorHandler + untilCancelled:lifetime]; + [callController setCallAudioManager:cam]; + return nil; }]; - + [futureCalling catchDo:^(id error) { - callController.errorHandler(error, nil, true); + callController.errorHandler(error, nil, true); }]; } --(void) incomingCallWithSession:(ResponderSessionDescriptor*)session { - require(session != nil); +- (void)incomingCallWithSession:(ResponderSessionDescriptor *)session { + ows_require(session != nil); - int64_t prevSession = lastIncomingSessionId; + int64_t prevSession = lastIncomingSessionId; lastIncomingSessionId = session.sessionId; if ([currentCallControllerObservable.currentValue callState].futureTermination.isIncomplete) { @@ -93,45 +95,48 @@ } [Environment.getCurrent.recentCallManager addMissedCallDueToBusy:session]; - + [[CallConnectUtil asyncSignalTooBusyToAnswerCallWithSessionDescriptor:session] catchDo:^(id error) { - Environment.errorNoter(error, @"Failed to signal busy.", false); + Environment.errorNoter(error, @"Failed to signal busy.", false); }]; return; } - + [[AppAudioManager sharedInstance] requestRequiredPermissionsIfNeededWithCompletion:^(BOOL granted) { - if (granted) { - Contact* callingContact = [Environment.getCurrent.contactsManager latestContactForPhoneNumber:session.initiatorNumber]; - CallController* callController = [self cancelExistingCallAndInitNewCallWork:false - remote:session.initiatorNumber - optionalContact:callingContact]; - - TOCCancelToken* lifetime = [callController untilCancelledToken]; - - TOCFuture* futureConnected = [CallConnectUtil asyncRespondToCallWithSessionDescriptor:session - andCallController:callController]; - - TOCFuture* futureStarted = [futureConnected thenTry:^id(CallConnectResult* connectResult) { - [callController advanceCallProgressToConversingWithShortAuthenticationString:connectResult.shortAuthenticationString]; - CallAudioManager* cam = [CallAudioManager callAudioManagerStartedWithAudioSocket:connectResult.audioSocket - andErrorHandler:callController.errorHandler - untilCancelled:lifetime]; - [callController setCallAudioManager:cam]; - return nil; - }]; - - [futureStarted catchDo:^(id error) { - callController.errorHandler(error, nil, true); - }]; - } - } incoming:YES]; + if (granted) { + Contact *callingContact = + [Environment.getCurrent.contactsManager latestContactForPhoneNumber:session.initiatorNumber]; + CallController *callController = [self cancelExistingCallAndInitNewCallWork:false + remote:session.initiatorNumber + optionalContact:callingContact]; + + TOCCancelToken *lifetime = [callController untilCancelledToken]; + + TOCFuture *futureConnected = + [CallConnectUtil asyncRespondToCallWithSessionDescriptor:session andCallController:callController]; + + TOCFuture *futureStarted = [futureConnected thenTry:^id(CallConnectResult *connectResult) { + [callController + advanceCallProgressToConversingWithShortAuthenticationString:connectResult.shortAuthenticationString]; + CallAudioManager *cam = [CallAudioManager callAudioManagerStartedWithAudioSocket:connectResult.audioSocket + andErrorHandler:callController.errorHandler + untilCancelled:lifetime]; + [callController setCallAudioManager:cam]; + return nil; + }]; + + [futureStarted catchDo:^(id error) { + callController.errorHandler(error, nil, true); + }]; + } + } + incoming:YES]; } --(CallController*) curCallController { +- (CallController *)curCallController { return currentCallControllerObservable.currentValue; } --(void)answerCall { +- (void)answerCall { [[self curCallController] acceptCall]; } @@ -143,11 +148,11 @@ [[self curCallController] backgroundTimeExpired]; } --(BOOL) toggleMute{ - return [self.curCallController toggleMute]; +- (BOOL)toggleMute { + return [self.curCallController toggleMute]; } --(void)terminate{ +- (void)terminate { [[self curCallController] terminateWithReason:CallTerminationType_UncategorizedFailure withFailureInfo:@"PhoneManager terminated" andRelatedInfo:nil]; diff --git a/Signal/src/phone/PhoneNumber.h b/Signal/src/phone/PhoneNumber.h deleted file mode 100644 index a5023bf2d..000000000 --- a/Signal/src/phone/PhoneNumber.h +++ /dev/null @@ -1,39 +0,0 @@ -#import -#import "NBPhoneNumberUtil.h" - -#define COUNTRY_CODE_PREFIX @"+" - -/** - * - * PhoneNumber is used to deal with the nitty details of parsing/canonicalizing phone numbers. - * Everything that expects a valid phone number should take a PhoneNumber, not a string, to avoid stringly typing. - * - */ -@interface PhoneNumber : NSObject { -@private NBPhoneNumber* phoneNumber; -@private NSString* e164; -} - -+(PhoneNumber*) phoneNumberFromText:(NSString*)text andRegion:(NSString*)regionCode; -+(PhoneNumber*) phoneNumberFromUserSpecifiedText:(NSString*)text; -+(PhoneNumber*) phoneNumberFromE164:(NSString*)text; - -+(PhoneNumber*) tryParsePhoneNumberFromText:(NSString*)text fromRegion:(NSString*)regionCode; -+(PhoneNumber*) tryParsePhoneNumberFromUserSpecifiedText:(NSString*)text; -+(PhoneNumber*) tryParsePhoneNumberFromE164:(NSString*)text; - - -+(NSString*) bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:(NSString*)input; -+(NSString*) bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:(NSString*)input - withSpecifiedCountryCodeString:(NSString*) countryCodeString; - -+(NSString*) regionCodeFromCountryCodeString:(NSString*) countryCodeString; - --(NSURL*) toSystemDialerURL; --(NSString *)toE164; --(NSString *)localizedDescriptionForUser; --(NSNumber*)getCountryCode; --(BOOL)isValid; --(BOOL)resolvesInternationallyTo:(PhoneNumber*) otherPhoneNumber; - -@end diff --git a/Signal/src/phone/PhoneNumber.m b/Signal/src/phone/PhoneNumber.m deleted file mode 100644 index 3ea02d4ae..000000000 --- a/Signal/src/phone/PhoneNumber.m +++ /dev/null @@ -1,174 +0,0 @@ -#import "PhoneNumber.h" -#import "Constraints.h" -#import "Environment.h" -#import "PhoneNumberUtil.h" -#import "NBAsYouTypeFormatter.h" -#import "NBPhoneNumber.h" - -static NSString *const RPDefaultsKeyPhoneNumberString = @"RPDefaultsKeyPhoneNumberString"; -static NSString *const RPDefaultsKeyPhoneNumberCanonical = @"RPDefaultsKeyPhoneNumberCanonical"; - -@implementation PhoneNumber - -+(PhoneNumber*) phoneNumberFromText:(NSString*)text andRegion:(NSString*)regionCode { - require(text != nil); - require(regionCode != nil); - - NBPhoneNumberUtil *phoneUtil = [PhoneNumberUtil sharedInstance].nbPhoneNumberUtil; - - NSError* parseError = nil; - NBPhoneNumber *number = [phoneUtil parse:text - defaultRegion:regionCode - error:&parseError]; - checkOperationDescribe(parseError == nil, [parseError description]); - //checkOperation([phoneUtil isValidNumber:number]); - - NSError* toE164Error; - NSString* e164 = [phoneUtil format:number numberFormat:NBEPhoneNumberFormatE164 error:&toE164Error]; - checkOperationDescribe(toE164Error == nil, [e164 description]); - - PhoneNumber* phoneNumber = [PhoneNumber new]; - phoneNumber->phoneNumber = number; - phoneNumber->e164 = e164; - return phoneNumber; -} - -+(PhoneNumber*) phoneNumberFromUserSpecifiedText:(NSString*)text { - require(text != nil); - - return [PhoneNumber phoneNumberFromText:text - andRegion:Environment.currentRegionCodeForPhoneNumbers]; -} - -+(PhoneNumber*) phoneNumberFromE164:(NSString*)text { - require(text != nil); - checkOperation([text hasPrefix:COUNTRY_CODE_PREFIX]); - PhoneNumber *number = [PhoneNumber phoneNumberFromText:text - andRegion:@"ZZ"]; - - checkOperation(number != nil); - return number; -} - -+(NSString*) bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:(NSString*)input { - return [PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:input - withSpecifiedRegionCode:Environment.currentRegionCodeForPhoneNumbers]; -} - -+(NSString*) bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:(NSString*)input withSpecifiedCountryCodeString:(NSString *)countryCodeString{ - return [PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:input - withSpecifiedRegionCode:[PhoneNumber regionCodeFromCountryCodeString:countryCodeString]]; -} - -+(NSString*) bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:(NSString*)input withSpecifiedRegionCode:(NSString *) regionCode{ - NBAsYouTypeFormatter* formatter = [[NBAsYouTypeFormatter alloc] initWithRegionCode:regionCode]; - - NSString* result = input; - for (NSUInteger i = 0; i < input.length; i++) { - result = [formatter inputDigit:[input substringWithRange:NSMakeRange(i, 1)]]; - } - return result; -} - - -+(NSString*) regionCodeFromCountryCodeString:(NSString*) countryCodeString { - NBPhoneNumberUtil* phoneUtil = [PhoneNumberUtil sharedInstance].nbPhoneNumberUtil; - NSString* regionCode = [phoneUtil getRegionCodeForCountryCode:@([[countryCodeString substringFromIndex:1] integerValue])]; - return regionCode; -} - - -+(PhoneNumber*) tryParsePhoneNumberFromText:(NSString*)text fromRegion:(NSString*)regionCode { - require(text != nil); - require(regionCode != nil); - - @try { - return [self phoneNumberFromText:text andRegion:regionCode]; - } @catch (OperationFailed* ex) { - DDLogError(@"Error parsing phone number from region code"); - return nil; - } -} - -+(PhoneNumber*) tryParsePhoneNumberFromUserSpecifiedText:(NSString*)text { - require(text != nil); - - char s[text.length+1]; - int xx = 0; - for (NSUInteger i = 0; i < text.length; i++) { - unichar x = [text characterAtIndex:i]; - if (x == '+' || (x >= '0' && x <= '9')) { - s[xx++] = (char)x; - } - } - - s[xx]=0; - text = [NSString stringWithUTF8String:(void*)s]; - - @try { - return [self phoneNumberFromUserSpecifiedText:text]; - } @catch (OperationFailed* ex) { - return nil; - } -} -+(PhoneNumber*) tryParsePhoneNumberFromE164:(NSString*)text { - require(text != nil); - - @try { - return [self phoneNumberFromE164:text]; - } @catch (OperationFailed* ex) { - return nil; - } -} - --(NSURL*) toSystemDialerURL { - NSString* link = [NSString stringWithFormat:@"telprompt://%@", e164]; - return [NSURL URLWithString:link]; -} - --(NSString *)toE164 { - return e164; -} - -- (NSNumber*)getCountryCode { - return phoneNumber.countryCode; -} - --(BOOL)isValid { - return [[PhoneNumberUtil sharedInstance].nbPhoneNumberUtil isValidNumber:phoneNumber]; -} - --(NSString *)localizedDescriptionForUser { - NBPhoneNumberUtil *phoneUtil = [PhoneNumberUtil sharedInstance].nbPhoneNumberUtil; - - NSError* formatError = nil; - NSString* pretty = [phoneUtil format:phoneNumber - numberFormat:NBEPhoneNumberFormatINTERNATIONAL - error:&formatError]; - - if (formatError != nil) return e164; - return pretty; -} - --(BOOL)resolvesInternationallyTo:(PhoneNumber*) otherPhoneNumber { - return [self.toE164 isEqualToString:otherPhoneNumber.toE164]; -} - --(NSString*) description { - return e164; -} - -- (void)encodeWithCoder:(NSCoder *)encoder { - [encoder encodeObject:phoneNumber forKey:RPDefaultsKeyPhoneNumberString]; - [encoder encodeObject:e164 forKey:RPDefaultsKeyPhoneNumberCanonical]; -} - -- (id)initWithCoder:(NSCoder *)decoder { - if((self = [super init])) { - phoneNumber = [decoder decodeObjectForKey:RPDefaultsKeyPhoneNumberString]; - e164 = [decoder decodeObjectForKey:RPDefaultsKeyPhoneNumberCanonical]; - } - return self; -} - -@end diff --git a/Signal/src/phone/RPAccountManager.h b/Signal/src/phone/RPAccountManager.h new file mode 100644 index 000000000..ee944beef --- /dev/null +++ b/Signal/src/phone/RPAccountManager.h @@ -0,0 +1,19 @@ +// +// RPAccountManager.h +// Signal +// +// Created by Frederic Jacobs on 19/12/15. +// Copyright © 2015 Open Whisper Systems. All rights reserved. +// + +#import + +@interface RPAccountManager : NSObject + ++ (void)registrationWithTsToken:(NSString *)tsToken + pushToken:(NSString *)pushToken + voipToken:(NSString *)voipPushToken + success:(void (^)())success + failure:(void (^)(NSError *))failure; + +@end diff --git a/Signal/src/phone/RPAccountManager.m b/Signal/src/phone/RPAccountManager.m new file mode 100644 index 000000000..82d4bb58d --- /dev/null +++ b/Signal/src/phone/RPAccountManager.m @@ -0,0 +1,104 @@ +// +// RPAccountManager.m +// Signal +// +// Created by Frederic Jacobs on 19/12/15. +// Copyright © 2015 Open Whisper Systems. All rights reserved. +// + +#import +#import +#import "ArrayUtil.h" +#import "DataUtil.h" +#import "RPAPICall.h" +#import "RPAccountManager.h" +#import "RPServerRequestsManager.h" +#import "SignalKeyingStorage.h" + +@interface RedPhoneAccountAttributes : MTLModel + +@property (nonatomic, copy, readonly) NSString *signalingKey; +@property (nonatomic, copy, readonly) NSString *apnRegistrationId; +@property (nonatomic, copy, readonly) NSString *voipRegistrationId; + + +- (instancetype)initWithSignalingCipherKey:(NSData *)signalingCipherKey + signalingMacKey:(NSData *)signalingMacKey + signalingExtraKey:(NSData *)signalingExtraKey + apnRegistrationId:(NSString *)apnRegistrationId + voipRegistrationId:(NSString *)voipRegistrationId; + +@end + +@implementation RedPhoneAccountAttributes + +- (instancetype)initWithSignalingCipherKey:(NSData *)signalingCipherKey + signalingMacKey:(NSData *)signalingMacKey + signalingExtraKey:(NSData *)signalingExtraKey + apnRegistrationId:(NSString *)apnRegistrationId + voipRegistrationId:(NSString *)voipRegistrationId { + self = [super init]; + + if (self) { + _signalingKey = @[ signalingCipherKey, signalingMacKey, signalingExtraKey ].ows_concatDatas.encodedAsBase64; + _apnRegistrationId = apnRegistrationId; + _voipRegistrationId = voipRegistrationId; + } + + return self; +} + +- (NSDictionary *)dictionaryValue { + NSMutableDictionary *dictionaryValue = [[super dictionaryValue] mutableCopy]; + if (!_voipRegistrationId) { + [dictionaryValue removeObjectForKey:@"voipRegistrationId"]; + } + + return dictionaryValue; +} + +@end + +@implementation RPAccountManager + ++ (void)generateKeyingMaterial { + [SignalKeyingStorage generateServerAuthPassword]; + [SignalKeyingStorage generateSignaling]; +} + ++ (NSDictionary *)attributesWithPushToken:(NSString *)pushToken voipToken:(NSString *)voipPushToken { + NSData *signalingCipherKey = SignalKeyingStorage.signalingCipherKey; + NSData *signalingMacKey = SignalKeyingStorage.signalingMacKey; + NSData *signalingExtraKeyData = SignalKeyingStorage.signalingExtraKey; + + + return [[RedPhoneAccountAttributes alloc] initWithSignalingCipherKey:signalingCipherKey + signalingMacKey:signalingMacKey + signalingExtraKey:signalingExtraKeyData + apnRegistrationId:pushToken + voipRegistrationId:voipPushToken] + .dictionaryValue; +} + ++ (void)registrationWithTsToken:(NSString *)tsToken + pushToken:(NSString *)pushToken + voipToken:(NSString *)voipPushToken + success:(void (^)())success + failure:(void (^)(NSError *))failure { + [self generateKeyingMaterial]; + + [[RPServerRequestsManager sharedManager] + performRequest:[RPAPICall verifyWithTSToken:tsToken + attributesParameters:[self attributesWithPushToken:pushToken voipToken:voipPushToken]] + success:^(NSURLSessionDataTask *task, id responseObject) { + success(); + } + failure:^(NSURLSessionDataTask *task, NSError *error) { + failure(error); + }]; +} + ++ (void)unregister { +} + +@end diff --git a/Signal/src/phone/callstate/CallController.h b/Signal/src/phone/callstate/CallController.h index f61e0a6b8..04d0a544a 100644 --- a/Signal/src/phone/callstate/CallController.h +++ b/Signal/src/phone/callstate/CallController.h @@ -1,7 +1,7 @@ #import #import "CallAudioManager.h" -#import "CallState.h" #import "CallProgress.h" +#import "CallState.h" #import "CallTermination.h" #import "PacketHandler.h" @@ -17,38 +17,47 @@ * */ @interface CallController : NSObject { -@private ObservableValueController* progress; -@private TOCFutureSource* termination; -@private TOCFutureSource* shortAuthenticationString; -@private TOCCancelTokenSource* canceller; -@private TOCFutureSource* interactiveCallAcceptedOrDenied; -@private bool initiatedLocally; -@private PhoneNumber* remoteNumber; -@private CallState* exposedCallState; -@private Contact* potentiallySpecifiedContact; -@private CallAudioManager *callAudioManager; + @private + ObservableValueController *progress; + @private + TOCFutureSource *termination; + @private + TOCFutureSource *shortAuthenticationString; + @private + TOCCancelTokenSource *canceller; + @private + TOCFutureSource *interactiveCallAcceptedOrDenied; + @private + bool initiatedLocally; + @private + PhoneNumber *remoteNumber; + @private + CallState *exposedCallState; + @private + Contact *potentiallySpecifiedContact; + @private + CallAudioManager *callAudioManager; } -+(CallController*) callControllerForCallInitiatedLocally:(bool)initiatedLocally - withRemoteNumber:(PhoneNumber*)remoteNumber - andOptionallySpecifiedContact:(Contact*)contact; ++ (CallController *)callControllerForCallInitiatedLocally:(bool)initiatedLocally + withRemoteNumber:(PhoneNumber *)remoteNumber + andOptionallySpecifiedContact:(Contact *)contact; --(void)setCallAudioManager:(CallAudioManager*) callAudioManager; --(void)advanceCallProgressTo:(enum CallProgressType)type; --(void)hangupOrDenyCall; --(void)acceptCall; +- (void)setCallAudioManager:(CallAudioManager *)callAudioManager; +- (void)advanceCallProgressTo:(enum CallProgressType)type; +- (void)hangupOrDenyCall; +- (void)acceptCall; - (void)backgroundTimeExpired; --(void)advanceCallProgressToConversingWithShortAuthenticationString:(NSString*)sas; --(void)terminateWithReason:(enum CallTerminationType)reason - withFailureInfo:(id)failureInfo - andRelatedInfo:(id)relatedInfo; --(void)terminateWithRejectionOrRemoteHangupAndFailureInfo:(id)failureInfo andRelatedInfo:(id)relatedInfo; --(BOOL)toggleMute; --(bool) isInitiator; --(TOCFuture*)interactiveCallAccepted; --(ErrorHandlerBlock)errorHandler; --(TOCCancelToken*)untilCancelledToken; --(CallState*)callState; +- (void)advanceCallProgressToConversingWithShortAuthenticationString:(NSString *)sas; +- (void)terminateWithReason:(enum CallTerminationType)reason + withFailureInfo:(id)failureInfo + andRelatedInfo:(id)relatedInfo; +- (void)terminateWithRejectionOrRemoteHangupAndFailureInfo:(id)failureInfo andRelatedInfo:(id)relatedInfo; +- (BOOL)toggleMute; +- (bool)isInitiator; +- (TOCFuture *)interactiveCallAccepted; +- (ErrorHandlerBlock)errorHandler; +- (TOCCancelToken *)untilCancelledToken; +- (CallState *)callState; @end - diff --git a/Signal/src/phone/callstate/CallController.m b/Signal/src/phone/callstate/CallController.m index 932b18066..698e1a7dd 100644 --- a/Signal/src/phone/callstate/CallController.m +++ b/Signal/src/phone/callstate/CallController.m @@ -4,136 +4,128 @@ UIBackgroundTaskIdentifier backgroundtask; } -+(CallController*) callControllerForCallInitiatedLocally:(bool)initiatedLocally - withRemoteNumber:(PhoneNumber*)remoteNumber - andOptionallySpecifiedContact:(Contact*)contact { - require(remoteNumber != nil); ++ (CallController *)callControllerForCallInitiatedLocally:(bool)initiatedLocally + withRemoteNumber:(PhoneNumber *)remoteNumber + andOptionallySpecifiedContact:(Contact *)contact { + ows_require(remoteNumber != nil); - CallController* instance = [CallController new]; - CallProgress* initialProgress = [CallProgress callProgressWithType:CallProgressType_Connecting]; - instance->progress = [ObservableValueController observableValueControllerWithInitialValue:initialProgress]; + CallController *instance = [CallController new]; + CallProgress *initialProgress = [CallProgress callProgressWithType:CallProgressType_Connecting]; + instance->progress = [ObservableValueController observableValueControllerWithInitialValue:initialProgress]; instance->termination = [TOCFutureSource new]; - instance->shortAuthenticationString = [TOCFutureSource new]; - instance->canceller = [TOCCancelTokenSource new]; + instance->shortAuthenticationString = [TOCFutureSource new]; + instance->canceller = [TOCCancelTokenSource new]; instance->interactiveCallAcceptedOrDenied = [TOCFutureSource new]; - instance->initiatedLocally = initiatedLocally; - instance->remoteNumber = remoteNumber; - instance->potentiallySpecifiedContact = contact; - instance->exposedCallState = [CallState callStateWithObservableProgress:instance->progress - andFutureTermination:instance->termination.future - andFutureSas:instance->shortAuthenticationString.future - andRemoteNumber:instance->remoteNumber - andInitiatedLocally:instance->initiatedLocally - andPotentiallySpecifiedContact:instance->potentiallySpecifiedContact - andFutureAccepted:instance->interactiveCallAcceptedOrDenied.future]; - + instance->initiatedLocally = initiatedLocally; + instance->remoteNumber = remoteNumber; + instance->potentiallySpecifiedContact = contact; + instance->exposedCallState = + [CallState callStateWithObservableProgress:instance->progress + andFutureTermination:instance->termination.future + andFutureSas:instance->shortAuthenticationString.future + andRemoteNumber:instance->remoteNumber + andInitiatedLocally:instance->initiatedLocally + andPotentiallySpecifiedContact:instance->potentiallySpecifiedContact + andFutureAccepted:instance->interactiveCallAcceptedOrDenied.future]; + return instance; } --(void) setCallAudioManager:(CallAudioManager*) _callAudioManager { - callAudioManager = _callAudioManager; +- (void)setCallAudioManager:(CallAudioManager *)_callAudioManager { + callAudioManager = _callAudioManager; } --(bool) isInitiator { +- (bool)isInitiator { return initiatedLocally; } --(ErrorHandlerBlock) errorHandler { +- (ErrorHandlerBlock)errorHandler { return ^(id error, id relatedInfo, bool causedTermination) { - if (causedTermination) { - if ([error isKindOfClass:CallTermination.class]) { - CallTermination* t = error; - [self terminateWithReason:t.type - withFailureInfo:t.failure - andRelatedInfo:t.messageInfo]; - } else { - [self terminateWithReason:CallTerminationType_UncategorizedFailure - withFailureInfo:error - andRelatedInfo:relatedInfo]; - } - } - - Environment.errorNoter(error, relatedInfo, causedTermination); + if (causedTermination) { + if ([error isKindOfClass:CallTermination.class]) { + CallTermination *t = error; + [self terminateWithReason:t.type withFailureInfo:t.failure andRelatedInfo:t.messageInfo]; + } else { + [self terminateWithReason:CallTerminationType_UncategorizedFailure + withFailureInfo:error + andRelatedInfo:relatedInfo]; + } + } + + Environment.errorNoter(error, relatedInfo, causedTermination); }; } --(TOCCancelToken*) untilCancelledToken { +- (TOCCancelToken *)untilCancelledToken { return canceller.token; } --(TOCFuture*)interactiveCallAccepted { - return [interactiveCallAcceptedOrDenied.future thenTry:^id(NSNumber* accepted) { - if ([accepted boolValue]) return accepted; - - return [TOCFuture futureWithFailure:[CallTermination callTerminationOfType:CallTerminationType_RejectedLocal - withFailure:accepted - andMessageInfo:nil]]; +- (TOCFuture *)interactiveCallAccepted { + return [interactiveCallAcceptedOrDenied.future thenTry:^id(NSNumber *accepted) { + if ([accepted boolValue]) + return accepted; + + return [TOCFuture futureWithFailure:[CallTermination callTerminationOfType:CallTerminationType_RejectedLocal + withFailure:accepted + andMessageInfo:nil]]; }]; } --(TOCFuture*)interactiveCallAcceptedOrDenied { +- (TOCFuture *)interactiveCallAcceptedOrDenied { return interactiveCallAcceptedOrDenied.future; } --(CallState*) callState { +- (CallState *)callState { return exposedCallState; } --(void)unrestrictedAdvanceCallProgressTo:(enum CallProgressType)type { - [progress adjustValue:^id(CallProgress* oldValue) { - if (type < [oldValue type]) return oldValue; - return [CallProgress callProgressWithType:type]; +- (void)unrestrictedAdvanceCallProgressTo:(enum CallProgressType)type { + [progress adjustValue:^id(CallProgress *oldValue) { + if (type < [oldValue type]) + return oldValue; + return [CallProgress callProgressWithType:type]; }]; } --(void)advanceCallProgressTo:(enum CallProgressType)type { - require(type < CallProgressType_Talking); - +- (void)advanceCallProgressTo:(enum CallProgressType)type { + ows_require(type < CallProgressType_Talking); + [self unrestrictedAdvanceCallProgressTo:type]; } - (void)backgroundTimeExpired { - [self terminateWithReason:CallTerminationType_BackgroundTimeExpired - withFailureInfo:nil - andRelatedInfo:nil]; + [self terminateWithReason:CallTerminationType_BackgroundTimeExpired withFailureInfo:nil andRelatedInfo:nil]; } --(void)hangupOrDenyCall { +- (void)hangupOrDenyCall { bool didDeny = [interactiveCallAcceptedOrDenied trySetResult:@NO]; - - enum CallTerminationType terminationType = didDeny - ? CallTerminationType_RejectedLocal - : CallTerminationType_HangupLocal; - [self terminateWithReason:terminationType - withFailureInfo:nil - andRelatedInfo:nil]; + + enum CallTerminationType terminationType = + didDeny ? CallTerminationType_RejectedLocal : CallTerminationType_HangupLocal; + [self terminateWithReason:terminationType withFailureInfo:nil andRelatedInfo:nil]; } --(void)acceptCall { +- (void)acceptCall { [interactiveCallAcceptedOrDenied trySetResult:@YES]; } --(void)advanceCallProgressToConversingWithShortAuthenticationString:(NSString*)sas { - require(sas != nil); +- (void)advanceCallProgressToConversingWithShortAuthenticationString:(NSString *)sas { + ows_require(sas != nil); [shortAuthenticationString trySetResult:sas]; [self unrestrictedAdvanceCallProgressTo:CallProgressType_Talking]; } --(void)terminateWithRejectionOrRemoteHangupAndFailureInfo:(id)failureInfo andRelatedInfo:(id)relatedInfo { - enum CallProgressType progressType = ((CallProgress*)progress.currentValue).type; - bool hasAcceptedAlready = progressType > CallProgressType_Ringing; - enum CallTerminationType terminationType = hasAcceptedAlready - ? CallTerminationType_HangupRemote - : CallTerminationType_RejectedRemote; - - [self terminateWithReason:terminationType - withFailureInfo:failureInfo - andRelatedInfo:relatedInfo]; +- (void)terminateWithRejectionOrRemoteHangupAndFailureInfo:(id)failureInfo andRelatedInfo:(id)relatedInfo { + enum CallProgressType progressType = ((CallProgress *)progress.currentValue).type; + bool hasAcceptedAlready = progressType > CallProgressType_Ringing; + enum CallTerminationType terminationType = + hasAcceptedAlready ? CallTerminationType_HangupRemote : CallTerminationType_RejectedRemote; + + [self terminateWithReason:terminationType withFailureInfo:failureInfo andRelatedInfo:relatedInfo]; } --(void)terminateWithReason:(enum CallTerminationType)reason - withFailureInfo:(id)failureInfo - andRelatedInfo:(id)relatedInfo { - - CallTermination* t = [CallTermination callTerminationOfType:reason - withFailure:failureInfo - andMessageInfo:relatedInfo]; - - if (![termination trySetResult:t]) return; +- (void)terminateWithReason:(enum CallTerminationType)reason + withFailureInfo:(id)failureInfo + andRelatedInfo:(id)relatedInfo { + CallTermination *t = + [CallTermination callTerminationOfType:reason withFailure:failureInfo andMessageInfo:relatedInfo]; + + if (![termination trySetResult:t]) + return; [self unrestrictedAdvanceCallProgressTo:CallProgressType_Terminated]; [interactiveCallAcceptedOrDenied trySetFailure:t]; [canceller cancel]; @@ -141,19 +133,20 @@ [progress sealValue]; } --(BOOL) toggleMute { - return [callAudioManager toggleMute]; +- (BOOL)toggleMute { + return [callAudioManager toggleMute]; } --(void) enableBackground { - [progress watchLatestValueOnArbitraryThread:^(CallProgress* latestProgress) { - if( CallProgressType_Connecting == latestProgress.type) { - backgroundtask = [UIApplication.sharedApplication beginBackgroundTaskWithExpirationHandler:^{ - //todo: handle premature expiration - }]; - }else if(CallProgressType_Terminated == latestProgress.type){ - [UIApplication.sharedApplication endBackgroundTask:backgroundtask]; - } - } untilCancelled:canceller.token]; +- (void)enableBackground { + [progress watchLatestValueOnArbitraryThread:^(CallProgress *latestProgress) { + if (CallProgressType_Connecting == latestProgress.type) { + backgroundtask = [UIApplication.sharedApplication beginBackgroundTaskWithExpirationHandler:^{ + // todo: handle premature expiration + }]; + } else if (CallProgressType_Terminated == latestProgress.type) { + [UIApplication.sharedApplication endBackgroundTask:backgroundtask]; + } + } + untilCancelled:canceller.token]; } @end diff --git a/Signal/src/phone/callstate/CallFailedServerMessage.h b/Signal/src/phone/callstate/CallFailedServerMessage.h index 4946ee1a9..6b333b439 100644 --- a/Signal/src/phone/callstate/CallFailedServerMessage.h +++ b/Signal/src/phone/callstate/CallFailedServerMessage.h @@ -2,8 +2,8 @@ @interface CallFailedServerMessage : NSObject -@property (readonly, nonatomic) NSString* text; +@property (readonly, nonatomic) NSString *text; -+(CallFailedServerMessage*) callFailedServerMessageWithText:(NSString*)text; ++ (CallFailedServerMessage *)callFailedServerMessageWithText:(NSString *)text; @end diff --git a/Signal/src/phone/callstate/CallFailedServerMessage.m b/Signal/src/phone/callstate/CallFailedServerMessage.m index e95fc058f..7c9bd55a8 100644 --- a/Signal/src/phone/callstate/CallFailedServerMessage.m +++ b/Signal/src/phone/callstate/CallFailedServerMessage.m @@ -5,11 +5,11 @@ @synthesize text; -+(CallFailedServerMessage*) callFailedServerMessageWithText:(NSString*)text { - require(text != nil); - - CallFailedServerMessage* instance = [CallFailedServerMessage new]; - instance->text = text; ++ (CallFailedServerMessage *)callFailedServerMessageWithText:(NSString *)text { + ows_require(text != nil); + + CallFailedServerMessage *instance = [CallFailedServerMessage new]; + instance->text = text; return instance; } diff --git a/Signal/src/phone/callstate/CallProgress.h b/Signal/src/phone/callstate/CallProgress.h index 2f1a7e46b..79a00f82f 100644 --- a/Signal/src/phone/callstate/CallProgress.h +++ b/Signal/src/phone/callstate/CallProgress.h @@ -19,11 +19,12 @@ enum CallProgressType { /// Securing covers: /// - The initiator has received a zrtp 'Hello' from the responder - /// - The initiator has not yet determined the handshake is over (by receiving a zrtp 'ConfAck' or authenticated audio data) + /// - The initiator has not yet determined the handshake is over (by receiving a zrtp 'ConfAck' or authenticated + /// audio data) /// - The responder's user has accepted the call (causing the responder to send zrtp 'Hello') /// - The responder has not yet determined the handshake is over (by receiving a zrtp 'Confirm2') CallProgressType_Securing, - + /// Talking covers: /// - Sending/Receiving encrypted and authenticated audio CallProgressType_Talking, @@ -39,11 +40,11 @@ enum CallProgressType { * The CallProgress class is just an NSObject wrapper for the CallProgressType enum. * **/ -@interface CallProgress : NSObject +@interface CallProgress : NSObject @property (nonatomic, readonly) enum CallProgressType type; -+(CallProgress*) callProgressWithType:(enum CallProgressType)type; --(NSString*) localizedDescriptionForUser; ++ (CallProgress *)callProgressWithType:(enum CallProgressType)type; +- (NSString *)localizedDescriptionForUser; @end diff --git a/Signal/src/phone/callstate/CallProgress.m b/Signal/src/phone/callstate/CallProgress.m index d351e5392..191bffb3d 100644 --- a/Signal/src/phone/callstate/CallProgress.m +++ b/Signal/src/phone/callstate/CallProgress.m @@ -5,26 +5,26 @@ @synthesize type; -+(CallProgress*) callProgressWithType:(enum CallProgressType)type { - CallProgress* instance = [CallProgress new]; - instance->type = type; ++ (CallProgress *)callProgressWithType:(enum CallProgressType)type { + CallProgress *instance = [CallProgress new]; + instance->type = type; return instance; } --(BOOL)isEqual:(id)object { - return [object isKindOfClass:CallProgress.class] && ((CallProgress*)object).type == type; +- (BOOL)isEqual:(id)object { + return [object isKindOfClass:CallProgress.class] && ((CallProgress *)object).type == type; } --(NSUInteger)hash { +- (NSUInteger)hash { return type; } --(NSString *)description { +- (NSString *)description { return makeCallProgressLocalizedTextDictionary()[self]; } --(NSString*) localizedDescriptionForUser { +- (NSString *)localizedDescriptionForUser { return [self description]; } --(id)copyWithZone:(NSZone *)zone { +- (id)copyWithZone:(NSZone *)zone { return [CallProgress callProgressWithType:type]; } diff --git a/Signal/src/phone/callstate/CallState.h b/Signal/src/phone/callstate/CallState.h index a8adb3d39..ac09dd1b4 100644 --- a/Signal/src/phone/callstate/CallState.h +++ b/Signal/src/phone/callstate/CallState.h @@ -1,37 +1,40 @@ #import +#import "Contact.h" #import "ObservableValue.h" #import "PhoneNumber.h" -#import "Contact.h" -/** +/** * * CallState exposes the state of a single call, in a simplified way intended to be consumed by the user interface code. * - * The observable value observableProgress exposes values of type CallProgression that indicate the progression of the call, from connecting through teminated. + * The observable value observableProgress exposes values of type CallProgression that indicate the progression of the + * call, from connecting through teminated. * The future futureTermination will eventually contain a CallTermination that indicates how the call terminated. - * The future futureShortAuthenticationString will eventually contain the sas to display, or else a failure if the call fails beforehand. + * The future futureShortAuthenticationString will eventually contain the sas to display, or else a failure if the call + * fails beforehand. * The remoteNumber field is what it sounds like. * The initiatedLocally field determines if we are the initiator of the call or the responder to a call. * - * The futures exposed by this type are guaranteed to run callbacks (from then/catch/finally/etc) either inline or on the main thread. + * The futures exposed by this type are guaranteed to run callbacks (from then/catch/finally/etc) either inline or on + * the main thread. * */ @interface CallState : NSObject -@property (nonatomic, readonly) ObservableValue* observableProgress; -@property (nonatomic, readonly) TOCFuture* futureTermination; -@property (nonatomic, readonly) TOCFuture* futureShortAuthenticationString; -@property (nonatomic, readonly) PhoneNumber* remoteNumber; +@property (nonatomic, readonly) ObservableValue *observableProgress; +@property (nonatomic, readonly) TOCFuture *futureTermination; +@property (nonatomic, readonly) TOCFuture *futureShortAuthenticationString; +@property (nonatomic, readonly) PhoneNumber *remoteNumber; @property (nonatomic, readonly) bool initiatedLocally; -@property (nonatomic, readonly) Contact* potentiallySpecifiedContact; -@property (nonatomic, readonly) TOCFuture* futureCallLocallyAcceptedOrRejected; +@property (nonatomic, readonly) Contact *potentiallySpecifiedContact; +@property (nonatomic, readonly) TOCFuture *futureCallLocallyAcceptedOrRejected; -+(CallState*) callStateWithObservableProgress:(ObservableValue*)observableProgress - andFutureTermination:(TOCFuture*)futureTermination - andFutureSas:(TOCFuture*)futureSas - andRemoteNumber:(PhoneNumber*)remoteNumber - andInitiatedLocally:(bool)initiatedLocally - andPotentiallySpecifiedContact:(Contact*)contact - andFutureAccepted:(TOCFuture*)futureCallLocallyAcceptedOrRejected; ++ (CallState *)callStateWithObservableProgress:(ObservableValue *)observableProgress + andFutureTermination:(TOCFuture *)futureTermination + andFutureSas:(TOCFuture *)futureSas + andRemoteNumber:(PhoneNumber *)remoteNumber + andInitiatedLocally:(bool)initiatedLocally + andPotentiallySpecifiedContact:(Contact *)contact + andFutureAccepted:(TOCFuture *)futureCallLocallyAcceptedOrRejected; @end diff --git a/Signal/src/phone/callstate/CallState.m b/Signal/src/phone/callstate/CallState.m index 2e0ca7c17..11e954cb8 100644 --- a/Signal/src/phone/callstate/CallState.m +++ b/Signal/src/phone/callstate/CallState.m @@ -11,27 +11,26 @@ @synthesize potentiallySpecifiedContact; @synthesize futureCallLocallyAcceptedOrRejected; -+(CallState*) callStateWithObservableProgress:(ObservableValue*)observableProgress - andFutureTermination:(TOCFuture*)futureTermination - andFutureSas:(TOCFuture*)futureSas - andRemoteNumber:(PhoneNumber*)remoteNumber - andInitiatedLocally:(bool)initiatedLocally - andPotentiallySpecifiedContact:(Contact*)contact - andFutureAccepted:(TOCFuture*)futureCallLocallyAcceptedOrRejected { ++ (CallState *)callStateWithObservableProgress:(ObservableValue *)observableProgress + andFutureTermination:(TOCFuture *)futureTermination + andFutureSas:(TOCFuture *)futureSas + andRemoteNumber:(PhoneNumber *)remoteNumber + andInitiatedLocally:(bool)initiatedLocally + andPotentiallySpecifiedContact:(Contact *)contact + andFutureAccepted:(TOCFuture *)futureCallLocallyAcceptedOrRejected { + ows_require(observableProgress != nil); + ows_require(futureTermination != nil); + ows_require(futureSas != nil); + ows_require(remoteNumber != nil); + ows_require(futureCallLocallyAcceptedOrRejected != nil); - require(observableProgress != nil); - require(futureTermination != nil); - require(futureSas != nil); - require(remoteNumber != nil); - require(futureCallLocallyAcceptedOrRejected != nil); - - CallState* call = [CallState new]; - call->observableProgress = observableProgress; - call->futureTermination = futureTermination; - call->futureShortAuthenticationString = futureSas; - call->remoteNumber = remoteNumber; - call->initiatedLocally = initiatedLocally; - call->potentiallySpecifiedContact = contact; + CallState *call = [CallState new]; + call->observableProgress = observableProgress; + call->futureTermination = futureTermination; + call->futureShortAuthenticationString = futureSas; + call->remoteNumber = remoteNumber; + call->initiatedLocally = initiatedLocally; + call->potentiallySpecifiedContact = contact; call->futureCallLocallyAcceptedOrRejected = futureCallLocallyAcceptedOrRejected; return call; } diff --git a/Signal/src/phone/callstate/CallTermination.h b/Signal/src/phone/callstate/CallTermination.h index 875e03670..a427b32d3 100644 --- a/Signal/src/phone/callstate/CallTermination.h +++ b/Signal/src/phone/callstate/CallTermination.h @@ -2,29 +2,35 @@ enum CallTerminationType { // -- while connecting -- - CallTerminationType_LoginFailed, /// The signaling server said our authentication details were wrong. - CallTerminationType_NoSuchUser, /// The signaling server said there's red phone user with that number. - CallTerminationType_StaleSession, /// The signaling server said the call we're trying to respond to managed to end before we made contact. - CallTerminationType_ServerMessage, /// The signaling server said we should display a custom message (it's in the messageInfo property). - + CallTerminationType_LoginFailed, /// The signaling server said our authentication details were wrong. + CallTerminationType_NoSuchUser, /// The signaling server said there's red phone user with that number. + CallTerminationType_StaleSession, /// The signaling server said the call we're trying to respond to managed to end + /// before we made contact. + CallTerminationType_ServerMessage, /// The signaling server said we should display a custom message (it's in the + /// messageInfo property). + // -- while ringing -- CallTerminationType_ResponderIsBusy, /// The signaling server said the responder can't answer because they're busy. - CallTerminationType_RecipientUnavailable, /// The signaling server said the responder never contacted it about the incoming call. - CallTerminationType_RejectedLocal, /// We did not accept the call. - CallTerminationType_RejectedRemote, /// The signaling server said the other side hung up (before handshake). + CallTerminationType_RecipientUnavailable, /// The signaling server said the responder never contacted it about the + /// incoming call. + CallTerminationType_RejectedLocal, /// We did not accept the call. + CallTerminationType_RejectedRemote, /// The signaling server said the other side hung up (before handshake). // -- while securing -- - CallTerminationType_HandshakeFailed, /// Something went wrong in the middle of the zrtp handshake. + CallTerminationType_HandshakeFailed, /// Something went wrong in the middle of the zrtp handshake. CallTerminationType_InvalidRemotePublicKey, /// The publickey supplied from the remote participant was not valid - + // -- anytime -- - CallTerminationType_HangupLocal, /// We hung up. - CallTerminationType_HangupRemote, /// The signaling server said the other side hung up (after they accepted). - CallTerminationType_ReplacedByNext, /// We automatically hung up because we started another call. (e.g. incoming call cancelled by us dialing out) - + CallTerminationType_HangupLocal, /// We hung up. + CallTerminationType_HangupRemote, /// The signaling server said the other side hung up (after they accepted). + CallTerminationType_ReplacedByNext, /// We automatically hung up because we started another call. (e.g. incoming + /// call cancelled by us dialing out) + // -- uh oh -- - CallTerminationType_BadInteractionWithServer, /// The signaling or relay server did something we didn't expect or understand. - CallTerminationType_UncategorizedFailure, /// Something went wrong. We didn't handle it properly, so we don't know what exactly it was. + CallTerminationType_BadInteractionWithServer, /// The signaling or relay server did something we didn't expect or + /// understand. + CallTerminationType_UncategorizedFailure, /// Something went wrong. We didn't handle it properly, so we don't know + /// what exactly it was. CallTerminationType_BackgroundTimeExpired, /// The application expired available time while in background. }; @@ -34,15 +40,15 @@ enum CallTerminationType { * **/ -@interface CallTermination : NSObject +@interface CallTermination : NSObject @property (readonly, nonatomic) enum CallTerminationType type; @property (readonly, nonatomic) id failure; @property (readonly, nonatomic) id messageInfo; -+(CallTermination*) callTerminationOfType:(enum CallTerminationType)type - withFailure:(id)failure - andMessageInfo:(id)messageInfo; --(NSString*) localizedDescriptionForUser; ++ (CallTermination *)callTerminationOfType:(enum CallTerminationType)type + withFailure:(id)failure + andMessageInfo:(id)messageInfo; +- (NSString *)localizedDescriptionForUser; @end diff --git a/Signal/src/phone/callstate/CallTermination.m b/Signal/src/phone/callstate/CallTermination.m index b82b8e22a..4b5d4fb65 100644 --- a/Signal/src/phone/callstate/CallTermination.m +++ b/Signal/src/phone/callstate/CallTermination.m @@ -5,31 +5,30 @@ @synthesize type, failure, messageInfo; -+(CallTermination*) callTerminationOfType:(enum CallTerminationType)type - withFailure:(id)failure - andMessageInfo:(id)messageInfo { - - CallTermination* instance = [CallTermination new]; - instance->type = type; - instance->failure = failure; - instance->messageInfo = messageInfo; ++ (CallTermination *)callTerminationOfType:(enum CallTerminationType)type + withFailure:(id)failure + andMessageInfo:(id)messageInfo { + CallTermination *instance = [CallTermination new]; + instance->type = type; + instance->failure = failure; + instance->messageInfo = messageInfo; return instance; } --(BOOL)isEqual:(id)object { - return [object isKindOfClass:CallTermination.class] && ((CallTermination*)object).type == type; +- (BOOL)isEqual:(id)object { + return [object isKindOfClass:CallTermination.class] && ((CallTermination *)object).type == type; } --(NSUInteger)hash { +- (NSUInteger)hash { return type; } --(NSString *)description { +- (NSString *)description { return makeCallTerminationLocalizedTextDictionary()[self]; } --(NSString*) localizedDescriptionForUser { +- (NSString *)localizedDescriptionForUser { return [self description]; } --(id)copyWithZone:(NSZone *)zone { +- (id)copyWithZone:(NSZone *)zone { return [CallTermination callTerminationOfType:type withFailure:[failure copyWithZone:zone] andMessageInfo:[messageInfo copyWithZone:zone]]; diff --git a/Signal/src/phone/signaling/CallConnectResult.h b/Signal/src/phone/signaling/CallConnectResult.h index 36018522a..7588b7009 100644 --- a/Signal/src/phone/signaling/CallConnectResult.h +++ b/Signal/src/phone/signaling/CallConnectResult.h @@ -9,10 +9,10 @@ */ @interface CallConnectResult : NSObject -@property (nonatomic,readonly) NSString* shortAuthenticationString; -@property (nonatomic,readonly) AudioSocket* audioSocket; +@property (nonatomic, readonly) NSString *shortAuthenticationString; +@property (nonatomic, readonly) AudioSocket *audioSocket; -+(CallConnectResult*) callConnectResultWithShortAuthenticationString:(NSString*)shortAuthenticationString - andAudioSocket:(AudioSocket*)audioSocket; ++ (CallConnectResult *)callConnectResultWithShortAuthenticationString:(NSString *)shortAuthenticationString + andAudioSocket:(AudioSocket *)audioSocket; @end diff --git a/Signal/src/phone/signaling/CallConnectResult.m b/Signal/src/phone/signaling/CallConnectResult.m index 6dca43ece..2dc782958 100644 --- a/Signal/src/phone/signaling/CallConnectResult.m +++ b/Signal/src/phone/signaling/CallConnectResult.m @@ -4,14 +4,14 @@ @synthesize audioSocket, shortAuthenticationString; -+(CallConnectResult*) callConnectResultWithShortAuthenticationString:(NSString*)shortAuthenticationString - andAudioSocket:(AudioSocket*)audioSocket { - require(shortAuthenticationString != nil); - require(audioSocket != nil); - - CallConnectResult* result = [CallConnectResult new]; ++ (CallConnectResult *)callConnectResultWithShortAuthenticationString:(NSString *)shortAuthenticationString + andAudioSocket:(AudioSocket *)audioSocket { + ows_require(shortAuthenticationString != nil); + ows_require(audioSocket != nil); + + CallConnectResult *result = [CallConnectResult new]; result->shortAuthenticationString = shortAuthenticationString; - result->audioSocket = audioSocket; + result->audioSocket = audioSocket; return result; } diff --git a/Signal/src/phone/signaling/CallConnectUtil.h b/Signal/src/phone/signaling/CallConnectUtil.h index 94705ffd2..6aaa04421 100644 --- a/Signal/src/phone/signaling/CallConnectUtil.h +++ b/Signal/src/phone/signaling/CallConnectUtil.h @@ -6,7 +6,7 @@ /** * * CallConnectUtil is a utility class containing methods related to connecting calls. - * + * * Its implementation is actually split over more specific utility classes: * - CallConnectUtil_Initiator * - CallConnectUtil_Responder @@ -16,14 +16,14 @@ @interface CallConnectUtil : NSObject /// Result has type Future(CallConnectResult) -+(TOCFuture*) asyncInitiateCallToRemoteNumber:(PhoneNumber*)remoteNumber - andCallController:(CallController*)callController; ++ (TOCFuture *)asyncInitiateCallToRemoteNumber:(PhoneNumber *)remoteNumber + andCallController:(CallController *)callController; /// Result has type Future(CallConnectResult) -+(TOCFuture*) asyncRespondToCallWithSessionDescriptor:(ResponderSessionDescriptor*)sessionDescriptor - andCallController:(CallController*)callController; ++ (TOCFuture *)asyncRespondToCallWithSessionDescriptor:(ResponderSessionDescriptor *)sessionDescriptor + andCallController:(CallController *)callController; /// Result has type Future(HttpResponse) -+(TOCFuture*) asyncSignalTooBusyToAnswerCallWithSessionDescriptor:(ResponderSessionDescriptor*)sessionDescriptor; ++ (TOCFuture *)asyncSignalTooBusyToAnswerCallWithSessionDescriptor:(ResponderSessionDescriptor *)sessionDescriptor; @end diff --git a/Signal/src/phone/signaling/CallConnectUtil.m b/Signal/src/phone/signaling/CallConnectUtil.m index 0614f9f99..a7c6b08a0 100644 --- a/Signal/src/phone/signaling/CallConnectUtil.m +++ b/Signal/src/phone/signaling/CallConnectUtil.m @@ -4,24 +4,23 @@ @implementation CallConnectUtil -+(TOCFuture*) asyncInitiateCallToRemoteNumber:(PhoneNumber *)remoteNumber - andCallController:(CallController*)callController { - require(remoteNumber != nil); - require(callController != nil); - return [CallConnectUtil_Initiator asyncConnectCallToRemoteNumber:remoteNumber - withCallController:callController]; ++ (TOCFuture *)asyncInitiateCallToRemoteNumber:(PhoneNumber *)remoteNumber + andCallController:(CallController *)callController { + ows_require(remoteNumber != nil); + ows_require(callController != nil); + return [CallConnectUtil_Initiator asyncConnectCallToRemoteNumber:remoteNumber withCallController:callController]; } -+(TOCFuture*) asyncRespondToCallWithSessionDescriptor:(ResponderSessionDescriptor*)sessionDescriptor - andCallController:(CallController*)callController { - require(sessionDescriptor != nil); - require(callController != nil); ++ (TOCFuture *)asyncRespondToCallWithSessionDescriptor:(ResponderSessionDescriptor *)sessionDescriptor + andCallController:(CallController *)callController { + ows_require(sessionDescriptor != nil); + ows_require(callController != nil); return [CallConnectUtil_Responder asyncConnectToIncomingCallWithSessionDescriptor:sessionDescriptor - andCallController:callController]; + andCallController:callController]; } -+(TOCFuture*) asyncSignalTooBusyToAnswerCallWithSessionDescriptor:(ResponderSessionDescriptor*)sessionDescriptor { - require(sessionDescriptor != nil); ++ (TOCFuture *)asyncSignalTooBusyToAnswerCallWithSessionDescriptor:(ResponderSessionDescriptor *)sessionDescriptor { + ows_require(sessionDescriptor != nil); return [CallConnectUtil_Responder asyncSignalTooBusyToAnswerCallWithSessionDescriptor:sessionDescriptor]; } diff --git a/Signal/src/phone/signaling/CallConnectUtil_Initiator.h b/Signal/src/phone/signaling/CallConnectUtil_Initiator.h index 6ab855cc3..fd44e8814 100644 --- a/Signal/src/phone/signaling/CallConnectUtil_Initiator.h +++ b/Signal/src/phone/signaling/CallConnectUtil_Initiator.h @@ -17,8 +17,7 @@ @interface CallConnectUtil_Initiator : NSObject /// Result has type Future*(CallConnectResult) -+(TOCFuture*) asyncConnectCallToRemoteNumber:(PhoneNumber*)remoteNumber - withCallController:(CallController*)callController; ++ (TOCFuture *)asyncConnectCallToRemoteNumber:(PhoneNumber *)remoteNumber + withCallController:(CallController *)callController; @end - diff --git a/Signal/src/phone/signaling/CallConnectUtil_Initiator.m b/Signal/src/phone/signaling/CallConnectUtil_Initiator.m index 7a58b1a45..fb8bc17c7 100644 --- a/Signal/src/phone/signaling/CallConnectUtil_Initiator.m +++ b/Signal/src/phone/signaling/CallConnectUtil_Initiator.m @@ -8,69 +8,72 @@ @implementation CallConnectUtil_Initiator -+(TOCFuture*) asyncConnectCallToRemoteNumber:(PhoneNumber*)remoteNumber - withCallController:(CallController*)callController { - - require(remoteNumber != nil); - require(callController != nil); - require(callController.isInitiator); - - TOCFuture* futureInitiatorSessionDescriptor = [self asyncConnectToSignalServerAndGetInitiatorSessionDescriptorWithCallController:callController]; - - return [futureInitiatorSessionDescriptor thenTry:^(InitiatorSessionDescriptor* session) { - return [CallConnectUtil_Server asyncConnectCallOverRelayDescribedInInitiatorSessionDescriptor:session - withCallController:callController - andInteropOptions:@[]]; ++ (TOCFuture *)asyncConnectCallToRemoteNumber:(PhoneNumber *)remoteNumber + withCallController:(CallController *)callController { + ows_require(remoteNumber != nil); + ows_require(callController != nil); + ows_require(callController.isInitiator); + + TOCFuture *futureInitiatorSessionDescriptor = + [self asyncConnectToSignalServerAndGetInitiatorSessionDescriptorWithCallController:callController]; + + return [futureInitiatorSessionDescriptor thenTry:^(InitiatorSessionDescriptor *session) { + return [CallConnectUtil_Server asyncConnectCallOverRelayDescribedInInitiatorSessionDescriptor:session + withCallController:callController + andInteropOptions:@[]]; }]; } -+(TOCFuture*) asyncConnectToSignalServerAndGetInitiatorSessionDescriptorWithCallController:(CallController*)callController { - require(callController != nil); - - TOCFuture* futureSignalConnection = [CallConnectUtil_Server asyncConnectToDefaultSignalingServerUntilCancelled:callController.untilCancelledToken]; - - return [futureSignalConnection thenTry:^(HttpManager* httpManager) { - requireState([httpManager isKindOfClass:HttpManager.class]); - - TOCFutureSource* predeclaredFutureSession = [TOCFutureSource new]; - - HttpResponse*(^serverRequestHandler)(HttpRequest*) = ^(HttpRequest* remoteRequest) { - return [self respondToServerRequest:remoteRequest - usingEventualDescriptor:predeclaredFutureSession.future - andCallController:callController]; - }; - - [httpManager startWithRequestHandler:serverRequestHandler - andErrorHandler:callController.errorHandler - untilCancelled:[callController untilCancelledToken]]; - - HttpRequest* initiateRequest = [HttpRequest httpRequestToInitiateToRemoteNumber:callController.callState.remoteNumber]; - TOCFuture* futureResponseToInitiate = [httpManager asyncOkResponseForRequest:initiateRequest - unlessCancelled:[callController untilCancelledToken]]; - TOCFuture* futureResponseToInitiateWithInterpretedFailures = [futureResponseToInitiate catchTry:^(id error) { - if ([error isKindOfClass:HttpResponse.class]) { - HttpResponse* badResponse = error; - return [TOCFuture futureWithFailure:[self callTerminationForBadResponse:badResponse - toInitiateRequest:initiateRequest]]; - } - - return [TOCFuture futureWithFailure:error]; - }]; - - TOCFuture* futureSession = [futureResponseToInitiateWithInterpretedFailures thenTry:^(HttpResponse* response) { - return [InitiatorSessionDescriptor initiatorSessionDescriptorFromJson:response.getOptionalBodyText]; - }]; - [predeclaredFutureSession trySetResult:futureSession]; - - return futureSession; ++ (TOCFuture *)asyncConnectToSignalServerAndGetInitiatorSessionDescriptorWithCallController: + (CallController *)callController { + ows_require(callController != nil); + + TOCFuture *futureSignalConnection = + [CallConnectUtil_Server asyncConnectToDefaultSignalingServerUntilCancelled:callController.untilCancelledToken]; + + return [futureSignalConnection thenTry:^(HttpManager *httpManager) { + requireState([httpManager isKindOfClass:HttpManager.class]); + + TOCFutureSource *predeclaredFutureSession = [TOCFutureSource new]; + + HttpResponse * (^serverRequestHandler)(HttpRequest *) = ^(HttpRequest *remoteRequest) { + return [self respondToServerRequest:remoteRequest + usingEventualDescriptor:predeclaredFutureSession.future + andCallController:callController]; + }; + + [httpManager startWithRequestHandler:serverRequestHandler + andErrorHandler:callController.errorHandler + untilCancelled:[callController untilCancelledToken]]; + + HttpRequest *initiateRequest = + [HttpRequest httpRequestToInitiateToRemoteNumber:callController.callState.remoteNumber]; + TOCFuture *futureResponseToInitiate = + [httpManager asyncOkResponseForRequest:initiateRequest unlessCancelled:[callController untilCancelledToken]]; + TOCFuture *futureResponseToInitiateWithInterpretedFailures = [futureResponseToInitiate catchTry:^(id error) { + if ([error isKindOfClass:HttpResponse.class]) { + HttpResponse *badResponse = error; + return [TOCFuture + futureWithFailure:[self callTerminationForBadResponse:badResponse toInitiateRequest:initiateRequest]]; + } + + return [TOCFuture futureWithFailure:error]; + }]; + + TOCFuture *futureSession = [futureResponseToInitiateWithInterpretedFailures thenTry:^(HttpResponse *response) { + return [InitiatorSessionDescriptor initiatorSessionDescriptorFromJson:response.getOptionalBodyText]; + }]; + [predeclaredFutureSession trySetResult:futureSession]; + + return futureSession; }]; } -+(CallTermination*) callTerminationForBadResponse:(HttpResponse*)badResponse - toInitiateRequest:(HttpRequest*)initiateRequest { - require(badResponse != nil); - require(initiateRequest != nil); - ++ (CallTermination *)callTerminationForBadResponse:(HttpResponse *)badResponse + toInitiateRequest:(HttpRequest *)initiateRequest { + ows_require(badResponse != nil); + ows_require(initiateRequest != nil); + switch (badResponse.getStatusCode) { case SIGNAL_STATUS_CODE_NO_SUCH_USER: return [CallTermination callTerminationOfType:CallTerminationType_NoSuchUser @@ -91,40 +94,42 @@ } } -+(HttpResponse*) respondToServerRequest:(HttpRequest*)request - usingEventualDescriptor:(TOCFuture*)futureInitiatorSessionDescriptor - andCallController:(CallController*)callController { - require(request != nil); - require(futureInitiatorSessionDescriptor != nil); - require(callController != nil); - ++ (HttpResponse *)respondToServerRequest:(HttpRequest *)request + usingEventualDescriptor:(TOCFuture *)futureInitiatorSessionDescriptor + andCallController:(CallController *)callController { + ows_require(request != nil); + ows_require(futureInitiatorSessionDescriptor != nil); + ows_require(callController != nil); + // heart beat? if (request.isKeepAlive) { return [HttpResponse httpResponse200Ok]; } - + // too soon? if (!futureInitiatorSessionDescriptor.hasResult) { - [callController terminateWithReason:CallTerminationType_BadInteractionWithServer - withFailureInfo:[IgnoredPacketFailure new:@"Didn't receive session id from signaling server. Not able to understand request."] - andRelatedInfo:request]; + [callController + terminateWithReason:CallTerminationType_BadInteractionWithServer + withFailureInfo: + [IgnoredPacketFailure + new:@"Didn't receive session id from signaling server. Not able to understand request."] + andRelatedInfo:request]; return [HttpResponse httpResponse500InternalServerError]; } int64_t sessionId = [[futureInitiatorSessionDescriptor forceGetResult] sessionId]; - + // hangup? if ([request isHangupForSession:sessionId]) { - [callController terminateWithRejectionOrRemoteHangupAndFailureInfo:nil - andRelatedInfo:request]; + [callController terminateWithRejectionOrRemoteHangupAndFailureInfo:nil andRelatedInfo:request]; return [HttpResponse httpResponse200Ok]; } - + // ringing? if ([request isRingingForSession:sessionId]) { [callController advanceCallProgressTo:CallProgressType_Ringing]; return [HttpResponse httpResponse200Ok]; } - + // busy signal? if ([request isBusyForSession:sessionId]) { [callController terminateWithReason:CallTerminationType_ResponderIsBusy @@ -132,7 +137,7 @@ andRelatedInfo:request]; return [HttpResponse httpResponse200Ok]; } - + // errr..... [callController terminateWithReason:CallTerminationType_BadInteractionWithServer withFailureInfo:[UnrecognizedRequestFailure new:@"Didn't understand signaling server."] diff --git a/Signal/src/phone/signaling/CallConnectUtil_Responder.h b/Signal/src/phone/signaling/CallConnectUtil_Responder.h index d087c97ac..152bc6526 100644 --- a/Signal/src/phone/signaling/CallConnectUtil_Responder.h +++ b/Signal/src/phone/signaling/CallConnectUtil_Responder.h @@ -1,7 +1,7 @@ #import +#import "CallController.h" #import "HttpManager.h" #import "ResponderSessionDescriptor.h" -#import "CallController.h" /** * @@ -17,10 +17,10 @@ @interface CallConnectUtil_Responder : NSObject /// Result has type Future(CallConnectResult) -+(TOCFuture*) asyncConnectToIncomingCallWithSessionDescriptor:(ResponderSessionDescriptor*)sessionDescriptor - andCallController:(CallController*)callController; ++ (TOCFuture *)asyncConnectToIncomingCallWithSessionDescriptor:(ResponderSessionDescriptor *)sessionDescriptor + andCallController:(CallController *)callController; /// Result has type Future(HttpResponse) -+(TOCFuture*) asyncSignalTooBusyToAnswerCallWithSessionDescriptor:(ResponderSessionDescriptor*)sessionDescriptor; ++ (TOCFuture *)asyncSignalTooBusyToAnswerCallWithSessionDescriptor:(ResponderSessionDescriptor *)sessionDescriptor; @end diff --git a/Signal/src/phone/signaling/CallConnectUtil_Responder.m b/Signal/src/phone/signaling/CallConnectUtil_Responder.m index d652375fe..78302adc6 100644 --- a/Signal/src/phone/signaling/CallConnectUtil_Responder.m +++ b/Signal/src/phone/signaling/CallConnectUtil_Responder.m @@ -6,71 +6,71 @@ @implementation CallConnectUtil_Responder -+(TOCFuture*) asyncConnectToIncomingCallWithSessionDescriptor:(ResponderSessionDescriptor*)sessionDescriptor - andCallController:(CallController*)callController { - - require(sessionDescriptor != nil); - require(callController != nil); - require(!callController.isInitiator); - - TOCFuture* futureSignalsAreGo = [self asyncConnectToSignalServerDescribedBy:sessionDescriptor - withCallController:callController]; - - TOCFuture* futureSignalsAreGoAndCallAccepted = [futureSignalsAreGo thenTry:^(id _) { - [callController advanceCallProgressTo:CallProgressType_Ringing]; - - return [callController interactiveCallAccepted]; ++ (TOCFuture *)asyncConnectToIncomingCallWithSessionDescriptor:(ResponderSessionDescriptor *)sessionDescriptor + andCallController:(CallController *)callController { + ows_require(sessionDescriptor != nil); + ows_require(callController != nil); + ows_require(!callController.isInitiator); + + TOCFuture *futureSignalsAreGo = + [self asyncConnectToSignalServerDescribedBy:sessionDescriptor withCallController:callController]; + + TOCFuture *futureSignalsAreGoAndCallAccepted = [futureSignalsAreGo thenTry:^(id _) { + [callController advanceCallProgressTo:CallProgressType_Ringing]; + + return [callController interactiveCallAccepted]; }]; - + return [futureSignalsAreGoAndCallAccepted thenTry:^(id _) { - return [CallConnectUtil_Server asyncConnectCallOverRelayDescribedInResponderSessionDescriptor:sessionDescriptor - withCallController:callController]; + return [CallConnectUtil_Server asyncConnectCallOverRelayDescribedInResponderSessionDescriptor:sessionDescriptor + withCallController:callController]; }]; } -+(TOCFuture*) asyncConnectToSignalServerDescribedBy:(ResponderSessionDescriptor*)sessionDescriptor - withCallController:(CallController*)callController { - require(sessionDescriptor != nil); - require(callController != nil); - - TOCFuture* futureSignalConnection = [CallConnectUtil_Server asyncConnectToSignalingServerNamed:sessionDescriptor.relayServerName - untilCancelled:[callController untilCancelledToken]]; - - return [futureSignalConnection thenTry:^id(HttpManager* httpManager) { - require([httpManager isKindOfClass:HttpManager.class]); - - HttpResponse*(^serverRequestHandler)(HttpRequest*) = ^(HttpRequest* remoteRequest) { - return [self respondToServerRequest:remoteRequest - usingDescriptor:sessionDescriptor - andCallController:callController]; - }; - - [httpManager startWithRequestHandler:serverRequestHandler - andErrorHandler:Environment.errorNoter - untilCancelled:[callController untilCancelledToken]]; - - HttpRequest* ringRequest = [HttpRequest httpRequestToRingWithSessionId:sessionDescriptor.sessionId]; - TOCFuture* futureResponseToRing = [httpManager asyncOkResponseForRequest:ringRequest - unlessCancelled:[callController untilCancelledToken]]; - TOCFuture* futureResponseToRingWithInterpretedFailures = [futureResponseToRing catchTry:^(id error) { - if ([error isKindOfClass:HttpResponse.class]) { - HttpResponse* badResponse = error; - return [TOCFuture futureWithFailure:[self callTerminationForBadResponse:badResponse - toRingRequest:ringRequest]]; - } - - return [TOCFuture futureWithFailure:error]; - }]; - - return [futureResponseToRingWithInterpretedFailures thenValue:@YES]; ++ (TOCFuture *)asyncConnectToSignalServerDescribedBy:(ResponderSessionDescriptor *)sessionDescriptor + withCallController:(CallController *)callController { + ows_require(sessionDescriptor != nil); + ows_require(callController != nil); + + TOCFuture *futureSignalConnection = + [CallConnectUtil_Server asyncConnectToSignalingServerNamed:sessionDescriptor.relayServerName + untilCancelled:[callController untilCancelledToken]]; + + return [futureSignalConnection thenTry:^id(HttpManager *httpManager) { + ows_require([httpManager isKindOfClass:HttpManager.class]); + + HttpResponse * (^serverRequestHandler)(HttpRequest *) = ^(HttpRequest *remoteRequest) { + return [self respondToServerRequest:remoteRequest + usingDescriptor:sessionDescriptor + andCallController:callController]; + }; + + [httpManager startWithRequestHandler:serverRequestHandler + andErrorHandler:Environment.errorNoter + untilCancelled:[callController untilCancelledToken]]; + + HttpRequest *ringRequest = [HttpRequest httpRequestToRingWithSessionId:sessionDescriptor.sessionId]; + TOCFuture *futureResponseToRing = + [httpManager asyncOkResponseForRequest:ringRequest unlessCancelled:[callController untilCancelledToken]]; + TOCFuture *futureResponseToRingWithInterpretedFailures = [futureResponseToRing catchTry:^(id error) { + if ([error isKindOfClass:HttpResponse.class]) { + HttpResponse *badResponse = error; + return [TOCFuture + futureWithFailure:[self callTerminationForBadResponse:badResponse toRingRequest:ringRequest]]; + } + + return [TOCFuture futureWithFailure:error]; + }]; + + return [futureResponseToRingWithInterpretedFailures thenValue:@YES]; }]; } -+(CallTermination*) callTerminationForBadResponse:(HttpResponse*)badResponse - toRingRequest:(HttpRequest*)ringRequest { - require(badResponse != nil); - require(ringRequest != nil); - ++ (CallTermination *)callTerminationForBadResponse:(HttpResponse *)badResponse + toRingRequest:(HttpRequest *)ringRequest { + ows_require(badResponse != nil); + ows_require(ringRequest != nil); + switch (badResponse.getStatusCode) { case SIGNAL_STATUS_CODE_STALE_SESSION: return [CallTermination callTerminationOfType:CallTerminationType_StaleSession @@ -86,18 +86,18 @@ andMessageInfo:ringRequest]; } } -+(HttpResponse*) respondToServerRequest:(HttpRequest*)request - usingDescriptor:(ResponderSessionDescriptor*)responderSessionDescriptor - andCallController:(CallController*)callController { - require(request != nil); - require(responderSessionDescriptor != nil); - require(callController != nil); - ++ (HttpResponse *)respondToServerRequest:(HttpRequest *)request + usingDescriptor:(ResponderSessionDescriptor *)responderSessionDescriptor + andCallController:(CallController *)callController { + ows_require(request != nil); + ows_require(responderSessionDescriptor != nil); + ows_require(callController != nil); + // heart beat? if (request.isKeepAlive) { return [HttpResponse httpResponse200Ok]; } - + // hangup? if ([request isHangupForSession:responderSessionDescriptor.sessionId]) { [callController terminateWithReason:CallTerminationType_HangupRemote @@ -105,7 +105,7 @@ andRelatedInfo:request]; return [HttpResponse httpResponse200Ok]; } - + // errr...... [callController terminateWithReason:CallTerminationType_BadInteractionWithServer withFailureInfo:[UnrecognizedRequestFailure new:@"Didn't understand signaling server."] @@ -113,36 +113,34 @@ return [HttpResponse httpResponse501NotImplemented]; } -+(TOCFuture*) asyncSignalTooBusyToAnswerCallWithSessionDescriptor:(ResponderSessionDescriptor*)sessionDescriptor { - require(sessionDescriptor != nil); - - HttpRequest* busyRequest = [HttpRequest httpRequestToSignalBusyWithSessionId:sessionDescriptor.sessionId]; - ++ (TOCFuture *)asyncSignalTooBusyToAnswerCallWithSessionDescriptor:(ResponderSessionDescriptor *)sessionDescriptor { + ows_require(sessionDescriptor != nil); + + HttpRequest *busyRequest = [HttpRequest httpRequestToSignalBusyWithSessionId:sessionDescriptor.sessionId]; + return [self asyncOkResponseFor:busyRequest fromSignalingServerNamed:sessionDescriptor.relayServerName unlessCancelled:nil andErrorHandler:Environment.errorNoter]; } -+(TOCFuture*) asyncOkResponseFor:(HttpRequest*)request - fromSignalingServerNamed:(NSString*)name - unlessCancelled:(TOCCancelToken*)unlessCancelledToken - andErrorHandler:(ErrorHandlerBlock)errorHandler { - require(request != nil); - require(errorHandler != nil); - require(name != nil); - - HttpManager* manager = [HttpManager startWithEndPoint:[Environment getSecureEndPointToSignalingServerNamed:name] ++ (TOCFuture *)asyncOkResponseFor:(HttpRequest *)request + fromSignalingServerNamed:(NSString *)name + unlessCancelled:(TOCCancelToken *)unlessCancelledToken + andErrorHandler:(ErrorHandlerBlock)errorHandler { + ows_require(request != nil); + ows_require(errorHandler != nil); + ows_require(name != nil); + + HttpManager *manager = [HttpManager startWithEndPoint:[Environment getSecureEndPointToSignalingServerNamed:name] untilCancelled:unlessCancelledToken]; - - [manager startWithRejectingRequestHandlerAndErrorHandler:errorHandler - untilCancelled:nil]; - - TOCFuture* result = [manager asyncOkResponseForRequest:request - unlessCancelled:unlessCancelledToken]; - + + [manager startWithRejectingRequestHandlerAndErrorHandler:errorHandler untilCancelled:nil]; + + TOCFuture *result = [manager asyncOkResponseForRequest:request unlessCancelled:unlessCancelledToken]; + [manager terminateWhenDoneCurrentWork]; - + return result; } diff --git a/Signal/src/phone/signaling/CallConnectUtil_Server.h b/Signal/src/phone/signaling/CallConnectUtil_Server.h index 2db721c50..1530aa9b5 100644 --- a/Signal/src/phone/signaling/CallConnectUtil_Server.h +++ b/Signal/src/phone/signaling/CallConnectUtil_Server.h @@ -11,19 +11,18 @@ @interface CallConnectUtil_Server : NSObject /// Result has type Future(HttpManager) -+(TOCFuture*) asyncConnectToDefaultSignalingServerUntilCancelled:(TOCCancelToken*)untilCancelledToken; ++ (TOCFuture *)asyncConnectToDefaultSignalingServerUntilCancelled:(TOCCancelToken *)untilCancelledToken; /// Result has type Future(HttpManager) -+(TOCFuture*) asyncConnectToSignalingServerNamed:(NSString*)name - untilCancelled:(TOCCancelToken*)untilCancelledToken; ++ (TOCFuture *)asyncConnectToSignalingServerNamed:(NSString *)name untilCancelled:(TOCCancelToken *)untilCancelledToken; /// Result has type Future(CallConnectResult) -+(TOCFuture*) asyncConnectCallOverRelayDescribedInResponderSessionDescriptor:(ResponderSessionDescriptor*)session - withCallController:(CallController*)callController; ++ (TOCFuture *)asyncConnectCallOverRelayDescribedInResponderSessionDescriptor:(ResponderSessionDescriptor *)session + withCallController:(CallController *)callController; /// Result has type Future(CallConnectResult) -+(TOCFuture*) asyncConnectCallOverRelayDescribedInInitiatorSessionDescriptor:(InitiatorSessionDescriptor*)session - withCallController:(CallController*)callController - andInteropOptions:(NSArray*)interopOptions; ++ (TOCFuture *)asyncConnectCallOverRelayDescribedInInitiatorSessionDescriptor:(InitiatorSessionDescriptor *)session + withCallController:(CallController *)callController + andInteropOptions:(NSArray *)interopOptions; @end diff --git a/Signal/src/phone/signaling/CallConnectUtil_Server.m b/Signal/src/phone/signaling/CallConnectUtil_Server.m index a8146d710..18b07a8cc 100644 --- a/Signal/src/phone/signaling/CallConnectUtil_Server.m +++ b/Signal/src/phone/signaling/CallConnectUtil_Server.m @@ -13,184 +13,186 @@ @implementation CallConnectUtil_Server -+(TOCFuture*) asyncConnectToDefaultSignalingServerUntilCancelled:(TOCCancelToken*)untilCancelledToken { ++ (TOCFuture *)asyncConnectToDefaultSignalingServerUntilCancelled:(TOCCancelToken *)untilCancelledToken { return [self asyncConnectToSignalingServerAt:Environment.getSecureEndPointToDefaultRelayServer untilCancelled:untilCancelledToken]; } -+(TOCFuture*) asyncConnectToSignalingServerNamed:(NSString*)name - untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(name != nil); ++ (TOCFuture *)asyncConnectToSignalingServerNamed:(NSString *)name + untilCancelled:(TOCCancelToken *)untilCancelledToken { + ows_require(name != nil); return [self asyncConnectToSignalingServerAt:[Environment getSecureEndPointToSignalingServerNamed:name] untilCancelled:untilCancelledToken]; } -+(TOCFuture*) asyncConnectToSignalingServerAt:(SecureEndPoint*)location - untilCancelled:(TOCCancelToken*)untilCancelledToken { - require(location != nil); - - TOCFuture* futureConnection = [LowLatencyConnector asyncLowLatencyConnectToEndPoint:location - untilCancelled:untilCancelledToken]; - - return [futureConnection thenTry:^(LowLatencyCandidate* result) { - HttpSocket* httpSocket = [HttpSocket httpSocketOver:[result networkStream]]; - return [HttpManager httpManagerFor:httpSocket - untilCancelled:untilCancelledToken]; ++ (TOCFuture *)asyncConnectToSignalingServerAt:(SecureEndPoint *)location + untilCancelled:(TOCCancelToken *)untilCancelledToken { + ows_require(location != nil); + + TOCFuture *futureConnection = + [LowLatencyConnector asyncLowLatencyConnectToEndPoint:location untilCancelled:untilCancelledToken]; + + return [futureConnection thenTry:^(LowLatencyCandidate *result) { + HttpSocket *httpSocket = [HttpSocket httpSocketOver:[result networkStream]]; + return [HttpManager httpManagerFor:httpSocket untilCancelled:untilCancelledToken]; }]; } -+(TOCFuture*) asyncConnectCallOverRelayDescribedInResponderSessionDescriptor:(ResponderSessionDescriptor*)session - withCallController:(CallController*)callController { - require(session != nil); - require(callController != nil); - - InitiatorSessionDescriptor* equivalentSession = [InitiatorSessionDescriptor initiatorSessionDescriptorWithSessionId:session.sessionId - andRelayServerName:session.relayServerName - andRelayPort:session.relayUdpPort]; - - NSArray* interopOptions = session.interopVersion == 0 - ? @[ENVIRONMENT_LEGACY_OPTION_RTP_PADDING_BIT_IMPLIES_EXTENSION_BIT_AND_TWELVE_EXTRA_ZERO_BYTES_IN_HEADER] - : @[]; - if (session.interopVersion > 1) Environment.errorNoter(@"Newer-than-code interop version specified.", session, false); - ++ (TOCFuture *)asyncConnectCallOverRelayDescribedInResponderSessionDescriptor:(ResponderSessionDescriptor *)session + withCallController:(CallController *)callController { + ows_require(session != nil); + ows_require(callController != nil); + + InitiatorSessionDescriptor *equivalentSession = + [InitiatorSessionDescriptor initiatorSessionDescriptorWithSessionId:session.sessionId + andRelayServerName:session.relayServerName + andRelayPort:session.relayUdpPort]; + + NSArray *interopOptions = + session.interopVersion == 0 + ? @[ ENVIRONMENT_LEGACY_OPTION_RTP_PADDING_BIT_IMPLIES_EXTENSION_BIT_AND_TWELVE_EXTRA_ZERO_BYTES_IN_HEADER ] + : @[]; + if (session.interopVersion > 1) + Environment.errorNoter(@"Newer-than-code interop version specified.", session, false); + return [self asyncConnectCallOverRelayDescribedInInitiatorSessionDescriptor:equivalentSession withCallController:callController andInteropOptions:interopOptions]; } -+(TOCFuture*) asyncConnectCallOverRelayDescribedInInitiatorSessionDescriptor:(InitiatorSessionDescriptor*)session - withCallController:(CallController*)callController - andInteropOptions:(NSArray*)interopOptions { - require(session != nil); - require(callController != nil); - - TOCFuture* futureUdpSocket = [self asyncRepeatedlyAttemptConnectToUdpRelayDescribedBy:session - withCallController:callController]; - - TOCFuture* futureZrtpHandshakeResult = [futureUdpSocket thenTry:^(UdpSocket* udpSocket) { - return [ZrtpManager asyncPerformHandshakeOver:[RtpSocket rtpSocketOverUdp:udpSocket interopOptions:interopOptions] - andCallController:callController]; ++ (TOCFuture *)asyncConnectCallOverRelayDescribedInInitiatorSessionDescriptor:(InitiatorSessionDescriptor *)session + withCallController:(CallController *)callController + andInteropOptions:(NSArray *)interopOptions { + ows_require(session != nil); + ows_require(callController != nil); + + TOCFuture *futureUdpSocket = + [self asyncRepeatedlyAttemptConnectToUdpRelayDescribedBy:session withCallController:callController]; + + TOCFuture *futureZrtpHandshakeResult = [futureUdpSocket thenTry:^(UdpSocket *udpSocket) { + return [ZrtpManager asyncPerformHandshakeOver:[RtpSocket rtpSocketOverUdp:udpSocket interopOptions:interopOptions] + andCallController:callController]; }]; - - return [futureZrtpHandshakeResult thenTry:^(ZrtpHandshakeResult* zrtpResult) { - AudioSocket* audioSocket = [AudioSocket audioSocketOver:[zrtpResult secureRtpSocket]]; - - NSString* sas = [[zrtpResult masterSecret] shortAuthenticationString]; - - return [CallConnectResult callConnectResultWithShortAuthenticationString:sas - andAudioSocket:audioSocket]; + + return [futureZrtpHandshakeResult thenTry:^(ZrtpHandshakeResult *zrtpResult) { + AudioSocket *audioSocket = [AudioSocket audioSocketOver:[zrtpResult secureRtpSocket]]; + + NSString *sas = [[zrtpResult masterSecret] shortAuthenticationString]; + + return [CallConnectResult callConnectResultWithShortAuthenticationString:sas andAudioSocket:audioSocket]; }]; } -+(TOCFuture*) asyncRepeatedlyAttemptConnectToUdpRelayDescribedBy:(InitiatorSessionDescriptor*)sessionDescriptor - withCallController:(CallController*)callController { - - require(sessionDescriptor != nil); - require(callController != nil); - - TOCUntilOperation operation = ^(TOCCancelToken* internalUntilCancelledToken) { - return [self asyncAttemptResolveThenConnectToUdpRelayDescribedBy:sessionDescriptor - untilCancelled:internalUntilCancelledToken - withErrorHandler:callController.errorHandler]; ++ (TOCFuture *)asyncRepeatedlyAttemptConnectToUdpRelayDescribedBy:(InitiatorSessionDescriptor *)sessionDescriptor + withCallController:(CallController *)callController { + ows_require(sessionDescriptor != nil); + ows_require(callController != nil); + + TOCUntilOperation operation = ^(TOCCancelToken *internalUntilCancelledToken) { + return [self asyncAttemptResolveThenConnectToUdpRelayDescribedBy:sessionDescriptor + untilCancelled:internalUntilCancelledToken + withErrorHandler:callController.errorHandler]; }; - - TOCFuture* futureRelayedUdpSocket = [TOCFuture retry:[TOCFuture operationTry:operation] + + TOCFuture *futureRelayedUdpSocket = [TOCFuture retry:[TOCFuture operationTry:operation] upToNTimes:MAX_TRY_COUNT withBaseTimeout:BASE_TIMEOUT_SECONDS andRetryFactor:RETRY_TIMEOUT_FACTOR untilCancelled:[callController untilCancelledToken]]; - + return [futureRelayedUdpSocket catchTry:^(id error) { - return [TOCFuture futureWithFailure:[CallTermination callTerminationOfType:CallTerminationType_BadInteractionWithServer - withFailure:error - andMessageInfo:@"Timed out on all attempts to contact relay."]]; + return [TOCFuture + futureWithFailure:[CallTermination callTerminationOfType:CallTerminationType_BadInteractionWithServer + withFailure:error + andMessageInfo:@"Timed out on all attempts to contact relay."]]; }]; } -+(TOCFuture*) asyncAttemptResolveThenConnectToUdpRelayDescribedBy:(InitiatorSessionDescriptor*)sessionDescriptor - untilCancelled:(TOCCancelToken*)untilCancelledToken - withErrorHandler:(ErrorHandlerBlock)errorHandler { - - require(sessionDescriptor != nil); - require(errorHandler != nil); - - NSString* domain = [Environment relayServerNameToHostName:sessionDescriptor.relayServerName]; - - TOCFuture* futureDnsResult = [DnsManager asyncQueryAddressesForDomainName:domain - unlessCancelled:untilCancelledToken]; - - TOCFuture* futureEndPoint = [futureDnsResult thenTry:^(NSArray* ipAddresses) { - require(ipAddresses.count > 0); - - IpAddress* address = ipAddresses[arc4random_uniform((unsigned int)ipAddresses.count)]; - return [IpEndPoint ipEndPointAtAddress:address - onPort:sessionDescriptor.relayUdpPort]; ++ (TOCFuture *)asyncAttemptResolveThenConnectToUdpRelayDescribedBy:(InitiatorSessionDescriptor *)sessionDescriptor + untilCancelled:(TOCCancelToken *)untilCancelledToken + withErrorHandler:(ErrorHandlerBlock)errorHandler { + ows_require(sessionDescriptor != nil); + ows_require(errorHandler != nil); + + NSString *domain = [Environment relayServerNameToHostName:sessionDescriptor.relayServerName]; + + TOCFuture *futureDnsResult = + [DnsManager asyncQueryAddressesForDomainName:domain unlessCancelled:untilCancelledToken]; + + TOCFuture *futureEndPoint = [futureDnsResult thenTry:^(NSArray *ipAddresses) { + ows_require(ipAddresses.count > 0); + + IpAddress *address = ipAddresses[arc4random_uniform((unsigned int)ipAddresses.count)]; + return [IpEndPoint ipEndPointAtAddress:address onPort:sessionDescriptor.relayUdpPort]; }]; - - return [futureEndPoint thenTry:^(IpEndPoint* remote) { - return [self asyncAttemptConnectToUdpRelayDescribedBy:remote - withSessionId:sessionDescriptor.sessionId - untilCancelled:untilCancelledToken - withErrorHandler:errorHandler]; + + return [futureEndPoint thenTry:^(IpEndPoint *remote) { + return [self asyncAttemptConnectToUdpRelayDescribedBy:remote + withSessionId:sessionDescriptor.sessionId + untilCancelled:untilCancelledToken + withErrorHandler:errorHandler]; }]; } -+(TOCFuture*) asyncAttemptConnectToUdpRelayDescribedBy:(IpEndPoint*)remoteEndPoint - withSessionId:(int64_t)sessionId - untilCancelled:(TOCCancelToken*)untilCancelledToken - withErrorHandler:(ErrorHandlerBlock)errorHandler { - - require(remoteEndPoint != nil); - require(errorHandler != nil); - - UdpSocket* udpSocket = [UdpSocket udpSocketTo:remoteEndPoint]; - ++ (TOCFuture *)asyncAttemptConnectToUdpRelayDescribedBy:(IpEndPoint *)remoteEndPoint + withSessionId:(int64_t)sessionId + untilCancelled:(TOCCancelToken *)untilCancelledToken + withErrorHandler:(ErrorHandlerBlock)errorHandler { + ows_require(remoteEndPoint != nil); + ows_require(errorHandler != nil); + + UdpSocket *udpSocket = [UdpSocket udpSocketTo:remoteEndPoint]; + id logger = [Environment.logging getOccurrenceLoggerForSender:self withKey:@"relay setup"]; - - TOCFuture* futureFirstResponseData = [self asyncFirstPacketReceivedAfterStartingSocket:udpSocket + + TOCFuture *futureFirstResponseData = [self asyncFirstPacketReceivedAfterStartingSocket:udpSocket untilCancelled:untilCancelledToken withErrorHandler:errorHandler]; - - TOCFuture* futureRelaySocket = [futureFirstResponseData thenTry:^id(NSData* openPortResponseData) { - HttpResponse* openPortResponse = [HttpResponse httpResponseFromData:openPortResponseData]; - [logger markOccurrence:openPortResponse]; - if (!openPortResponse.isOkResponse) return [TOCFuture futureWithFailure:openPortResponse]; - - return udpSocket; + + TOCFuture *futureRelaySocket = [futureFirstResponseData thenTry:^id(NSData *openPortResponseData) { + HttpResponse *openPortResponse = [HttpResponse httpResponseFromData:openPortResponseData]; + [logger markOccurrence:openPortResponse]; + if (!openPortResponse.isOkResponse) + return [TOCFuture futureWithFailure:openPortResponse]; + + return udpSocket; }]; - - HttpRequest* openPortRequest = [HttpRequest httpRequestToOpenPortWithSessionId:sessionId]; + + HttpRequest *openPortRequest = [HttpRequest httpRequestToOpenPortWithSessionId:sessionId]; [logger markOccurrence:openPortRequest]; [udpSocket send:[openPortRequest serialize]]; - + return futureRelaySocket; } -+(TOCFuture*) asyncFirstPacketReceivedAfterStartingSocket:(UdpSocket*)udpSocket - untilCancelled:(TOCCancelToken*)untilCancelledToken - withErrorHandler:(ErrorHandlerBlock)errorHandler { - - require(udpSocket != nil); - require(errorHandler != nil); - - TOCFutureSource* futureResultSource = [TOCFutureSource futureSourceUntil:untilCancelledToken]; - ++ (TOCFuture *)asyncFirstPacketReceivedAfterStartingSocket:(UdpSocket *)udpSocket + untilCancelled:(TOCCancelToken *)untilCancelledToken + withErrorHandler:(ErrorHandlerBlock)errorHandler { + ows_require(udpSocket != nil); + ows_require(errorHandler != nil); + + TOCFutureSource *futureResultSource = [TOCFutureSource futureSourceUntil:untilCancelledToken]; + PacketHandlerBlock packetHandler = ^(id packet) { - if (![futureResultSource trySetResult:packet]) {; - errorHandler([IgnoredPacketFailure new:@"Received another packet before relay socket events redirected to new handler."], packet, false); - } + if (![futureResultSource trySetResult:packet]) { + ; + errorHandler([IgnoredPacketFailure + new:@"Received another packet before relay socket events redirected to new handler."], + packet, + false); + } }; - + ErrorHandlerBlock socketErrorHandler = ^(id error, id relatedInfo, bool causedTermination) { - if (causedTermination) [futureResultSource trySetFailure:error]; - errorHandler(error, relatedInfo, causedTermination); + if (causedTermination) + [futureResultSource trySetFailure:error]; + errorHandler(error, relatedInfo, causedTermination); }; - - [udpSocket startWithHandler:[PacketHandler packetHandler:packetHandler - withErrorHandler:socketErrorHandler] + + [udpSocket startWithHandler:[PacketHandler packetHandler:packetHandler withErrorHandler:socketErrorHandler] untilCancelled:untilCancelledToken]; - + return futureResultSource.future; } diff --git a/Signal/src/phone/signaling/InitiateSignal.pb.h b/Signal/src/phone/signaling/InitiateSignal.pb.h index 7227457ac..bf98591a9 100644 --- a/Signal/src/phone/signaling/InitiateSignal.pb.h +++ b/Signal/src/phone/signaling/InitiateSignal.pb.h @@ -7,107 +7,110 @@ @class InitiateSignal; @class InitiateSignalBuilder; #ifndef __has_feature - #define __has_feature(x) 0 // Compatibility with non-clang compilers. -#endif // __has_feature +#define __has_feature(x) 0 // Compatibility with non-clang compilers. +#endif // __has_feature #ifndef NS_RETURNS_NOT_RETAINED - #if __has_feature(attribute_ns_returns_not_retained) - #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained)) - #else - #define NS_RETURNS_NOT_RETAINED - #endif +#if __has_feature(attribute_ns_returns_not_retained) +#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained)) +#else +#define NS_RETURNS_NOT_RETAINED +#endif #endif @interface InitiateSignalRoot : NSObject { } -+ (PBExtensionRegistry*) extensionRegistry; -+ (void) registerAllExtensions:(PBMutableExtensionRegistry*) registry; ++ (PBExtensionRegistry *)extensionRegistry; ++ (void)registerAllExtensions:(PBMutableExtensionRegistry *)registry; @end @interface InitiateSignal : PBGeneratedMessage { -@private - BOOL hasSessionId_:1; - BOOL hasInitiator_:1; - BOOL hasServerName_:1; - BOOL hasPort_:1; - BOOL hasVersion_:1; - UInt64 sessionId; - NSString* initiator; - NSString* serverName; - UInt32 port; - UInt32 version; + @private + BOOL hasSessionId_ : 1; + BOOL hasInitiator_ : 1; + BOOL hasServerName_ : 1; + BOOL hasPort_ : 1; + BOOL hasVersion_ : 1; + UInt64 sessionId; + NSString *initiator; + NSString *serverName; + UInt32 port; + UInt32 version; } -- (BOOL) hasInitiator; -- (BOOL) hasSessionId; -- (BOOL) hasPort; -- (BOOL) hasServerName; -- (BOOL) hasVersion; -@property (readonly, strong) NSString* initiator; +- (BOOL)hasInitiator; +- (BOOL)hasSessionId; +- (BOOL)hasPort; +- (BOOL)hasServerName; +- (BOOL)hasVersion; +@property (readonly, strong) NSString *initiator; @property (readonly) UInt64 sessionId; @property (readonly) UInt32 port; -@property (readonly, strong) NSString* serverName; +@property (readonly, strong) NSString *serverName; @property (readonly) UInt32 version; -+ (InitiateSignal*) defaultInstance; -- (InitiateSignal*) defaultInstance; ++ (InitiateSignal *)defaultInstance; +- (InitiateSignal *)defaultInstance; -- (BOOL) isInitialized; -- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output; -- (InitiateSignalBuilder*) builder; -+ (InitiateSignalBuilder*) builder; -+ (InitiateSignalBuilder*) builderWithPrototype:(InitiateSignal*) prototype; -- (InitiateSignalBuilder*) toBuilder; +- (BOOL)isInitialized; +- (void)writeToCodedOutputStream:(PBCodedOutputStream *)output; +- (InitiateSignalBuilder *)builder; ++ (InitiateSignalBuilder *)builder; ++ (InitiateSignalBuilder *)builderWithPrototype:(InitiateSignal *)prototype; +- (InitiateSignalBuilder *)toBuilder; -+ (InitiateSignal*) parseFromData:(NSData*) data; -+ (InitiateSignal*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -+ (InitiateSignal*) parseFromInputStream:(NSInputStream*) input; -+ (InitiateSignal*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -+ (InitiateSignal*) parseFromCodedInputStream:(PBCodedInputStream*) input; -+ (InitiateSignal*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; ++ (InitiateSignal *)parseFromData:(NSData *)data; ++ (InitiateSignal *)parseFromData:(NSData *)data extensionRegistry:(PBExtensionRegistry *)extensionRegistry; ++ (InitiateSignal *)parseFromInputStream:(NSInputStream *)input; ++ (InitiateSignal *)parseFromInputStream:(NSInputStream *)input + extensionRegistry:(PBExtensionRegistry *)extensionRegistry; ++ (InitiateSignal *)parseFromCodedInputStream:(PBCodedInputStream *)input; ++ (InitiateSignal *)parseFromCodedInputStream:(PBCodedInputStream *)input + extensionRegistry:(PBExtensionRegistry *)extensionRegistry; @end @interface InitiateSignalBuilder : PBGeneratedMessageBuilder { -@private - InitiateSignal* result; + @private + InitiateSignal *result; } -- (InitiateSignal*) defaultInstance; +- (InitiateSignal *)defaultInstance; -- (InitiateSignalBuilder*) clear; -- (InitiateSignalBuilder*) clone; +- (InitiateSignalBuilder *)clear; +- (InitiateSignalBuilder *)clone; -- (InitiateSignal*) build; -- (InitiateSignal*) buildPartial; +- (InitiateSignal *)build; +- (InitiateSignal *)buildPartial; -- (InitiateSignalBuilder*) mergeFrom:(InitiateSignal*) other; -- (InitiateSignalBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input; -- (InitiateSignalBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; +- (InitiateSignalBuilder *)mergeFrom:(InitiateSignal *)other; +- (InitiateSignalBuilder *)mergeFromCodedInputStream:(PBCodedInputStream *)input; +- (InitiateSignalBuilder *)mergeFromCodedInputStream:(PBCodedInputStream *)input + extensionRegistry:(PBExtensionRegistry *)extensionRegistry; -- (BOOL) hasInitiator; -- (NSString*) initiator; -- (InitiateSignalBuilder*) setInitiator:(NSString*) value; -- (InitiateSignalBuilder*) clearInitiator; +- (BOOL)hasInitiator; +- (NSString *)initiator; +- (InitiateSignalBuilder *)setInitiator:(NSString *)value; +- (InitiateSignalBuilder *)clearInitiator; -- (BOOL) hasSessionId; -- (UInt64) sessionId; -- (InitiateSignalBuilder*) setSessionId:(UInt64) value; -- (InitiateSignalBuilder*) clearSessionId; +- (BOOL)hasSessionId; +- (UInt64)sessionId; +- (InitiateSignalBuilder *)setSessionId:(UInt64)value; +- (InitiateSignalBuilder *)clearSessionId; -- (BOOL) hasPort; -- (UInt32) port; -- (InitiateSignalBuilder*) setPort:(UInt32) value; -- (InitiateSignalBuilder*) clearPort; +- (BOOL)hasPort; +- (UInt32)port; +- (InitiateSignalBuilder *)setPort:(UInt32)value; +- (InitiateSignalBuilder *)clearPort; -- (BOOL) hasServerName; -- (NSString*) serverName; -- (InitiateSignalBuilder*) setServerName:(NSString*) value; -- (InitiateSignalBuilder*) clearServerName; +- (BOOL)hasServerName; +- (NSString *)serverName; +- (InitiateSignalBuilder *)setServerName:(NSString *)value; +- (InitiateSignalBuilder *)clearServerName; -- (BOOL) hasVersion; -- (UInt32) version; -- (InitiateSignalBuilder*) setVersion:(UInt32) value; -- (InitiateSignalBuilder*) clearVersion; +- (BOOL)hasVersion; +- (UInt32)version; +- (InitiateSignalBuilder *)setVersion:(UInt32)value; +- (InitiateSignalBuilder *)clearVersion; @end diff --git a/Signal/src/phone/signaling/InitiateSignal.pb.m b/Signal/src/phone/signaling/InitiateSignal.pb.m index 2bb4e1636..035608b7c 100644 --- a/Signal/src/phone/signaling/InitiateSignal.pb.m +++ b/Signal/src/phone/signaling/InitiateSignal.pb.m @@ -4,403 +4,408 @@ // @@protoc_insertion_point(imports) @implementation InitiateSignalRoot -static PBExtensionRegistry* extensionRegistry = nil; -+ (PBExtensionRegistry*) extensionRegistry { - return extensionRegistry; +static PBExtensionRegistry *extensionRegistry = nil; ++ (PBExtensionRegistry *)extensionRegistry { + return extensionRegistry; } -+ (void) initialize { - if (self == [InitiateSignalRoot class]) { - PBMutableExtensionRegistry* registry = [PBMutableExtensionRegistry registry]; - [self registerAllExtensions:registry]; - extensionRegistry = registry; - } ++ (void)initialize { + if (self == [InitiateSignalRoot class]) { + PBMutableExtensionRegistry *registry = [PBMutableExtensionRegistry registry]; + [self registerAllExtensions:registry]; + extensionRegistry = registry; + } } -+ (void) registerAllExtensions:(PBMutableExtensionRegistry*) registry { ++ (void)registerAllExtensions:(PBMutableExtensionRegistry *)registry { } @end @interface InitiateSignal () -@property (strong) NSString* initiator; +@property (strong) NSString *initiator; @property UInt64 sessionId; @property UInt32 port; -@property (strong) NSString* serverName; +@property (strong) NSString *serverName; @property UInt32 version; @end @implementation InitiateSignal -- (BOOL) hasInitiator { - return !!hasInitiator_; +- (BOOL)hasInitiator { + return !!hasInitiator_; } -- (void) setHasInitiator:(BOOL) value_ { - hasInitiator_ = !!value_; +- (void)setHasInitiator:(BOOL)value_ { + hasInitiator_ = !!value_; } @synthesize initiator; -- (BOOL) hasSessionId { - return !!hasSessionId_; +- (BOOL)hasSessionId { + return !!hasSessionId_; } -- (void) setHasSessionId:(BOOL) value_ { - hasSessionId_ = !!value_; +- (void)setHasSessionId:(BOOL)value_ { + hasSessionId_ = !!value_; } @synthesize sessionId; -- (BOOL) hasPort { - return !!hasPort_; +- (BOOL)hasPort { + return !!hasPort_; } -- (void) setHasPort:(BOOL) value_ { - hasPort_ = !!value_; +- (void)setHasPort:(BOOL)value_ { + hasPort_ = !!value_; } @synthesize port; -- (BOOL) hasServerName { - return !!hasServerName_; +- (BOOL)hasServerName { + return !!hasServerName_; } -- (void) setHasServerName:(BOOL) value_ { - hasServerName_ = !!value_; +- (void)setHasServerName:(BOOL)value_ { + hasServerName_ = !!value_; } @synthesize serverName; -- (BOOL) hasVersion { - return !!hasVersion_; +- (BOOL)hasVersion { + return !!hasVersion_; } -- (void) setHasVersion:(BOOL) value_ { - hasVersion_ = !!value_; +- (void)setHasVersion:(BOOL)value_ { + hasVersion_ = !!value_; } @synthesize version; -- (id) init { - if ((self = [super init])) { - self.initiator = @""; - self.sessionId = 0L; - self.port = 0; - self.serverName = @""; - self.version = 0; - } - return self; +- (id)init { + if ((self = [super init])) { + self.initiator = @""; + self.sessionId = 0L; + self.port = 0; + self.serverName = @""; + self.version = 0; + } + return self; } -static InitiateSignal* defaultInitiateSignalInstance = nil; -+ (void) initialize { - if (self == [InitiateSignal class]) { - defaultInitiateSignalInstance = [[InitiateSignal alloc] init]; - } +static InitiateSignal *defaultInitiateSignalInstance = nil; ++ (void)initialize { + if (self == [InitiateSignal class]) { + defaultInitiateSignalInstance = [[InitiateSignal alloc] init]; + } } -+ (InitiateSignal*) defaultInstance { - return defaultInitiateSignalInstance; ++ (InitiateSignal *)defaultInstance { + return defaultInitiateSignalInstance; } -- (InitiateSignal*) defaultInstance { - return defaultInitiateSignalInstance; +- (InitiateSignal *)defaultInstance { + return defaultInitiateSignalInstance; } -- (BOOL) isInitialized { - return YES; -} -- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output { - if (self.hasInitiator) { - [output writeString:1 value:self.initiator]; - } - if (self.hasSessionId) { - [output writeUInt64:2 value:self.sessionId]; - } - if (self.hasPort) { - [output writeUInt32:3 value:self.port]; - } - if (self.hasServerName) { - [output writeString:4 value:self.serverName]; - } - if (self.hasVersion) { - [output writeUInt32:5 value:self.version]; - } - [self.unknownFields writeToCodedOutputStream:output]; -} -- (SInt32) serializedSize { - __block SInt32 size_ = memoizedSerializedSize; - if (size_ != -1) { - return size_; - } - - size_ = 0; - if (self.hasInitiator) { - size_ += computeStringSize(1, self.initiator); - } - if (self.hasSessionId) { - size_ += computeUInt64Size(2, self.sessionId); - } - if (self.hasPort) { - size_ += computeUInt32Size(3, self.port); - } - if (self.hasServerName) { - size_ += computeStringSize(4, self.serverName); - } - if (self.hasVersion) { - size_ += computeUInt32Size(5, self.version); - } - size_ += self.unknownFields.serializedSize; - memoizedSerializedSize = size_; - return size_; -} -+ (InitiateSignal*) parseFromData:(NSData*) data { - return (InitiateSignal*)[[[InitiateSignal builder] mergeFromData:data] build]; -} -+ (InitiateSignal*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (InitiateSignal*)[[[InitiateSignal builder] mergeFromData:data extensionRegistry:extensionRegistry] build]; -} -+ (InitiateSignal*) parseFromInputStream:(NSInputStream*) input { - return (InitiateSignal*)[[[InitiateSignal builder] mergeFromInputStream:input] build]; -} -+ (InitiateSignal*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (InitiateSignal*)[[[InitiateSignal builder] mergeFromInputStream:input extensionRegistry:extensionRegistry] build]; -} -+ (InitiateSignal*) parseFromCodedInputStream:(PBCodedInputStream*) input { - return (InitiateSignal*)[[[InitiateSignal builder] mergeFromCodedInputStream:input] build]; -} -+ (InitiateSignal*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (InitiateSignal*)[[[InitiateSignal builder] mergeFromCodedInputStream:input extensionRegistry:extensionRegistry] build]; -} -+ (InitiateSignalBuilder*) builder { - return [[InitiateSignalBuilder alloc] init]; -} -+ (InitiateSignalBuilder*) builderWithPrototype:(InitiateSignal*) prototype { - return [[InitiateSignal builder] mergeFrom:prototype]; -} -- (InitiateSignalBuilder*) builder { - return [InitiateSignal builder]; -} -- (InitiateSignalBuilder*) toBuilder { - return [InitiateSignal builderWithPrototype:self]; -} -- (void) writeDescriptionTo:(NSMutableString*) output withIndent:(NSString*) indent { - if (self.hasInitiator) { - [output appendFormat:@"%@%@: %@\n", indent, @"initiator", self.initiator]; - } - if (self.hasSessionId) { - [output appendFormat:@"%@%@: %@\n", indent, @"sessionId", [NSNumber numberWithLongLong:self.sessionId]]; - } - if (self.hasPort) { - [output appendFormat:@"%@%@: %@\n", indent, @"port", [NSNumber numberWithInteger:self.port]]; - } - if (self.hasServerName) { - [output appendFormat:@"%@%@: %@\n", indent, @"serverName", self.serverName]; - } - if (self.hasVersion) { - [output appendFormat:@"%@%@: %@\n", indent, @"version", [NSNumber numberWithInteger:self.version]]; - } - [self.unknownFields writeDescriptionTo:output withIndent:indent]; -} -- (BOOL) isEqual:(id)other { - if (other == self) { +- (BOOL)isInitialized { return YES; - } - if (![other isKindOfClass:[InitiateSignal class]]) { - return NO; - } - InitiateSignal *otherMessage = other; - return - self.hasInitiator == otherMessage.hasInitiator && - (!self.hasInitiator || [self.initiator isEqual:otherMessage.initiator]) && - self.hasSessionId == otherMessage.hasSessionId && - (!self.hasSessionId || self.sessionId == otherMessage.sessionId) && - self.hasPort == otherMessage.hasPort && - (!self.hasPort || self.port == otherMessage.port) && - self.hasServerName == otherMessage.hasServerName && - (!self.hasServerName || [self.serverName isEqual:otherMessage.serverName]) && - self.hasVersion == otherMessage.hasVersion && - (!self.hasVersion || self.version == otherMessage.version) && - (self.unknownFields == otherMessage.unknownFields || (self.unknownFields != nil && [self.unknownFields isEqual:otherMessage.unknownFields])); } -- (NSUInteger) hash { - __block NSUInteger hashCode = 7; - if (self.hasInitiator) { - hashCode = hashCode * 31 + [self.initiator hash]; - } - if (self.hasSessionId) { - hashCode = hashCode * 31 + [[NSNumber numberWithLongLong:self.sessionId] hash]; - } - if (self.hasPort) { - hashCode = hashCode * 31 + [[NSNumber numberWithInteger:self.port] hash]; - } - if (self.hasServerName) { - hashCode = hashCode * 31 + [self.serverName hash]; - } - if (self.hasVersion) { - hashCode = hashCode * 31 + [[NSNumber numberWithInteger:self.version] hash]; - } - hashCode = hashCode * 31 + [self.unknownFields hash]; - return hashCode; +- (void)writeToCodedOutputStream:(PBCodedOutputStream *)output { + if (self.hasInitiator) { + [output writeString:1 value:self.initiator]; + } + if (self.hasSessionId) { + [output writeUInt64:2 value:self.sessionId]; + } + if (self.hasPort) { + [output writeUInt32:3 value:self.port]; + } + if (self.hasServerName) { + [output writeString:4 value:self.serverName]; + } + if (self.hasVersion) { + [output writeUInt32:5 value:self.version]; + } + [self.unknownFields writeToCodedOutputStream:output]; +} +- (SInt32)serializedSize { + __block SInt32 size_ = memoizedSerializedSize; + if (size_ != -1) { + return size_; + } + + size_ = 0; + if (self.hasInitiator) { + size_ += computeStringSize(1, self.initiator); + } + if (self.hasSessionId) { + size_ += computeUInt64Size(2, self.sessionId); + } + if (self.hasPort) { + size_ += computeUInt32Size(3, self.port); + } + if (self.hasServerName) { + size_ += computeStringSize(4, self.serverName); + } + if (self.hasVersion) { + size_ += computeUInt32Size(5, self.version); + } + size_ += self.unknownFields.serializedSize; + memoizedSerializedSize = size_; + return size_; +} ++ (InitiateSignal *)parseFromData:(NSData *)data { + return (InitiateSignal *)[[[InitiateSignal builder] mergeFromData:data] build]; +} ++ (InitiateSignal *)parseFromData:(NSData *)data extensionRegistry:(PBExtensionRegistry *)extensionRegistry { + return (InitiateSignal *)[[[InitiateSignal builder] mergeFromData:data extensionRegistry:extensionRegistry] build]; +} ++ (InitiateSignal *)parseFromInputStream:(NSInputStream *)input { + return (InitiateSignal *)[[[InitiateSignal builder] mergeFromInputStream:input] build]; +} ++ (InitiateSignal *)parseFromInputStream:(NSInputStream *)input + extensionRegistry:(PBExtensionRegistry *)extensionRegistry { + return (InitiateSignal *)[[[InitiateSignal builder] mergeFromInputStream:input extensionRegistry:extensionRegistry] + build]; +} ++ (InitiateSignal *)parseFromCodedInputStream:(PBCodedInputStream *)input { + return (InitiateSignal *)[[[InitiateSignal builder] mergeFromCodedInputStream:input] build]; +} ++ (InitiateSignal *)parseFromCodedInputStream:(PBCodedInputStream *)input + extensionRegistry:(PBExtensionRegistry *)extensionRegistry { + return (InitiateSignal *)[ + [[InitiateSignal builder] mergeFromCodedInputStream:input extensionRegistry:extensionRegistry] build]; +} ++ (InitiateSignalBuilder *)builder { + return [[InitiateSignalBuilder alloc] init]; +} ++ (InitiateSignalBuilder *)builderWithPrototype:(InitiateSignal *)prototype { + return [[InitiateSignal builder] mergeFrom:prototype]; +} +- (InitiateSignalBuilder *)builder { + return [InitiateSignal builder]; +} +- (InitiateSignalBuilder *)toBuilder { + return [InitiateSignal builderWithPrototype:self]; +} +- (void)writeDescriptionTo:(NSMutableString *)output withIndent:(NSString *)indent { + if (self.hasInitiator) { + [output appendFormat:@"%@%@: %@\n", indent, @"initiator", self.initiator]; + } + if (self.hasSessionId) { + [output appendFormat:@"%@%@: %@\n", indent, @"sessionId", [NSNumber numberWithLongLong:self.sessionId]]; + } + if (self.hasPort) { + [output appendFormat:@"%@%@: %@\n", indent, @"port", [NSNumber numberWithInteger:self.port]]; + } + if (self.hasServerName) { + [output appendFormat:@"%@%@: %@\n", indent, @"serverName", self.serverName]; + } + if (self.hasVersion) { + [output appendFormat:@"%@%@: %@\n", indent, @"version", [NSNumber numberWithInteger:self.version]]; + } + [self.unknownFields writeDescriptionTo:output withIndent:indent]; +} +- (BOOL)isEqual:(id)other { + if (other == self) { + return YES; + } + if (![other isKindOfClass:[InitiateSignal class]]) { + return NO; + } + InitiateSignal *otherMessage = other; + return self.hasInitiator == otherMessage.hasInitiator && + (!self.hasInitiator || [self.initiator isEqual:otherMessage.initiator]) && + self.hasSessionId == otherMessage.hasSessionId && + (!self.hasSessionId || self.sessionId == otherMessage.sessionId) && self.hasPort == otherMessage.hasPort && + (!self.hasPort || self.port == otherMessage.port) && self.hasServerName == otherMessage.hasServerName && + (!self.hasServerName || [self.serverName isEqual:otherMessage.serverName]) && + self.hasVersion == otherMessage.hasVersion && (!self.hasVersion || self.version == otherMessage.version) && + (self.unknownFields == otherMessage.unknownFields || + (self.unknownFields != nil && [self.unknownFields isEqual:otherMessage.unknownFields])); +} +- (NSUInteger)hash { + __block NSUInteger hashCode = 7; + if (self.hasInitiator) { + hashCode = hashCode * 31 + [self.initiator hash]; + } + if (self.hasSessionId) { + hashCode = hashCode * 31 + [[NSNumber numberWithLongLong:self.sessionId] hash]; + } + if (self.hasPort) { + hashCode = hashCode * 31 + [[NSNumber numberWithInteger:self.port] hash]; + } + if (self.hasServerName) { + hashCode = hashCode * 31 + [self.serverName hash]; + } + if (self.hasVersion) { + hashCode = hashCode * 31 + [[NSNumber numberWithInteger:self.version] hash]; + } + hashCode = hashCode * 31 + [self.unknownFields hash]; + return hashCode; } @end -@interface InitiateSignalBuilder() -@property (strong) InitiateSignal* result; +@interface InitiateSignalBuilder () +@property (strong) InitiateSignal *result; @end @implementation InitiateSignalBuilder @synthesize result; -- (id) init { - if ((self = [super init])) { - self.result = [[InitiateSignal alloc] init]; - } - return self; -} -- (PBGeneratedMessage*) internalGetResult { - return result; -} -- (InitiateSignalBuilder*) clear { - self.result = [[InitiateSignal alloc] init]; - return self; -} -- (InitiateSignalBuilder*) clone { - return [InitiateSignal builderWithPrototype:result]; -} -- (InitiateSignal*) defaultInstance { - return [InitiateSignal defaultInstance]; -} -- (InitiateSignal*) build { - [self checkInitialized]; - return [self buildPartial]; -} -- (InitiateSignal*) buildPartial { - InitiateSignal* returnMe = result; - self.result = nil; - return returnMe; -} -- (InitiateSignalBuilder*) mergeFrom:(InitiateSignal*) other { - if (other == [InitiateSignal defaultInstance]) { - return self; - } - if (other.hasInitiator) { - [self setInitiator:other.initiator]; - } - if (other.hasSessionId) { - [self setSessionId:other.sessionId]; - } - if (other.hasPort) { - [self setPort:other.port]; - } - if (other.hasServerName) { - [self setServerName:other.serverName]; - } - if (other.hasVersion) { - [self setVersion:other.version]; - } - [self mergeUnknownFields:other.unknownFields]; - return self; -} -- (InitiateSignalBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input { - return [self mergeFromCodedInputStream:input extensionRegistry:[PBExtensionRegistry emptyRegistry]]; -} -- (InitiateSignalBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - PBUnknownFieldSetBuilder* unknownFields = [PBUnknownFieldSet builderWithUnknownFields:self.unknownFields]; - while (YES) { - SInt32 tag = [input readTag]; - switch (tag) { - case 0: - [self setUnknownFields:[unknownFields build]]; - return self; - default: { - if (![self parseUnknownField:input unknownFields:unknownFields extensionRegistry:extensionRegistry tag:tag]) { - [self setUnknownFields:[unknownFields build]]; - return self; - } - break; - } - case 10: { - [self setInitiator:[input readString]]; - break; - } - case 16: { - [self setSessionId:[input readUInt64]]; - break; - } - case 24: { - [self setPort:[input readUInt32]]; - break; - } - case 34: { - [self setServerName:[input readString]]; - break; - } - case 40: { - [self setVersion:[input readUInt32]]; - break; - } +- (id)init { + if ((self = [super init])) { + self.result = [[InitiateSignal alloc] init]; } - } + return self; } -- (BOOL) hasInitiator { - return result.hasInitiator; +- (PBGeneratedMessage *)internalGetResult { + return result; } -- (NSString*) initiator { - return result.initiator; +- (InitiateSignalBuilder *)clear { + self.result = [[InitiateSignal alloc] init]; + return self; } -- (InitiateSignalBuilder*) setInitiator:(NSString*) value { - result.hasInitiator = YES; - result.initiator = value; - return self; +- (InitiateSignalBuilder *)clone { + return [InitiateSignal builderWithPrototype:result]; } -- (InitiateSignalBuilder*) clearInitiator { - result.hasInitiator = NO; - result.initiator = @""; - return self; +- (InitiateSignal *)defaultInstance { + return [InitiateSignal defaultInstance]; } -- (BOOL) hasSessionId { - return result.hasSessionId; +- (InitiateSignal *)build { + [self checkInitialized]; + return [self buildPartial]; } -- (UInt64) sessionId { - return result.sessionId; +- (InitiateSignal *)buildPartial { + InitiateSignal *returnMe = result; + self.result = nil; + return returnMe; } -- (InitiateSignalBuilder*) setSessionId:(UInt64) value { - result.hasSessionId = YES; - result.sessionId = value; - return self; +- (InitiateSignalBuilder *)mergeFrom:(InitiateSignal *)other { + if (other == [InitiateSignal defaultInstance]) { + return self; + } + if (other.hasInitiator) { + [self setInitiator:other.initiator]; + } + if (other.hasSessionId) { + [self setSessionId:other.sessionId]; + } + if (other.hasPort) { + [self setPort:other.port]; + } + if (other.hasServerName) { + [self setServerName:other.serverName]; + } + if (other.hasVersion) { + [self setVersion:other.version]; + } + [self mergeUnknownFields:other.unknownFields]; + return self; } -- (InitiateSignalBuilder*) clearSessionId { - result.hasSessionId = NO; - result.sessionId = 0L; - return self; +- (InitiateSignalBuilder *)mergeFromCodedInputStream:(PBCodedInputStream *)input { + return [self mergeFromCodedInputStream:input extensionRegistry:[PBExtensionRegistry emptyRegistry]]; } -- (BOOL) hasPort { - return result.hasPort; +- (InitiateSignalBuilder *)mergeFromCodedInputStream:(PBCodedInputStream *)input + extensionRegistry:(PBExtensionRegistry *)extensionRegistry { + PBUnknownFieldSetBuilder *unknownFields = [PBUnknownFieldSet builderWithUnknownFields:self.unknownFields]; + while (YES) { + SInt32 tag = [input readTag]; + switch (tag) { + case 0: + [self setUnknownFields:[unknownFields build]]; + return self; + default: { + if (![self parseUnknownField:input + unknownFields:unknownFields + extensionRegistry:extensionRegistry + tag:tag]) { + [self setUnknownFields:[unknownFields build]]; + return self; + } + break; + } + case 10: { + [self setInitiator:[input readString]]; + break; + } + case 16: { + [self setSessionId:[input readUInt64]]; + break; + } + case 24: { + [self setPort:[input readUInt32]]; + break; + } + case 34: { + [self setServerName:[input readString]]; + break; + } + case 40: { + [self setVersion:[input readUInt32]]; + break; + } + } + } } -- (UInt32) port { - return result.port; +- (BOOL)hasInitiator { + return result.hasInitiator; } -- (InitiateSignalBuilder*) setPort:(UInt32) value { - result.hasPort = YES; - result.port = value; - return self; +- (NSString *)initiator { + return result.initiator; } -- (InitiateSignalBuilder*) clearPort { - result.hasPort = NO; - result.port = 0; - return self; +- (InitiateSignalBuilder *)setInitiator:(NSString *)value { + result.hasInitiator = YES; + result.initiator = value; + return self; } -- (BOOL) hasServerName { - return result.hasServerName; +- (InitiateSignalBuilder *)clearInitiator { + result.hasInitiator = NO; + result.initiator = @""; + return self; } -- (NSString*) serverName { - return result.serverName; +- (BOOL)hasSessionId { + return result.hasSessionId; } -- (InitiateSignalBuilder*) setServerName:(NSString*) value { - result.hasServerName = YES; - result.serverName = value; - return self; +- (UInt64)sessionId { + return result.sessionId; } -- (InitiateSignalBuilder*) clearServerName { - result.hasServerName = NO; - result.serverName = @""; - return self; +- (InitiateSignalBuilder *)setSessionId:(UInt64)value { + result.hasSessionId = YES; + result.sessionId = value; + return self; } -- (BOOL) hasVersion { - return result.hasVersion; +- (InitiateSignalBuilder *)clearSessionId { + result.hasSessionId = NO; + result.sessionId = 0L; + return self; } -- (UInt32) version { - return result.version; +- (BOOL)hasPort { + return result.hasPort; } -- (InitiateSignalBuilder*) setVersion:(UInt32) value { - result.hasVersion = YES; - result.version = value; - return self; +- (UInt32)port { + return result.port; } -- (InitiateSignalBuilder*) clearVersion { - result.hasVersion = NO; - result.version = 0; - return self; +- (InitiateSignalBuilder *)setPort:(UInt32)value { + result.hasPort = YES; + result.port = value; + return self; +} +- (InitiateSignalBuilder *)clearPort { + result.hasPort = NO; + result.port = 0; + return self; +} +- (BOOL)hasServerName { + return result.hasServerName; +} +- (NSString *)serverName { + return result.serverName; +} +- (InitiateSignalBuilder *)setServerName:(NSString *)value { + result.hasServerName = YES; + result.serverName = value; + return self; +} +- (InitiateSignalBuilder *)clearServerName { + result.hasServerName = NO; + result.serverName = @""; + return self; +} +- (BOOL)hasVersion { + return result.hasVersion; +} +- (UInt32)version { + return result.version; +} +- (InitiateSignalBuilder *)setVersion:(UInt32)value { + result.hasVersion = YES; + result.version = value; + return self; +} +- (InitiateSignalBuilder *)clearVersion { + result.hasVersion = NO; + result.version = 0; + return self; } @end diff --git a/Signal/src/phone/signaling/InitiatorSessionDescriptor.h b/Signal/src/phone/signaling/InitiatorSessionDescriptor.h index 83e055576..c1a7f2989 100644 --- a/Signal/src/phone/signaling/InitiatorSessionDescriptor.h +++ b/Signal/src/phone/signaling/InitiatorSessionDescriptor.h @@ -11,14 +11,14 @@ @property (nonatomic, readonly) in_port_t relayUdpPort; @property (nonatomic, readonly) int64_t sessionId; -@property (nonatomic, readonly) NSString* relayServerName; +@property (nonatomic, readonly) NSString *relayServerName; -+(InitiatorSessionDescriptor*) initiatorSessionDescriptorWithSessionId:(int64_t)sessionId - andRelayServerName:(NSString*)relayServerName - andRelayPort:(in_port_t)relayUdpPort; ++ (InitiatorSessionDescriptor *)initiatorSessionDescriptorWithSessionId:(int64_t)sessionId + andRelayServerName:(NSString *)relayServerName + andRelayPort:(in_port_t)relayUdpPort; -+(InitiatorSessionDescriptor*) initiatorSessionDescriptorFromJson:(NSString*)json; ++ (InitiatorSessionDescriptor *)initiatorSessionDescriptorFromJson:(NSString *)json; --(NSString*) toJson; +- (NSString *)toJson; @end diff --git a/Signal/src/phone/signaling/InitiatorSessionDescriptor.m b/Signal/src/phone/signaling/InitiatorSessionDescriptor.m index 8a6547110..2a11c8ff6 100644 --- a/Signal/src/phone/signaling/InitiatorSessionDescriptor.m +++ b/Signal/src/phone/signaling/InitiatorSessionDescriptor.m @@ -11,47 +11,50 @@ @synthesize relayUdpPort, relayServerName, sessionId; -+(InitiatorSessionDescriptor*) initiatorSessionDescriptorWithSessionId:(int64_t)sessionId andRelayServerName:(NSString*)relayServerName andRelayPort:(in_port_t)relayUdpPort { - require(relayServerName != nil); - require(relayUdpPort > 0); - InitiatorSessionDescriptor* d = [InitiatorSessionDescriptor new]; - d->sessionId = sessionId; - d->relayServerName = relayServerName; - d->relayUdpPort = relayUdpPort; ++ (InitiatorSessionDescriptor *)initiatorSessionDescriptorWithSessionId:(int64_t)sessionId + andRelayServerName:(NSString *)relayServerName + andRelayPort:(in_port_t)relayUdpPort { + ows_require(relayServerName != nil); + ows_require(relayUdpPort > 0); + InitiatorSessionDescriptor *d = [InitiatorSessionDescriptor new]; + d->sessionId = sessionId; + d->relayServerName = relayServerName; + d->relayUdpPort = relayUdpPort; return d; } -+(InitiatorSessionDescriptor*) initiatorSessionDescriptorFromJson:(NSString*)json { ++ (InitiatorSessionDescriptor *)initiatorSessionDescriptorFromJson:(NSString *)json { checkOperation(json != nil); - NSDictionary* fields = [json decodedAsJsonIntoDictionary]; - id jsonSessionId = fields[SessionIdKey]; - id jsonRelayPort = fields[RelayPortKey]; - id jsonRelayName = fields[RelayHostKey]; + NSDictionary *fields = [json decodedAsJsonIntoDictionary]; + id jsonSessionId = fields[SessionIdKey]; + id jsonRelayPort = fields[RelayPortKey]; + id jsonRelayName = fields[RelayHostKey]; checkOperationDescribe([jsonSessionId isKindOfClass:NSNumber.class], @"Unexpected json data"); checkOperationDescribe([jsonRelayPort isKindOfClass:NSNumber.class], @"Unexpected json data"); checkOperationDescribe([jsonRelayName isKindOfClass:NSString.class], @"Unexpected json data"); checkOperationDescribe([jsonRelayPort unsignedShortValue] > 0, @"Unexpected json data"); - - int64_t sessionId = [[jsonSessionId description] longLongValue]; // workaround: asking for longLongValue directly causes rounding-through-double + + int64_t sessionId = [[jsonSessionId description] + longLongValue]; // workaround: asking for longLongValue directly causes rounding-through-double in_port_t relayUdpPort = [jsonRelayPort unsignedShortValue]; return [InitiatorSessionDescriptor initiatorSessionDescriptorWithSessionId:sessionId - andRelayServerName:jsonRelayName - andRelayPort:relayUdpPort]; + andRelayServerName:jsonRelayName + andRelayPort:relayUdpPort]; } --(NSString*) toJson { - return [@{SessionIdKey : @(sessionId), +- (NSString *)toJson { + return + [@{ SessionIdKey : @(sessionId), RelayPortKey : @(relayUdpPort), - RelayHostKey : relayServerName - } encodedAsJson]; + RelayHostKey : relayServerName } encodedAsJson]; } --(NSString*) description { +- (NSString *)description { return [NSString stringWithFormat:@"relay name: %@, relay port: %d, session id: %llud", - relayServerName, - relayUdpPort, - sessionId]; + relayServerName, + relayUdpPort, + sessionId]; } @end diff --git a/Signal/src/phone/signaling/ResponderSessionDescriptor.h b/Signal/src/phone/signaling/ResponderSessionDescriptor.h index 40fa8669c..2e5baab39 100644 --- a/Signal/src/phone/signaling/ResponderSessionDescriptor.h +++ b/Signal/src/phone/signaling/ResponderSessionDescriptor.h @@ -5,24 +5,25 @@ /** * - * The ResponderSessionDescriptor class stores the information included in device notifications indicating an incoming call. + * The ResponderSessionDescriptor class stores the information included in device notifications indicating an incoming + * call. * It describes who is calling, which relay server to connect to, and what to tell the relay server. * */ @interface ResponderSessionDescriptor : NSObject -@property (nonatomic,readonly) NSUInteger interopVersion; -@property (nonatomic,readonly) in_port_t relayUdpPort; -@property (nonatomic,readonly) int64_t sessionId; -@property (nonatomic,readonly) NSString* relayServerName; -@property (nonatomic,readonly) PhoneNumber* initiatorNumber; +@property (nonatomic, readonly) NSUInteger interopVersion; +@property (nonatomic, readonly) in_port_t relayUdpPort; +@property (nonatomic, readonly) int64_t sessionId; +@property (nonatomic, readonly) NSString *relayServerName; +@property (nonatomic, readonly) PhoneNumber *initiatorNumber; -+(ResponderSessionDescriptor*)responderSessionDescriptorWithInteropVersion:(NSUInteger)interopVersion - andRelayUdpPort:(in_port_t)relayUdpPort - andSessionId:(int64_t)sessionId - andRelayServerName:(NSString*)relayServerName - andInitiatorNumber:(PhoneNumber*)initiatorNumber; ++ (ResponderSessionDescriptor *)responderSessionDescriptorWithInteropVersion:(NSUInteger)interopVersion + andRelayUdpPort:(in_port_t)relayUdpPort + andSessionId:(int64_t)sessionId + andRelayServerName:(NSString *)relayServerName + andInitiatorNumber:(PhoneNumber *)initiatorNumber; -+(ResponderSessionDescriptor*)responderSessionDescriptorFromEncryptedRemoteNotification:(NSDictionary*)remoteNotif; ++ (ResponderSessionDescriptor *)responderSessionDescriptorFromEncryptedRemoteNotification:(NSDictionary *)remoteNotif; @end diff --git a/Signal/src/phone/signaling/ResponderSessionDescriptor.m b/Signal/src/phone/signaling/ResponderSessionDescriptor.m index 64a0bfd01..6ee229024 100644 --- a/Signal/src/phone/signaling/ResponderSessionDescriptor.m +++ b/Signal/src/phone/signaling/ResponderSessionDescriptor.m @@ -2,18 +2,18 @@ #import "Constraints.h" #import "CryptoTools.h" -#import "Util.h" #import "InitiateSignal.pb.h" #import "SignalKeyingStorage.h" +#import "Util.h" #define MessagePropertyKey @"m" -#define RelayPortKey @"p" -#define SessionIdKey @"s" -#define RelayHostKey @"n" +#define RelayPortKey @"p" +#define SessionIdKey @"s" +#define RelayHostKey @"n" #define InitiatorNumberKey @"i" -#define VERSION_SIZE 1 -#define IV_SIZE 16 +#define VERSION_SIZE 1 +#define IV_SIZE 16 #define HMAC_TRUNCATED_SIZE 10 #define EXPECTED_REMOTE_NOTIF_FORMAT_VERSION 0 @@ -27,40 +27,40 @@ @synthesize initiatorNumber; @synthesize interopVersion; -+(ResponderSessionDescriptor*)responderSessionDescriptorWithInteropVersion:(NSUInteger)interopVersion - andRelayUdpPort:(in_port_t)relayUdpPort - andSessionId:(int64_t)sessionId - andRelayServerName:(NSString*)relayServerName - andInitiatorNumber:(PhoneNumber*)initiatorNumber { - require(relayUdpPort > 0); - require(relayServerName != nil); - require(initiatorNumber != nil); - - ResponderSessionDescriptor* rsd = [ResponderSessionDescriptor new]; ++ (ResponderSessionDescriptor *)responderSessionDescriptorWithInteropVersion:(NSUInteger)interopVersion + andRelayUdpPort:(in_port_t)relayUdpPort + andSessionId:(int64_t)sessionId + andRelayServerName:(NSString *)relayServerName + andInitiatorNumber:(PhoneNumber *)initiatorNumber { + ows_require(relayUdpPort > 0); + ows_require(relayServerName != nil); + ows_require(initiatorNumber != nil); + + ResponderSessionDescriptor *rsd = [ResponderSessionDescriptor new]; rsd->interopVersion = interopVersion; - rsd->relayUdpPort = relayUdpPort; - rsd->sessionId = sessionId; - rsd->relayServerName = relayServerName; - rsd->initiatorNumber = initiatorNumber; - + rsd->relayUdpPort = relayUdpPort; + rsd->sessionId = sessionId; + rsd->relayServerName = relayServerName; + rsd->initiatorNumber = initiatorNumber; + return rsd; } -+(ResponderSessionDescriptor*)responderSessionDescriptorFromEncryptedRemoteNotification:(NSDictionary*)remoteNotif { - require(remoteNotif != nil); - - NSString* message = remoteNotif[MessagePropertyKey]; ++ (ResponderSessionDescriptor *)responderSessionDescriptorFromEncryptedRemoteNotification:(NSDictionary *)remoteNotif { + ows_require(remoteNotif != nil); + + NSString *message = remoteNotif[MessagePropertyKey]; checkOperation(message != nil); - NSData* authenticatedPayload = [message decodedAsBase64Data]; + NSData *authenticatedPayload = [message decodedAsBase64Data]; checkOperation(authenticatedPayload.length > 0); uint8_t includedRemoteNotificationFormatVersion = [authenticatedPayload uint8At:0]; checkOperation(includedRemoteNotificationFormatVersion == EXPECTED_REMOTE_NOTIF_FORMAT_VERSION); - - NSData* encryptedPayload = [self verifyAndRemoveMacFromRemoteNotifcationData:authenticatedPayload]; - NSData* payload = [self decryptRemoteNotificationData:encryptedPayload]; - - InitiateSignal* parsedPayload = [InitiateSignal parseFromData:payload]; + + NSData *encryptedPayload = [self verifyAndRemoveMacFromRemoteNotifcationData:authenticatedPayload]; + NSData *payload = [self decryptRemoteNotificationData:encryptedPayload]; + + InitiateSignal *parsedPayload = [InitiateSignal parseFromData:payload]; in_port_t maxPort = (in_port_t)-1; assert(maxPort > 0); @@ -72,44 +72,44 @@ checkOperation(parsedPayload.serverName != nil); NSUInteger interopVersion = parsedPayload.version; - int64_t sessionId = (int64_t)parsedPayload.sessionId; - in_port_t relayUdpPort = (in_port_t)parsedPayload.port; - NSString* relayServerName = parsedPayload.serverName; - PhoneNumber* phoneNumber = [PhoneNumber phoneNumberFromE164:parsedPayload.initiator]; - + int64_t sessionId = (int64_t)parsedPayload.sessionId; + in_port_t relayUdpPort = (in_port_t)parsedPayload.port; + NSString *relayServerName = parsedPayload.serverName; + PhoneNumber *phoneNumber = [PhoneNumber phoneNumberFromE164:parsedPayload.initiator]; + return [ResponderSessionDescriptor responderSessionDescriptorWithInteropVersion:interopVersion andRelayUdpPort:relayUdpPort andSessionId:sessionId andRelayServerName:relayServerName andInitiatorNumber:phoneNumber]; } -+(NSData*) verifyAndRemoveMacFromRemoteNotifcationData:(NSData*)data { - require(data != nil); ++ (NSData *)verifyAndRemoveMacFromRemoteNotifcationData:(NSData *)data { + ows_require(data != nil); checkOperation(data.length >= HMAC_TRUNCATED_SIZE); - NSData* includedMac = [data takeLast:HMAC_TRUNCATED_SIZE]; - NSData* payload = [data skipLast:HMAC_TRUNCATED_SIZE]; - NSData* signalingMacKey = SignalKeyingStorage.signalingMacKey; - require(signalingMacKey != nil); - NSData* computedMac = [[payload hmacWithSha1WithKey:signalingMacKey] takeLast:HMAC_TRUNCATED_SIZE]; + NSData *includedMac = [data takeLast:HMAC_TRUNCATED_SIZE]; + NSData *payload = [data skipLast:HMAC_TRUNCATED_SIZE]; + NSData *signalingMacKey = SignalKeyingStorage.signalingMacKey; + ows_require(signalingMacKey != nil); + NSData *computedMac = [[payload hmacWithSha1WithKey:signalingMacKey] takeLast:HMAC_TRUNCATED_SIZE]; checkOperation([includedMac isEqualToData_TimingSafe:computedMac]); return payload; } -+(NSData*) decryptRemoteNotificationData:(NSData*)data { - require(data != nil); ++ (NSData *)decryptRemoteNotificationData:(NSData *)data { + ows_require(data != nil); checkOperation(data.length >= VERSION_SIZE + IV_SIZE); - NSData* cipherKey = SignalKeyingStorage.signalingCipherKey; - require(cipherKey != nil); - NSData* iv = [data subdataWithRange:NSMakeRange(VERSION_SIZE, IV_SIZE)]; - NSData* cipherText = [data skip:VERSION_SIZE+IV_SIZE]; + NSData *cipherKey = SignalKeyingStorage.signalingCipherKey; + ows_require(cipherKey != nil); + NSData *iv = [data subdataWithRange:NSMakeRange(VERSION_SIZE, IV_SIZE)]; + NSData *cipherText = [data skip:VERSION_SIZE + IV_SIZE]; return [cipherText decryptWithAesInCipherBlockChainingModeWithPkcs7PaddingWithKey:cipherKey andIv:iv]; } --(NSString*) description { +- (NSString *)description { return [NSString stringWithFormat:@"relay name: %@, relay port: %d, session id: %llud, interop version: %lu", - relayServerName, - relayUdpPort, - sessionId, - (unsigned long)interopVersion]; + relayServerName, + relayUdpPort, + sessionId, + (unsigned long)interopVersion]; } @end diff --git a/Signal/src/phone/signaling/SignalUtil.h b/Signal/src/phone/signaling/SignalUtil.h index 0810e94cb..01829962f 100644 --- a/Signal/src/phone/signaling/SignalUtil.h +++ b/Signal/src/phone/signaling/SignalUtil.h @@ -7,32 +7,32 @@ #define SIGNAL_STATUS_CODE_SERVER_MESSAGE 402 #define SIGNAL_STATUS_CODE_LOGIN_FAILED 401 -@interface HttpRequest(SignalUtil) +@interface HttpRequest (SignalUtil) --(bool) isKeepAlive; +- (bool)isKeepAlive; --(bool) isRingingForSession:(int64_t)targetSessionId; +- (bool)isRingingForSession:(int64_t)targetSessionId; --(bool) isHangupForSession:(int64_t)targetSessionId; +- (bool)isHangupForSession:(int64_t)targetSessionId; --(bool) isBusyForSession:(int64_t)targetSessionId; +- (bool)isBusyForSession:(int64_t)targetSessionId; -+(HttpRequest*) httpRequestToOpenPortWithSessionId:(int64_t)sessionId; ++ (HttpRequest *)httpRequestToOpenPortWithSessionId:(int64_t)sessionId; -+(HttpRequest*) httpRequestToInitiateToRemoteNumber:(PhoneNumber*)remoteNumber; ++ (HttpRequest *)httpRequestToInitiateToRemoteNumber:(PhoneNumber *)remoteNumber; -+(HttpRequest*) httpRequestToRingWithSessionId:(int64_t)sessionId; ++ (HttpRequest *)httpRequestToRingWithSessionId:(int64_t)sessionId; -+(HttpRequest*) httpRequestToSignalBusyWithSessionId:(int64_t)sessionId; ++ (HttpRequest *)httpRequestToSignalBusyWithSessionId:(int64_t)sessionId; -+(HttpRequest*) httpRequestToStartRegistrationOfPhoneNumber; ++ (HttpRequest *)httpRequestToStartRegistrationOfPhoneNumber; -+(HttpRequest*) httpRequestToStartRegistrationOfPhoneNumberWithVoice; ++ (HttpRequest *)httpRequestToStartRegistrationOfPhoneNumberWithVoice; -+(HttpRequest*) httpRequestToVerifyAccessToPhoneNumberWithChallenge:(NSString*)challenge; ++ (HttpRequest *)httpRequestToVerifyAccessToPhoneNumberWithChallenge:(NSString *)challenge; -+(HttpRequest*) httpRequestToRegisterForApnSignalingWithDeviceToken:(NSData*)deviceToken; ++ (HttpRequest *)httpRequestToRegisterForApnSignalingWithDeviceToken:(NSData *)deviceToken; -+(HttpRequest*) httpRequestForPhoneNumberDirectoryFilter; ++ (HttpRequest *)httpRequestForPhoneNumberDirectoryFilter; @end diff --git a/Signal/src/phone/signaling/SignalUtil.m b/Signal/src/phone/signaling/SignalUtil.m index ec1c7f1b7..1d726f2c5 100644 --- a/Signal/src/phone/signaling/SignalUtil.m +++ b/Signal/src/phone/signaling/SignalUtil.m @@ -1,8 +1,9 @@ #import "SignalUtil.h" +#import #import "Constraints.h" -#import "Util.h" #import "SignalKeyingStorage.h" +#import "Util.h" #define CLAIMED_INTEROP_VERSION_IN_INITIATE_SIGNAL 1 @@ -11,112 +12,112 @@ * Augments HttpRequest with utility methods related to interacting with signaling servers. * */ -@implementation HttpRequest(SignalUtil) +@implementation HttpRequest (SignalUtil) --(NSNumber*) tryGetSessionId { - if (![self.location hasPrefix:@"/session/"]) return nil; - - NSString* sessionIdText = [self.location substringFromIndex:@"/session/".length]; - sessionIdText = [sessionIdText stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet]; - NSNumber* sessionIdNumber = [sessionIdText tryParseAsDecimalNumber]; +- (NSNumber *)tryGetSessionId { + if (![self.location hasPrefix:@"/session/"]) + return nil; + + NSString *sessionIdText = [self.location substringFromIndex:@"/session/".length]; + sessionIdText = [sessionIdText stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet]; + NSNumber *sessionIdNumber = [sessionIdText tryParseAsDecimalNumber]; + + if (sessionIdNumber.hasLongLongValue) + return sessionIdNumber; - if (sessionIdNumber.hasLongLongValue) return sessionIdNumber; - return nil; } --(bool) isKeepAlive { +- (bool)isKeepAlive { return [self.method isEqualToString:@"GET"] && [self.location hasPrefix:@"/keepalive"]; } --(bool) isRingingForSession:(int64_t)targetSessionId { +- (bool)isRingingForSession:(int64_t)targetSessionId { NSNumber *sessionId = self.tryGetSessionId; - BOOL isMethod = [self.method isEqualToString:@"RING"]; - BOOL isSession = sessionId?[@(targetSessionId) isEqualToNumber:sessionId]:NO; - - return isMethod&&isSession; + BOOL isMethod = [self.method isEqualToString:@"RING"]; + BOOL isSession = sessionId ? [@(targetSessionId) isEqualToNumber:sessionId] : NO; + + return isMethod && isSession; } --(bool) isHangupForSession:(int64_t)targetSessionId { +- (bool)isHangupForSession:(int64_t)targetSessionId { NSNumber *sessionId = self.tryGetSessionId; - BOOL isMethod = [self.method isEqualToString:@"DELETE"]; - BOOL isSession = sessionId?[@(targetSessionId) isEqualToNumber:sessionId]:NO; - - return isMethod&&isSession; + BOOL isMethod = [self.method isEqualToString:@"DELETE"]; + BOOL isSession = sessionId ? [@(targetSessionId) isEqualToNumber:sessionId] : NO; + + return isMethod && isSession; } --(bool) isBusyForSession:(int64_t)targetSessionId { +- (bool)isBusyForSession:(int64_t)targetSessionId { NSNumber *sessionId = self.tryGetSessionId; - BOOL isMethod = [self.method isEqualToString:@"BUSY"]; - BOOL isSession = sessionId?[@(targetSessionId) isEqualToNumber:sessionId]:NO; - - return isMethod&&isSession; + BOOL isMethod = [self.method isEqualToString:@"BUSY"]; + BOOL isSession = sessionId ? [@(targetSessionId) isEqualToNumber:sessionId] : NO; + + return isMethod && isSession; } -+(HttpRequest*) httpRequestToOpenPortWithSessionId:(int64_t)sessionId { ++ (HttpRequest *)httpRequestToOpenPortWithSessionId:(int64_t)sessionId { return [HttpRequest httpRequestUnauthenticatedWithMethod:@"GET" andLocation:[NSString stringWithFormat:@"/open/%lld", sessionId]]; } -+(HttpRequest*) httpRequestToRingWithSessionId:(int64_t)sessionId { - return [HttpRequest httpRequestWithOtpAuthenticationAndMethod:@"RING" - andLocation:[NSString stringWithFormat:@"/session/%lld", sessionId]]; ++ (HttpRequest *)httpRequestToRingWithSessionId:(int64_t)sessionId { + return + [HttpRequest httpRequestWithOtpAuthenticationAndMethod:@"RING" + andLocation:[NSString stringWithFormat:@"/session/%lld", sessionId]]; } -+(HttpRequest*) httpRequestToSignalBusyWithSessionId:(int64_t)sessionId { - return [HttpRequest httpRequestWithOtpAuthenticationAndMethod:@"BUSY" - andLocation:[NSString stringWithFormat:@"/session/%lld", sessionId]]; ++ (HttpRequest *)httpRequestToSignalBusyWithSessionId:(int64_t)sessionId { + return + [HttpRequest httpRequestWithOtpAuthenticationAndMethod:@"BUSY" + andLocation:[NSString stringWithFormat:@"/session/%lld", sessionId]]; } -+(HttpRequest*) httpRequestToInitiateToRemoteNumber:(PhoneNumber*)remoteNumber { - require(remoteNumber != nil); - - NSString* formattedRemoteNumber = remoteNumber.toE164; - NSString* interopVersionInsert = CLAIMED_INTEROP_VERSION_IN_INITIATE_SIGNAL == 0 - ? @"" - : [NSString stringWithFormat:@"/%d", CLAIMED_INTEROP_VERSION_IN_INITIATE_SIGNAL]; ++ (HttpRequest *)httpRequestToInitiateToRemoteNumber:(PhoneNumber *)remoteNumber { + ows_require(remoteNumber != nil); + + NSString *formattedRemoteNumber = remoteNumber.toE164; + NSString *interopVersionInsert = + CLAIMED_INTEROP_VERSION_IN_INITIATE_SIGNAL == 0 + ? @"" + : [NSString stringWithFormat:@"/%d", CLAIMED_INTEROP_VERSION_IN_INITIATE_SIGNAL]; return [HttpRequest httpRequestWithOtpAuthenticationAndMethod:@"GET" andLocation:[NSString stringWithFormat:@"/session%@/%@", - interopVersionInsert, - formattedRemoteNumber]]; + interopVersionInsert, + formattedRemoteNumber]]; } -+(HttpRequest*) httpRequestToStartRegistrationOfPhoneNumber { - return [HttpRequest httpRequestWithBasicAuthenticationAndMethod:@"GET" - andLocation:@"/users/verification"]; ++ (HttpRequest *)httpRequestToStartRegistrationOfPhoneNumber { + return [HttpRequest httpRequestWithBasicAuthenticationAndMethod:@"GET" andLocation:@"/users/verification"]; } -+(HttpRequest*) httpRequestToStartRegistrationOfPhoneNumberWithVoice { - return [HttpRequest httpRequestWithBasicAuthenticationAndMethod:@"GET" - andLocation:@"/users/verification/voice"]; ++ (HttpRequest *)httpRequestToStartRegistrationOfPhoneNumberWithVoice { + return [HttpRequest httpRequestWithBasicAuthenticationAndMethod:@"GET" andLocation:@"/users/verification/voice"]; } -+(HttpRequest*) httpRequestToVerifyAccessToPhoneNumberWithChallenge:(NSString*)challenge { - require(challenge != nil); - - PhoneNumber* localPhoneNumber = SignalKeyingStorage.localNumber; - NSString* query = [NSString stringWithFormat:@"/users/verification/%@", localPhoneNumber.toE164]; ++ (HttpRequest *)httpRequestToVerifyAccessToPhoneNumberWithChallenge:(NSString *)challenge { + ows_require(challenge != nil); + + NSString *localPhoneNumber = [TSAccountManager localNumber]; + NSString *query = [NSString stringWithFormat:@"/users/verification/%@", localPhoneNumber]; [SignalKeyingStorage generateSignaling]; - - NSData* signalingCipherKey = SignalKeyingStorage.signalingCipherKey; - NSData* signalingMacKey = SignalKeyingStorage.signalingMacKey; - NSData* signalingExtraKeyData = SignalKeyingStorage.signalingExtraKey; - - NSString* encodedSignalingKey = @[signalingCipherKey, signalingMacKey, signalingExtraKeyData].ows_concatDatas.encodedAsBase64; - NSString* body = @{@"key" : encodedSignalingKey, @"challenge" : challenge}.encodedAsJson; - - return [HttpRequest httpRequestWithBasicAuthenticationAndMethod:@"PUT" - andLocation:query - andOptionalBody:body]; + + NSData *signalingCipherKey = SignalKeyingStorage.signalingCipherKey; + NSData *signalingMacKey = SignalKeyingStorage.signalingMacKey; + NSData *signalingExtraKeyData = SignalKeyingStorage.signalingExtraKey; + + NSString *encodedSignalingKey = + @[ signalingCipherKey, signalingMacKey, signalingExtraKeyData ].ows_concatDatas.encodedAsBase64; + NSString *body = @{ @"key" : encodedSignalingKey, @"challenge" : challenge }.encodedAsJson; + + return [HttpRequest httpRequestWithBasicAuthenticationAndMethod:@"PUT" andLocation:query andOptionalBody:body]; } -+(HttpRequest*) httpRequestToRegisterForApnSignalingWithDeviceToken:(NSData*)deviceToken { - require(deviceToken != nil); - - NSString* query = [NSString stringWithFormat:@"/apn/%@", deviceToken.encodedAsHexString]; - - return [HttpRequest httpRequestWithBasicAuthenticationAndMethod:@"PUT" - andLocation:query]; ++ (HttpRequest *)httpRequestToRegisterForApnSignalingWithDeviceToken:(NSData *)deviceToken { + ows_require(deviceToken != nil); + + NSString *query = [NSString stringWithFormat:@"/apn/%@", deviceToken.encodedAsHexString]; + + return [HttpRequest httpRequestWithBasicAuthenticationAndMethod:@"PUT" andLocation:query]; } -+(HttpRequest*) httpRequestForPhoneNumberDirectoryFilter { - return [HttpRequest httpRequestWithOtpAuthenticationAndMethod:@"GET" - andLocation:@"/users/directory"]; ++ (HttpRequest *)httpRequestForPhoneNumberDirectoryFilter { + return [HttpRequest httpRequestWithOtpAuthenticationAndMethod:@"GET" andLocation:@"/users/directory"]; } @end diff --git a/Signal/src/phone/signaling/number directory/GroupContactsResult.h b/Signal/src/phone/signaling/number directory/GroupContactsResult.h index f72ee4ea1..d1f6ecc3e 100644 --- a/Signal/src/phone/signaling/number directory/GroupContactsResult.h +++ b/Signal/src/phone/signaling/number directory/GroupContactsResult.h @@ -12,13 +12,13 @@ @interface GroupContactsResult : NSObject -- (instancetype)initWithMembersId:(NSArray*)memberIdentifiers without:(NSArray*)removeIds; +- (instancetype)initWithMembersId:(NSArray *)memberIdentifiers without:(NSArray *)removeIds; - (NSUInteger)numberOfMembers; -- (BOOL)isContactAtIndexPath:(NSIndexPath*)indexPath; +- (BOOL)isContactAtIndexPath:(NSIndexPath *)indexPath; -- (Contact*)contactForIndexPath:(NSIndexPath*)indexPath; -- (NSString*)identifierForIndexPath:(NSIndexPath*)indexPath; +- (Contact *)contactForIndexPath:(NSIndexPath *)indexPath; +- (NSString *)identifierForIndexPath:(NSIndexPath *)indexPath; @end diff --git a/Signal/src/phone/signaling/number directory/GroupContactsResult.m b/Signal/src/phone/signaling/number directory/GroupContactsResult.m index 31f20af71..588961d15 100644 --- a/Signal/src/phone/signaling/number directory/GroupContactsResult.m +++ b/Signal/src/phone/signaling/number directory/GroupContactsResult.m @@ -8,88 +8,89 @@ #import "GroupContactsResult.h" +#import #import "Contact.h" -#import "Environment.h" #import "ContactsManager.h" +#import "Environment.h" #import "SignalKeyingStorage.h" -@interface GroupContactsResult() +@interface GroupContactsResult () -@property NSMutableArray *unknownNumbers; -@property NSMutableArray *knownNumbers; +@property NSMutableArray *unknownNumbers; +@property NSMutableArray *knownNumbers; -@property NSMutableDictionary *associatedContactDict; +@property NSMutableDictionary *associatedContactDict; @end @implementation GroupContactsResult -- (instancetype)initWithMembersId:(NSArray*)memberIdentifiers without:(NSArray*)removeIds{ +- (instancetype)initWithMembersId:(NSArray *)memberIdentifiers without:(NSArray *)removeIds { self = [super init]; - + ContactsManager *manager = [Environment.getCurrent contactsManager]; - - NSMutableSet *remainingNumbers = [NSMutableSet setWithArray:memberIdentifiers]; - - NSMutableArray *knownNumbers = [NSMutableArray array]; + + NSMutableSet *remainingNumbers = [NSMutableSet setWithArray:memberIdentifiers]; + + NSMutableArray *knownNumbers = [NSMutableArray array]; NSMutableArray *associatedContacts = [NSMutableArray array]; - + for (NSString *identifier in memberIdentifiers) { - if([identifier isEqualToString:[SignalKeyingStorage.localNumber toE164]]) { + if ([identifier isEqualToString:[TSAccountManager localNumber]]) { // remove local number - + [remainingNumbers removeObject:identifier]; continue; } - - if (removeIds && [removeIds containsObject:identifier]){ - //Remove ids + + if (removeIds && [removeIds containsObject:identifier]) { + // Remove ids [remainingNumbers removeObject:identifier]; continue; } - + PhoneNumber *number = [PhoneNumber phoneNumberFromE164:identifier]; - + if (!number) { continue; } - + Contact *contact = [manager latestContactForPhoneNumber:number]; - + if (!contact) { continue; } - + [knownNumbers addObject:identifier]; [associatedContacts addObject:contact]; - + [remainingNumbers removeObject:identifier]; } - + _unknownNumbers = [NSMutableArray arrayWithArray:[remainingNumbers allObjects]]; [_unknownNumbers sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { - return [obj1 compare:obj2 options:0]; + return [obj1 compare:obj2 options:0]; }]; - - + + // Populate mapping dictionary. _associatedContactDict = [NSMutableDictionary dictionary]; - for (NSUInteger i = 0 ; i < [knownNumbers count]; i++) { + for (NSUInteger i = 0; i < [knownNumbers count]; i++) { NSString *identifier = [knownNumbers objectAtIndex:i]; - Contact *contact = [associatedContacts objectAtIndex:i]; - + Contact *contact = [associatedContacts objectAtIndex:i]; + [_associatedContactDict setObject:contact forKey:identifier]; } - + // Known Numbers _knownNumbers = [NSMutableArray arrayWithArray:knownNumbers]; [_knownNumbers sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { - Contact *contact1 = [_associatedContactDict objectForKey:obj1]; - Contact *contact2 = [_associatedContactDict objectForKey:obj2]; - - return [[manager class] contactComparator](contact1, contact2); + Contact *contact1 = [_associatedContactDict objectForKey:obj1]; + Contact *contact2 = [_associatedContactDict objectForKey:obj2]; + + return [[manager class] contactComparator](contact1, contact2); }]; - + return self; } @@ -97,7 +98,7 @@ return [self.knownNumbers count] + [self.unknownNumbers count]; } -- (BOOL)isContactAtIndexPath:(NSIndexPath*)indexPath { +- (BOOL)isContactAtIndexPath:(NSIndexPath *)indexPath { if ((NSUInteger)indexPath.row < [self.unknownNumbers count]) { return NO; } else { @@ -105,7 +106,7 @@ } } -- (Contact*)contactForIndexPath:(NSIndexPath*)indexPath { +- (Contact *)contactForIndexPath:(NSIndexPath *)indexPath { if ([self isContactAtIndexPath:indexPath]) { NSString *identifier = [_knownNumbers objectAtIndex:[self knownNumbersIndexForIndexPath:indexPath]]; return [_associatedContactDict objectForKey:identifier]; @@ -115,7 +116,7 @@ } } -- (NSString*)identifierForIndexPath:(NSIndexPath*)indexPath { +- (NSString *)identifierForIndexPath:(NSIndexPath *)indexPath { if ([self isContactAtIndexPath:indexPath]) { return [_knownNumbers objectAtIndex:[self knownNumbersIndexForIndexPath:indexPath]]; } else { @@ -123,9 +124,9 @@ } } -- (NSUInteger)knownNumbersIndexForIndexPath:(NSIndexPath*)indexPath { +- (NSUInteger)knownNumbersIndexForIndexPath:(NSIndexPath *)indexPath { NSAssert(((NSUInteger)indexPath.row >= [_unknownNumbers count]), @"Wrong index for known number"); - + return (NSUInteger)indexPath.row - [_unknownNumbers count]; } diff --git a/Signal/src/profiling/CategorizingLogger.h b/Signal/src/profiling/CategorizingLogger.h index 030ff487b..e9bcb9d94 100644 --- a/Signal/src/profiling/CategorizingLogger.h +++ b/Signal/src/profiling/CategorizingLogger.h @@ -2,12 +2,14 @@ #import "JitterQueue.h" #import "Logging.h" -@interface CategorizingLogger : NSObject { -@private NSMutableArray* callbacks; -@private NSMutableDictionary* indexDic; +@interface CategorizingLogger : NSObject { + @private + NSMutableArray *callbacks; + @private + NSMutableDictionary *indexDic; } -+(CategorizingLogger*) categorizingLogger; --(void) addLoggingCallback:(void(^)(NSString* category, id details, NSUInteger index))callback; ++ (CategorizingLogger *)categorizingLogger; +- (void)addLoggingCallback:(void (^)(NSString *category, id details, NSUInteger index))callback; @end diff --git a/Signal/src/profiling/CategorizingLogger.m b/Signal/src/profiling/CategorizingLogger.m index badfd9491..aae72b88c 100644 --- a/Signal/src/profiling/CategorizingLogger.m +++ b/Signal/src/profiling/CategorizingLogger.m @@ -1,78 +1,90 @@ -#import "CategorizingLogger.h" -#import "AnonymousOccurrenceLogger.h" #import "AnonymousConditionLogger.h" +#import "AnonymousOccurrenceLogger.h" #import "AnonymousValueLogger.h" +#import "CategorizingLogger.h" #import "LoggingUtil.h" @implementation CategorizingLogger -+(CategorizingLogger*) categorizingLogger { - CategorizingLogger* c = [CategorizingLogger new]; - c->callbacks = [NSMutableArray array]; - c->indexDic = [NSMutableDictionary dictionary]; ++ (CategorizingLogger *)categorizingLogger { + CategorizingLogger *c = [CategorizingLogger new]; + c->callbacks = [NSMutableArray array]; + c->indexDic = [NSMutableDictionary dictionary]; return c; } --(void) addLoggingCallback:(void(^)(NSString* category, id details, NSUInteger index))callback { +- (void)addLoggingCallback:(void (^)(NSString *category, id details, NSUInteger index))callback { [callbacks addObject:[callback copy]]; } --(void) log:(NSString*)category details:(id)details { - NSNumber* index = indexDic[category]; +- (void)log:(NSString *)category details:(id)details { + NSNumber *index = indexDic[category]; if (index == nil) { - index = @(indexDic.count); + index = @(indexDic.count); indexDic[category] = index; } NSUInteger x = [index unsignedIntegerValue]; - for (void (^callback)(NSString* category, id details, NSUInteger index) in callbacks) { + for (void (^callback)(NSString *category, id details, NSUInteger index) in callbacks) { callback(category, details, x); } } --(id) getValueLoggerForValue:(id)valueIdentity from:(id)sender { +- (id)getValueLoggerForValue:(id)valueIdentity from:(id)sender { id r = [AnonymousValueLogger anonymousValueLogger:^(double value) { - [self log:[NSString stringWithFormat:@"Value %@ from %@", valueIdentity, sender] details:@(value)]; + [self log:[NSString stringWithFormat:@"Value %@ from %@", valueIdentity, sender] details:@(value)]; }]; return [LoggingUtil throttleValueLogger:r discardingAfterEventForDuration:0.5]; } --(id) getOccurrenceLoggerForSender:(id)sender withKey:(NSString*)key { - id r = [AnonymousOccurrenceLogger anonymousOccurencyLoggerWithMarker:^(id details){ - [self log:[NSString stringWithFormat:@"Mark %@ from %@", key, sender] details:details]; +- (id)getOccurrenceLoggerForSender:(id)sender withKey:(NSString *)key { + id r = [AnonymousOccurrenceLogger anonymousOccurencyLoggerWithMarker:^(id details) { + [self log:[NSString stringWithFormat:@"Mark %@ from %@", key, sender] details:details]; }]; return [LoggingUtil throttleOccurrenceLogger:r discardingAfterEventForDuration:0.5]; } --(id) getConditionLoggerForSender:(id)sender { +- (id)getConditionLoggerForSender:(id)sender { return [AnonymousConditionLogger anonymousConditionLoggerWithLogNotice:^(NSString *text) { - [self log:[NSString stringWithFormat:@"Notice from %@", sender] details:text]; - } andLogWarning:^(NSString *text) { - [self log:[NSString stringWithFormat:@"Warning from %@", sender] details:text]; - } andLogError:^(NSString *text) { - [self log:[NSString stringWithFormat:@"Error from %@", sender] details:text]; - }]; + [self log:[NSString stringWithFormat:@"Notice from %@", sender] details:text]; + } + andLogWarning:^(NSString *text) { + [self log:[NSString stringWithFormat:@"Warning from %@", sender] details:text]; + } + andLogError:^(NSString *text) { + [self log:[NSString stringWithFormat:@"Error from %@", sender] details:text]; + }]; } --(id) jitterQueueNotificationReceiver { +- (id)jitterQueueNotificationReceiver { return self; } --(void) notifyCreated { +- (void)notifyCreated { [self log:@"JitterQueue created" details:nil]; } --(void) notifyArrival:(uint16_t)sequenceNumber { +- (void)notifyArrival:(uint16_t)sequenceNumber { [self log:@"JitterQueue arrival" details:[NSString stringWithFormat:@"sequence: %d", sequenceNumber]]; } --(void) notifyDequeue:(uint16_t)sequenceNumber withRemainingEnqueuedItemCount:(NSUInteger)remainingCount { - [self log:@"JitterQueue dequeue" details:[NSString stringWithFormat:@"sequence: %d, remaining: %lu", sequenceNumber, (unsigned long)remainingCount]]; +- (void)notifyDequeue:(uint16_t)sequenceNumber withRemainingEnqueuedItemCount:(NSUInteger)remainingCount { + [self log:@"JitterQueue dequeue" + details:[NSString + stringWithFormat:@"sequence: %d, remaining: %lu", sequenceNumber, (unsigned long)remainingCount]]; } --(void) notifyBadArrival:(uint16_t)sequenceNumber ofType:(enum JitterBadArrivalType)arrivalType { - [self log:@"JitterQueue bad arrival" details:[NSString stringWithFormat:@"sequence: %d, arrival type: %d", sequenceNumber, arrivalType]]; +- (void)notifyBadArrival:(uint16_t)sequenceNumber ofType:(enum JitterBadArrivalType)arrivalType { + [self log:@"JitterQueue bad arrival" + details:[NSString stringWithFormat:@"sequence: %d, arrival type: %d", sequenceNumber, arrivalType]]; } --(void) notifyBadDequeueOfType:(enum JitterBadDequeueType)type { +- (void)notifyBadDequeueOfType:(enum JitterBadDequeueType)type { [self log:@"JitterQueue bad dequeue" details:[NSString stringWithFormat:@"type: %d", type]]; } --(void) notifyResyncFrom:(uint16_t)oldReadHeadSequenceNumber to:(uint16_t)newReadHeadSequenceNumber { - [self log:@"JitterQueue resync" details:[NSString stringWithFormat:@"from: %d, to: %d", oldReadHeadSequenceNumber, newReadHeadSequenceNumber]]; +- (void)notifyResyncFrom:(uint16_t)oldReadHeadSequenceNumber to:(uint16_t)newReadHeadSequenceNumber { + [self log:@"JitterQueue resync" + details:[NSString stringWithFormat:@"from: %d, to: %d", oldReadHeadSequenceNumber, newReadHeadSequenceNumber]]; } --(void) notifyDiscardOverflow:(uint16_t)discardedSequenceNumber resyncingFrom:(uint16_t)oldReadHeadSequenceNumber to:(uint16_t)newReadHeadSequenceNumber { - [self log:@"JitterQueue discard overflow" details:[NSString stringWithFormat:@"discarded: %d, from: %d, to: %d", discardedSequenceNumber, oldReadHeadSequenceNumber, newReadHeadSequenceNumber]]; +- (void)notifyDiscardOverflow:(uint16_t)discardedSequenceNumber + resyncingFrom:(uint16_t)oldReadHeadSequenceNumber + to:(uint16_t)newReadHeadSequenceNumber { + [self log:@"JitterQueue discard overflow" + details:[NSString stringWithFormat:@"discarded: %d, from: %d, to: %d", + discardedSequenceNumber, + oldReadHeadSequenceNumber, + newReadHeadSequenceNumber]]; } @end diff --git a/Signal/src/profiling/DecayingSampleEstimator.h b/Signal/src/profiling/DecayingSampleEstimator.h index a78323964..7ad17cd1c 100644 --- a/Signal/src/profiling/DecayingSampleEstimator.h +++ b/Signal/src/profiling/DecayingSampleEstimator.h @@ -2,20 +2,25 @@ /// A sample estimate based on an exponential weighting of observed samples, favoring the latest samples. @interface DecayingSampleEstimator : NSObject { -@private double estimate; -@private double decayPerUnitSample; + @private + double estimate; + @private + double decayPerUnitSample; } -+(DecayingSampleEstimator*) decayingSampleEstimatorWithInitialEstimate:(double)initialEstimate andDecayPerUnitSample:(double)decayPerUnitSample; -+(DecayingSampleEstimator*) decayingSampleEstimatorWithInitialEstimate:(double)initialEstimate andDecayFactor:(double)decayFactor perNSamples:(double)decayPeriod; ++ (DecayingSampleEstimator *)decayingSampleEstimatorWithInitialEstimate:(double)initialEstimate + andDecayPerUnitSample:(double)decayPerUnitSample; ++ (DecayingSampleEstimator *)decayingSampleEstimatorWithInitialEstimate:(double)initialEstimate + andDecayFactor:(double)decayFactor + perNSamples:(double)decayPeriod; /// Decays the current estimate towards the given sample value, assuming a unit weighting. --(void) updateWithNextSample:(double)sampleValue; +- (void)updateWithNextSample:(double)sampleValue; /// Decays the current estimate towards the given sample value, with a given weighting. --(void) updateWithNextSample:(double)sampleValue withSampleWeight:(double)weight; +- (void)updateWithNextSample:(double)sampleValue withSampleWeight:(double)weight; --(double) currentEstimate; --(double) decayRatePerUnitSample; --(void) forceEstimateTo:(double)newEstimate; +- (double)currentEstimate; +- (double)decayRatePerUnitSample; +- (void)forceEstimateTo:(double)newEstimate; @end diff --git a/Signal/src/profiling/DecayingSampleEstimator.m b/Signal/src/profiling/DecayingSampleEstimator.m index c5d054929..f2fb8f50b 100644 --- a/Signal/src/profiling/DecayingSampleEstimator.m +++ b/Signal/src/profiling/DecayingSampleEstimator.m @@ -1,43 +1,48 @@ -#import "DecayingSampleEstimator.h" #import "Constraints.h" +#import "DecayingSampleEstimator.h" @implementation DecayingSampleEstimator -+(DecayingSampleEstimator*) decayingSampleEstimatorWithInitialEstimate:(double)initialEstimate andDecayPerUnitSample:(double)decayPerUnitSample { - require(decayPerUnitSample >= 0); - require(decayPerUnitSample <= 1); - DecayingSampleEstimator* d = [DecayingSampleEstimator new]; - d->estimate = initialEstimate; - d->decayPerUnitSample = decayPerUnitSample; ++ (DecayingSampleEstimator *)decayingSampleEstimatorWithInitialEstimate:(double)initialEstimate + andDecayPerUnitSample:(double)decayPerUnitSample { + ows_require(decayPerUnitSample >= 0); + ows_require(decayPerUnitSample <= 1); + DecayingSampleEstimator *d = [DecayingSampleEstimator new]; + d->estimate = initialEstimate; + d->decayPerUnitSample = decayPerUnitSample; return d; } -+(DecayingSampleEstimator*) decayingSampleEstimatorWithInitialEstimate:(double)initialEstimate andDecayFactor:(double)decayFactor perNSamples:(double)decayPeriod { - require(decayFactor >= 0); - require(decayFactor <= 1); - require(decayPeriod > 0); - double decayPerUnitSample = 1 - pow(1 - decayFactor, 1/decayPeriod); - return [DecayingSampleEstimator decayingSampleEstimatorWithInitialEstimate:initialEstimate andDecayPerUnitSample:decayPerUnitSample]; ++ (DecayingSampleEstimator *)decayingSampleEstimatorWithInitialEstimate:(double)initialEstimate + andDecayFactor:(double)decayFactor + perNSamples:(double)decayPeriod { + ows_require(decayFactor >= 0); + ows_require(decayFactor <= 1); + ows_require(decayPeriod > 0); + double decayPerUnitSample = 1 - pow(1 - decayFactor, 1 / decayPeriod); + return [DecayingSampleEstimator decayingSampleEstimatorWithInitialEstimate:initialEstimate + andDecayPerUnitSample:decayPerUnitSample]; } --(void) updateWithNextSample:(double)sampleValue { +- (void)updateWithNextSample:(double)sampleValue { estimate *= 1 - decayPerUnitSample; estimate += sampleValue * decayPerUnitSample; } --(void) updateWithNextSample:(double)sampleValue withSampleWeight:(double)weight { - require(weight >= 0); - if (weight == 0) return; - +- (void)updateWithNextSample:(double)sampleValue withSampleWeight:(double)weight { + ows_require(weight >= 0); + if (weight == 0) + return; + double decayPerWeightedSample = 1 - pow(1 - decayPerUnitSample, weight); estimate *= 1 - decayPerWeightedSample; estimate += sampleValue * decayPerWeightedSample; } --(double) currentEstimate { +- (double)currentEstimate { return estimate; } --(void) forceEstimateTo:(double)newEstimate { +- (void)forceEstimateTo:(double)newEstimate { estimate = newEstimate; } --(double) decayRatePerUnitSample { +- (double)decayRatePerUnitSample { return decayPerUnitSample; } diff --git a/Signal/src/profiling/EventWindow.h b/Signal/src/profiling/EventWindow.h index 05046b06c..4d1d17bc0 100644 --- a/Signal/src/profiling/EventWindow.h +++ b/Signal/src/profiling/EventWindow.h @@ -2,13 +2,16 @@ #import "PriorityQueue.h" @interface EventWindow : NSObject { -@private NSTimeInterval windowDuration; -@private PriorityQueue* events; -@private NSTimeInterval lastWindowEnding; + @private + NSTimeInterval windowDuration; + @private + PriorityQueue *events; + @private + NSTimeInterval lastWindowEnding; } -+(EventWindow*) eventWindowWithWindowDuration:(NSTimeInterval)windowDuration; --(void) addEventAtTime:(NSTimeInterval)eventTime; --(NSUInteger) countAfterRemovingEventsBeforeWindowEndingAt:(NSTimeInterval)endOfWindowTime; ++ (EventWindow *)eventWindowWithWindowDuration:(NSTimeInterval)windowDuration; +- (void)addEventAtTime:(NSTimeInterval)eventTime; +- (NSUInteger)countAfterRemovingEventsBeforeWindowEndingAt:(NSTimeInterval)endOfWindowTime; @end diff --git a/Signal/src/profiling/EventWindow.m b/Signal/src/profiling/EventWindow.m index 99f60f6c4..756d151e5 100644 --- a/Signal/src/profiling/EventWindow.m +++ b/Signal/src/profiling/EventWindow.m @@ -2,31 +2,31 @@ @implementation EventWindow -+(EventWindow*) eventWindowWithWindowDuration:(NSTimeInterval)windowDuration { - require(windowDuration >= 0); - - EventWindow* w = [EventWindow new]; ++ (EventWindow *)eventWindowWithWindowDuration:(NSTimeInterval)windowDuration { + ows_require(windowDuration >= 0); + + EventWindow *w = [EventWindow new]; w->windowDuration = windowDuration; - w->events = [PriorityQueue priorityQueueAscendingWithComparator:^NSComparisonResult(id obj1, id obj2) { - return [(NSNumber*)obj1 compare:(NSNumber*)obj2]; + w->events = [PriorityQueue priorityQueueAscendingWithComparator:^NSComparisonResult(id obj1, id obj2) { + return [(NSNumber *)obj1 compare:(NSNumber *)obj2]; }]; w->lastWindowEnding = -INFINITY; return w; } --(void) addEventAtTime:(NSTimeInterval)eventTime { +- (void)addEventAtTime:(NSTimeInterval)eventTime { [events enqueue:@(eventTime)]; } --(NSUInteger) countAfterRemovingEventsBeforeWindowEndingAt:(NSTimeInterval)endOfWindowTime { +- (NSUInteger)countAfterRemovingEventsBeforeWindowEndingAt:(NSTimeInterval)endOfWindowTime { // because values are removed, going backwards will give misleading results. // checking for this case so callers don't get silent bad results // includes a small leeway in case of non-monotonic time source or extended precision lose - requireState(endOfWindowTime >= lastWindowEnding-0.03); + requireState(endOfWindowTime >= lastWindowEnding - 0.03); lastWindowEnding = endOfWindowTime; - + NSTimeInterval startOfWindowTime = endOfWindowTime - windowDuration; - while(events.count > 0 && [events.peek doubleValue] < startOfWindowTime) { + while (events.count > 0 && [events.peek doubleValue] < startOfWindowTime) { [events dequeue]; } return events.count; diff --git a/Signal/src/profiling/LoggingUtil.h b/Signal/src/profiling/LoggingUtil.h index d0050dd28..cc5b8bcdd 100644 --- a/Signal/src/profiling/LoggingUtil.h +++ b/Signal/src/profiling/LoggingUtil.h @@ -1,15 +1,23 @@ #import -#import "Logging.h" #import "DecayingSampleEstimator.h" +#import "Logging.h" @interface LoggingUtil : NSObject -+(id) throttleValueLogger:(id)valueLogger discardingAfterEventForDuration:(NSTimeInterval)duration; -+(id) throttleOccurrenceLogger:(id)occurrenceLogger discardingAfterEventForDuration:(NSTimeInterval)duration; -+(id) getAccumulatingValueLoggerTo:(id)logging named:(id)valueIdentity from:(id)sender; -+(id) getDifferenceValueLoggerTo:(id)logging named:(id)valueIdentity from:(id)sender; -+(id) getAveragingValueLoggerTo:(id)logging named:(id)valueIdentity from:(id)sender; -+(id) getValueEstimateLoggerTo:(id)logging named:(id)valueIdentity from:(id)sender withEstimator:(DecayingSampleEstimator*)estimator; -+(id) getMagnitudeDecayingToZeroValueLoggerTo:(id)logging named:(id)valueIdentity from:(id)sender withDecayFactor:(double)decayFactorPerSample; ++ (id)throttleValueLogger:(id)valueLogger + discardingAfterEventForDuration:(NSTimeInterval)duration; ++ (id)throttleOccurrenceLogger:(id)occurrenceLogger + discardingAfterEventForDuration:(NSTimeInterval)duration; ++ (id)getAccumulatingValueLoggerTo:(id)logging named:(id)valueIdentity from:(id)sender; ++ (id)getDifferenceValueLoggerTo:(id)logging named:(id)valueIdentity from:(id)sender; ++ (id)getAveragingValueLoggerTo:(id)logging named:(id)valueIdentity from:(id)sender; ++ (id)getValueEstimateLoggerTo:(id)logging + named:(id)valueIdentity + from:(id)sender + withEstimator:(DecayingSampleEstimator *)estimator; ++ (id)getMagnitudeDecayingToZeroValueLoggerTo:(id)logging + named:(id)valueIdentity + from:(id)sender + withDecayFactor:(double)decayFactorPerSample; @end diff --git a/Signal/src/profiling/LoggingUtil.m b/Signal/src/profiling/LoggingUtil.m index 0f607add7..453126766 100644 --- a/Signal/src/profiling/LoggingUtil.m +++ b/Signal/src/profiling/LoggingUtil.m @@ -1,80 +1,90 @@ -#import "LoggingUtil.h" -#import "AnonymousValueLogger.h" #import "AnonymousOccurrenceLogger.h" +#import "AnonymousValueLogger.h" #import "Constraints.h" +#import "LoggingUtil.h" #import "TimeUtil.h" @implementation LoggingUtil -+(id) throttleValueLogger:(id)valueLogger discardingAfterEventForDuration:(NSTimeInterval)duration { ++ (id)throttleValueLogger:(id)valueLogger + discardingAfterEventForDuration:(NSTimeInterval)duration { __block NSTimeInterval t = [TimeUtil time] - duration; return [AnonymousValueLogger anonymousValueLogger:^(double value) { - double t2 = [TimeUtil time]; - if (t2 - duration < t) return; - t = t2; - - [valueLogger logValue:value]; + double t2 = [TimeUtil time]; + if (t2 - duration < t) + return; + t = t2; + + [valueLogger logValue:value]; }]; } -+(id) throttleOccurrenceLogger:(id)occurrenceLogger discardingAfterEventForDuration:(NSTimeInterval)duration { ++ (id)throttleOccurrenceLogger:(id)occurrenceLogger + discardingAfterEventForDuration:(NSTimeInterval)duration { __block NSTimeInterval t = [TimeUtil time] - duration; return [AnonymousOccurrenceLogger anonymousOccurencyLoggerWithMarker:^(id details) { - double t2 = [TimeUtil time]; - if (t2 - duration < t) return; - t = t2; - - [occurrenceLogger markOccurrence:details]; + double t2 = [TimeUtil time]; + if (t2 - duration < t) + return; + t = t2; + + [occurrenceLogger markOccurrence:details]; }]; } -+(id) getAccumulatingValueLoggerTo:(id)logging named:(id)valueIdentity from:(id)sender { ++ (id)getAccumulatingValueLoggerTo:(id)logging named:(id)valueIdentity from:(id)sender { __block double total = 0.0; id norm = [logging getValueLoggerForValue:valueIdentity from:sender]; return [AnonymousValueLogger anonymousValueLogger:^(double value) { - total += value; - [norm logValue:total]; + total += value; + [norm logValue:total]; }]; } -+(id) getDifferenceValueLoggerTo:(id)logging named:(id)valueIdentity from:(id)sender { - __block double previous = 0.0; ++ (id)getDifferenceValueLoggerTo:(id)logging named:(id)valueIdentity from:(id)sender { + __block double previous = 0.0; __block bool hasPrevious = false; - id norm = [logging getValueLoggerForValue:valueIdentity from:sender]; + id norm = [logging getValueLoggerForValue:valueIdentity from:sender]; return [AnonymousValueLogger anonymousValueLogger:^(double value) { - double d = value - previous; - previous = value; - if (hasPrevious) { - [norm logValue:d]; - } - hasPrevious = true; + double d = value - previous; + previous = value; + if (hasPrevious) { + [norm logValue:d]; + } + hasPrevious = true; }]; } -+(id) getAveragingValueLoggerTo:(id)logging named:(id)valueIdentity from:(id)sender { - __block double total = 0.0; ++ (id)getAveragingValueLoggerTo:(id)logging named:(id)valueIdentity from:(id)sender { + __block double total = 0.0; __block NSUInteger count = 0; - id norm = [logging getValueLoggerForValue:valueIdentity from:sender]; + id norm = [logging getValueLoggerForValue:valueIdentity from:sender]; return [AnonymousValueLogger anonymousValueLogger:^(double value) { - total += value; - count += 1; - [norm logValue:total/count]; + total += value; + count += 1; + [norm logValue:total / count]; }]; } -+(id) getValueEstimateLoggerTo:(id)logging named:(id)valueIdentity from:(id)sender withEstimator:(DecayingSampleEstimator*)estimator { - require(estimator != nil); ++ (id)getValueEstimateLoggerTo:(id)logging + named:(id)valueIdentity + from:(id)sender + withEstimator:(DecayingSampleEstimator *)estimator { + ows_require(estimator != nil); id norm = [logging getValueLoggerForValue:valueIdentity from:sender]; return [AnonymousValueLogger anonymousValueLogger:^(double value) { - [estimator updateWithNextSample:value]; - [norm logValue:estimator.currentEstimate]; + [estimator updateWithNextSample:value]; + [norm logValue:estimator.currentEstimate]; }]; } -+(id) getMagnitudeDecayingToZeroValueLoggerTo:(id)logging named:(id)valueIdentity from:(id)sender withDecayFactor:(double)decayFactorPerSample { - require(decayFactorPerSample <= 1); - require(decayFactorPerSample >= 0); ++ (id)getMagnitudeDecayingToZeroValueLoggerTo:(id)logging + named:(id)valueIdentity + from:(id)sender + withDecayFactor:(double)decayFactorPerSample { + ows_require(decayFactorPerSample <= 1); + ows_require(decayFactorPerSample >= 0); __block double decayingEstimate = 0.0; - id norm = [logging getValueLoggerForValue:valueIdentity from:sender]; + id norm = [logging getValueLoggerForValue:valueIdentity from:sender]; return [AnonymousValueLogger anonymousValueLogger:^(double value) { - value = ABS(value); - decayingEstimate = MAX(value, decayingEstimate*decayFactorPerSample); - [norm logValue:decayingEstimate]; + value = ABS(value); + decayingEstimate = MAX(value, decayingEstimate * decayFactorPerSample); + [norm logValue:decayingEstimate]; }]; } diff --git a/Signal/src/profiling/protocols/ConditionLogger.h b/Signal/src/profiling/protocols/ConditionLogger.h index 3c2424cea..29caba2e8 100644 --- a/Signal/src/profiling/protocols/ConditionLogger.h +++ b/Signal/src/profiling/protocols/ConditionLogger.h @@ -1,7 +1,7 @@ #import @protocol ConditionLogger --(void) logNotice:(id)details; --(void) logWarning:(id)details; --(void) logError:(id)details; +- (void)logNotice:(id)details; +- (void)logWarning:(id)details; +- (void)logError:(id)details; @end diff --git a/Signal/src/profiling/protocols/Logging.h b/Signal/src/profiling/protocols/Logging.h index 9fc52713c..3368a3b38 100644 --- a/Signal/src/profiling/protocols/Logging.h +++ b/Signal/src/profiling/protocols/Logging.h @@ -1,20 +1,23 @@ #import -#import "OccurrenceLogger.h" #import "ConditionLogger.h" +#import "OccurrenceLogger.h" #import "ValueLogger.h" @protocol JitterQueueNotificationReceiver; @protocol Logging -/// Note: the logger MUST NOT store a reference to the given sender. Calling this method, or storing its result, must not create a reference cycle. --(id) getOccurrenceLoggerForSender:(id)sender withKey:(NSString*)key; +/// Note: the logger MUST NOT store a reference to the given sender. Calling this method, or storing its result, must +/// not create a reference cycle. +- (id)getOccurrenceLoggerForSender:(id)sender withKey:(NSString *)key; -/// Note: the logger MUST NOT store a reference to the given sender. Calling this method, or storing its result, must not create a reference cycle. --(id) getConditionLoggerForSender:(id)sender; +/// Note: the logger MUST NOT store a reference to the given sender. Calling this method, or storing its result, must +/// not create a reference cycle. +- (id)getConditionLoggerForSender:(id)sender; -/// Note: the logger MUST NOT store a reference to the given sender. Calling this method, or storing its result, must not create a reference cycle. --(id) getValueLoggerForValue:(id)valueIdentity from:(id)sender; +/// Note: the logger MUST NOT store a reference to the given sender. Calling this method, or storing its result, must +/// not create a reference cycle. +- (id)getValueLoggerForValue:(id)valueIdentity from:(id)sender; --(id) jitterQueueNotificationReceiver; +- (id)jitterQueueNotificationReceiver; @end diff --git a/Signal/src/profiling/protocols/OccurrenceLogger.h b/Signal/src/profiling/protocols/OccurrenceLogger.h index ad3a17557..e08ce74ec 100644 --- a/Signal/src/profiling/protocols/OccurrenceLogger.h +++ b/Signal/src/profiling/protocols/OccurrenceLogger.h @@ -1,5 +1,5 @@ #import @protocol OccurrenceLogger --(void) markOccurrence:(id)details; +- (void)markOccurrence:(id)details; @end diff --git a/Signal/src/profiling/protocols/ValueLogger.h b/Signal/src/profiling/protocols/ValueLogger.h index c2fda5fd1..f398bbde9 100644 --- a/Signal/src/profiling/protocols/ValueLogger.h +++ b/Signal/src/profiling/protocols/ValueLogger.h @@ -2,6 +2,6 @@ @protocol ValueLogger --(void) logValue:(double)value; +- (void)logValue:(double)value; @end diff --git a/Signal/src/profiling/protocols/utilities/AnonymousConditionLogger.h b/Signal/src/profiling/protocols/utilities/AnonymousConditionLogger.h index 40409f791..5b0e044b2 100644 --- a/Signal/src/profiling/protocols/utilities/AnonymousConditionLogger.h +++ b/Signal/src/profiling/protocols/utilities/AnonymousConditionLogger.h @@ -1,12 +1,14 @@ #import #import "ConditionLogger.h" -@interface AnonymousConditionLogger : NSObject +@interface AnonymousConditionLogger : NSObject -@property (nonatomic,readonly,copy) void (^logNoticeBlock)(id details); -@property (nonatomic,readonly,copy) void (^logWarningBlock)(id details); -@property (nonatomic,readonly,copy) void (^logErrorBlock)(id details); +@property (nonatomic, readonly, copy) void (^logNoticeBlock)(id details); +@property (nonatomic, readonly, copy) void (^logWarningBlock)(id details); +@property (nonatomic, readonly, copy) void (^logErrorBlock)(id details); -+(AnonymousConditionLogger*) anonymousConditionLoggerWithLogNotice:(void(^)(id details))logNotice andLogWarning:(void(^)(id details))logWarning andLogError:(void(^)(id details))logError; ++ (AnonymousConditionLogger *)anonymousConditionLoggerWithLogNotice:(void (^)(id details))logNotice + andLogWarning:(void (^)(id details))logWarning + andLogError:(void (^)(id details))logError; @end diff --git a/Signal/src/profiling/protocols/utilities/AnonymousConditionLogger.m b/Signal/src/profiling/protocols/utilities/AnonymousConditionLogger.m index ae6bfefd0..1cb5a2a25 100644 --- a/Signal/src/profiling/protocols/utilities/AnonymousConditionLogger.m +++ b/Signal/src/profiling/protocols/utilities/AnonymousConditionLogger.m @@ -3,25 +3,27 @@ @implementation AnonymousConditionLogger -+(AnonymousConditionLogger*) anonymousConditionLoggerWithLogNotice:(void(^)(id details))logNotice andLogWarning:(void(^)(id details))logWarning andLogError:(void(^)(id details))logError { - require(logNotice != nil); - require(logWarning != nil); - require(logError != nil); - - AnonymousConditionLogger* a = [AnonymousConditionLogger new]; - a->_logErrorBlock = logError; - a->_logWarningBlock = logWarning; - a->_logNoticeBlock = logNotice; ++ (AnonymousConditionLogger *)anonymousConditionLoggerWithLogNotice:(void (^)(id details))logNotice + andLogWarning:(void (^)(id details))logWarning + andLogError:(void (^)(id details))logError { + ows_require(logNotice != nil); + ows_require(logWarning != nil); + ows_require(logError != nil); + + AnonymousConditionLogger *a = [AnonymousConditionLogger new]; + a->_logErrorBlock = logError; + a->_logWarningBlock = logWarning; + a->_logNoticeBlock = logNotice; return a; } --(void) logError:(id)details { +- (void)logError:(id)details { _logErrorBlock(details); } --(void) logWarning:(id)details { +- (void)logWarning:(id)details { _logWarningBlock(details); } --(void) logNotice:(id)details { +- (void)logNotice:(id)details { _logNoticeBlock(details); } diff --git a/Signal/src/profiling/protocols/utilities/AnonymousOccurrenceLogger.h b/Signal/src/profiling/protocols/utilities/AnonymousOccurrenceLogger.h index 43092e17c..23ac458e1 100644 --- a/Signal/src/profiling/protocols/utilities/AnonymousOccurrenceLogger.h +++ b/Signal/src/profiling/protocols/utilities/AnonymousOccurrenceLogger.h @@ -1,10 +1,10 @@ #import #import "OccurrenceLogger.h" -@interface AnonymousOccurrenceLogger : NSObject +@interface AnonymousOccurrenceLogger : NSObject -@property (readonly,nonatomic,copy) void (^marker)(id details); +@property (readonly, nonatomic, copy) void (^marker)(id details); -+(AnonymousOccurrenceLogger*) anonymousOccurencyLoggerWithMarker:(void(^)(id details))marker; ++ (AnonymousOccurrenceLogger *)anonymousOccurencyLoggerWithMarker:(void (^)(id details))marker; @end diff --git a/Signal/src/profiling/protocols/utilities/AnonymousOccurrenceLogger.m b/Signal/src/profiling/protocols/utilities/AnonymousOccurrenceLogger.m index 8d1fbf644..25d995ea6 100644 --- a/Signal/src/profiling/protocols/utilities/AnonymousOccurrenceLogger.m +++ b/Signal/src/profiling/protocols/utilities/AnonymousOccurrenceLogger.m @@ -3,14 +3,14 @@ @implementation AnonymousOccurrenceLogger -+(AnonymousOccurrenceLogger*) anonymousOccurencyLoggerWithMarker:(void(^)(id details))marker { - require(marker != nil); - AnonymousOccurrenceLogger* a = [AnonymousOccurrenceLogger new]; - a->_marker = marker; ++ (AnonymousOccurrenceLogger *)anonymousOccurencyLoggerWithMarker:(void (^)(id details))marker { + ows_require(marker != nil); + AnonymousOccurrenceLogger *a = [AnonymousOccurrenceLogger new]; + a->_marker = marker; return a; } --(void) markOccurrence:(id)details { +- (void)markOccurrence:(id)details { _marker(details); } diff --git a/Signal/src/profiling/protocols/utilities/AnonymousValueLogger.h b/Signal/src/profiling/protocols/utilities/AnonymousValueLogger.h index 8127a078e..9aff7d661 100644 --- a/Signal/src/profiling/protocols/utilities/AnonymousValueLogger.h +++ b/Signal/src/profiling/protocols/utilities/AnonymousValueLogger.h @@ -1,10 +1,10 @@ #import #import "ValueLogger.h" -@interface AnonymousValueLogger : NSObject +@interface AnonymousValueLogger : NSObject -@property (nonatomic,readonly,copy) void (^logValueBlock)(double value); +@property (nonatomic, readonly, copy) void (^logValueBlock)(double value); -+(AnonymousValueLogger*) anonymousValueLogger:(void(^)(double value))logValue; ++ (AnonymousValueLogger *)anonymousValueLogger:(void (^)(double value))logValue; @end diff --git a/Signal/src/profiling/protocols/utilities/AnonymousValueLogger.m b/Signal/src/profiling/protocols/utilities/AnonymousValueLogger.m index 4f8e90a0b..cf72ccc6d 100644 --- a/Signal/src/profiling/protocols/utilities/AnonymousValueLogger.m +++ b/Signal/src/profiling/protocols/utilities/AnonymousValueLogger.m @@ -3,14 +3,14 @@ @implementation AnonymousValueLogger -+(AnonymousValueLogger*) anonymousValueLogger:(void(^)(double value))logValue { - require(logValue != nil); - AnonymousValueLogger* a = [AnonymousValueLogger new]; - a->_logValueBlock = logValue; ++ (AnonymousValueLogger *)anonymousValueLogger:(void (^)(double value))logValue { + ows_require(logValue != nil); + AnonymousValueLogger *a = [AnonymousValueLogger new]; + a->_logValueBlock = logValue; return a; } --(void) logValue:(double)value { +- (void)logValue:(double)value { _logValueBlock(value); } diff --git a/Signal/src/profiling/protocols/utilities/DiscardingLog.h b/Signal/src/profiling/protocols/utilities/DiscardingLog.h index 4e7b90015..0b8f92ed7 100644 --- a/Signal/src/profiling/protocols/utilities/DiscardingLog.h +++ b/Signal/src/profiling/protocols/utilities/DiscardingLog.h @@ -1,8 +1,9 @@ #import -#import "Logging.h" #import "ConditionLogger.h" #import "JitterQueue.h" +#import "Logging.h" -@interface DiscardingLog : NSObject -+(DiscardingLog*) discardingLog; +@interface DiscardingLog + : NSObject ++ (DiscardingLog *)discardingLog; @end diff --git a/Signal/src/profiling/protocols/utilities/DiscardingLog.m b/Signal/src/profiling/protocols/utilities/DiscardingLog.m index 175eeedcb..3b5c85887 100644 --- a/Signal/src/profiling/protocols/utilities/DiscardingLog.m +++ b/Signal/src/profiling/protocols/utilities/DiscardingLog.m @@ -1,44 +1,46 @@ #import "DiscardingLog.h" @implementation DiscardingLog -+(DiscardingLog*) discardingLog { ++ (DiscardingLog *)discardingLog { return [DiscardingLog new]; } --(id) getOccurrenceLoggerForSender:(id)sender withKey:(NSString *)key { +- (id)getOccurrenceLoggerForSender:(id)sender withKey:(NSString *)key { return self; } --(id) getConditionLoggerForSender:(id)sender { +- (id)getConditionLoggerForSender:(id)sender { return self; } --(id) jitterQueueNotificationReceiver { +- (id)jitterQueueNotificationReceiver { return self; } --(id) getValueLoggerForValue:(id)valueIdentity from:(id)sender { +- (id)getValueLoggerForValue:(id)valueIdentity from:(id)sender { return self; } --(void) logValue:(double)value { +- (void)logValue:(double)value { } --(void) markOccurrence:(id)details { +- (void)markOccurrence:(id)details { } --(void) logError:(NSString *)text { +- (void)logError:(NSString *)text { } --(void) logNotice:(NSString *)text { +- (void)logNotice:(NSString *)text { } --(void) logWarning:(NSString *)text { +- (void)logWarning:(NSString *)text { } --(void) notifyArrival:(uint16_t)sequenceNumber { +- (void)notifyArrival:(uint16_t)sequenceNumber { } --(void) notifyDequeue:(uint16_t)sequenceNumber withRemainingEnqueuedItemCount:(NSUInteger)remainingCount { +- (void)notifyDequeue:(uint16_t)sequenceNumber withRemainingEnqueuedItemCount:(NSUInteger)remainingCount { } --(void) notifyBadArrival:(uint16_t)sequenceNumber ofType:(enum JitterBadArrivalType)arrivalType { +- (void)notifyBadArrival:(uint16_t)sequenceNumber ofType:(enum JitterBadArrivalType)arrivalType { } --(void) notifyBadDequeueOfType:(enum JitterBadDequeueType)type { +- (void)notifyBadDequeueOfType:(enum JitterBadDequeueType)type { } --(void) notifyResyncFrom:(uint16_t)oldReadHeadSequenceNumber to:(uint16_t)newReadHeadSequenceNumber { +- (void)notifyResyncFrom:(uint16_t)oldReadHeadSequenceNumber to:(uint16_t)newReadHeadSequenceNumber { } --(void) notifyDiscardOverflow:(uint16_t)discardedSequenceNumber resyncingFrom:(uint16_t)oldReadHeadSequenceNumber to:(uint16_t)newReadHeadSequenceNumber { +- (void)notifyDiscardOverflow:(uint16_t)discardedSequenceNumber + resyncingFrom:(uint16_t)oldReadHeadSequenceNumber + to:(uint16_t)newReadHeadSequenceNumber { } @end diff --git a/Signal/src/textsecure/Account/TSAccountManager.h b/Signal/src/textsecure/Account/TSAccountManager.h deleted file mode 100644 index c5923365c..000000000 --- a/Signal/src/textsecure/Account/TSAccountManager.h +++ /dev/null @@ -1,79 +0,0 @@ -// -// TSAccountManagement.h -// TextSecureKit -// -// Created by Frederic Jacobs on 27/10/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import -#import "TSConstants.h" - -static NSString *const TSRegistrationErrorDomain = @"TSRegistrationErrorDomain"; -static NSString *const TSRegistrationErrorUserInfoHTTPStatus = @"TSHTTPStatus"; - -typedef NS_ENUM(NSUInteger, TSRegistrationFailure) { - kTSRegistrationFailureAuthentication, - kTSRegistrationFailureNetwork, - kTSRegistrationFailureRateLimit, - kTSRegistrationFailureWrongCode, - kTSRegistrationFailureAlreadyRegistered, - kTSRegistrationFailurePrekeys, - kTSRegistrationFailurePushID, - kTSRegistrationFailureRequest -}; - -typedef void(^failedVerificationBlock)(NSError *error); - -@interface TSAccountManager : NSObject - -/** - * Returns if a user is registered or not - * - * @return registered or not - */ - -+ (BOOL)isRegistered; - -/** - * Returns registered number - * - * @return E164 formatted phone number - */ - -+ (NSString*)registeredNumber; - -/** - * The registration ID is unique to an installation of TextSecure, it allows to know if the app was reinstalled - * - * @return registrationID; - */ - -+ (uint32_t)getOrGenerateRegistrationId; - -/** - * Sets the user as registered - * - */ - -+ (void)setRegistered:(BOOL)registered; - -#if TARGET_OS_IPHONE - -+ (void)registerWithRedPhoneToken:(NSString*)tsToken pushToken:(NSData*)pushToken voipToken:(NSData*)voipToken success:(successCompletionBlock)successBlock failure:(failedVerificationBlock)failureBlock; - -/** - * Register's the device's push notification token with the server - * - * @param pushToken Apple's Push Token - */ - -+ (void)registerForPushNotifications:(NSData*)pushToken voipToken:(NSData*)voipToken success:(successCompletionBlock)success failure:(failedVerificationBlock)failureBlock; - -#endif - -+ (NSError*)errorForRegistrationFailure:(TSRegistrationFailure)failureType HTTPStatusCode:(long)HTTPStatus; - -+ (void)unregisterTextSecureWithSuccess:(successCompletionBlock)success failure:(failedVerificationBlock)failureBlock; - -@end diff --git a/Signal/src/textsecure/Account/TSAccountManager.m b/Signal/src/textsecure/Account/TSAccountManager.m deleted file mode 100644 index 22d48f4ea..000000000 --- a/Signal/src/textsecure/Account/TSAccountManager.m +++ /dev/null @@ -1,220 +0,0 @@ -// -// TSAccountManagement.m -// TextSecureKit -// -// Created by Frederic Jacobs on 27/10/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "Constraints.h" -#import "NSData+Base64.h" -#import "NSData+hexString.h" -#import "NSData+ows_StripToken.h" -#import "NSURLSessionDataTask+StatusCode.h" - -#import "SecurityUtils.h" -#import "TSNetworkManager.h" -#import "TSAccountManager.h" -#import "TSSocketManager.h" -#import "TSStorageManager+keyingMaterial.h" -#import "TSPreKeyManager.h" - -@interface TSAccountManager () - -@property (nonatomic, retain) NSString *phoneNumberAwaitingVerification; - -@end - -@implementation TSAccountManager - -+ (BOOL)isRegistered { - return [[TSStorageManager sharedManager] boolForKey:TSStorageIsRegistered inCollection:TSStorageInternalSettingsCollection]; -} - -+ (void)setRegistered:(BOOL)registered{ - [[TSStorageManager sharedManager] setObject:registered?@YES:@NO forKey:TSStorageIsRegistered inCollection:TSStorageInternalSettingsCollection]; -} - -+ (NSString *)registeredNumber { - YapDatabaseConnection *dbConn = [[TSStorageManager sharedManager] newDatabaseConnection]; - __block NSString *phoneNumber; - - [dbConn readWithBlock:^(YapDatabaseReadTransaction *transaction) { - phoneNumber = [transaction objectForKey:TSStorageRegisteredNumberKey inCollection:TSStorageUserAccountCollection]; - }]; - - return phoneNumber; -} - -+ (uint32_t)getOrGenerateRegistrationId { - YapDatabaseConnection *dbConn = [[TSStorageManager sharedManager] newDatabaseConnection]; - __block uint32_t registrationID = 0; - - [dbConn readWithBlock:^(YapDatabaseReadTransaction *transaction) { - registrationID = [[transaction objectForKey:TSStorageLocalRegistrationId inCollection:TSStorageUserAccountCollection] unsignedIntValue]; - }]; - - if (registrationID == 0) { - registrationID = (uint32_t)arc4random_uniform(16380)+1; - - [dbConn readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [transaction setObject:[NSNumber numberWithUnsignedInteger:registrationID] - forKey:TSStorageLocalRegistrationId - inCollection:TSStorageUserAccountCollection]; - }]; - } - - return registrationID; -} - -+ (void)registerForPushNotifications:(NSData *)pushToken voipToken:(NSData*)voipToken success:(successCompletionBlock)success failure:(failedVerificationBlock)failureBlock{ - - NSString *pushTokenString = [pushToken ows_tripToken]; - NSString *voipTokenString = [voipToken ows_tripToken]; - - [[TSNetworkManager sharedManager] queueAuthenticatedRequest:[[TSRegisterForPushRequest alloc] initWithPushIdentifier:pushTokenString voipIdentifier:voipTokenString] success:^(NSURLSessionDataTask *task, id responseObject) { - success(); - } failure:^(NSURLSessionDataTask *task, NSError *error) { - NSLog(@"NSError: %@", error.debugDescription); - - TSRegistrationFailure failureType = kTSRegistrationFailureNetwork; - switch ([task statusCode]) { - case 401: - failureType = kTSRegistrationFailureAuthentication; - break; - case 415: - failureType = kTSRegistrationFailureRequest; - break; - default: - break; - } - - failureBlock([self errorForRegistrationFailure:failureType HTTPStatusCode:[task statusCode]]); - }]; -} - -+ (void)registerWithRedPhoneToken:(NSString*)tsToken - pushToken:(NSData*)pushToken - voipToken:(NSData*)voipToken - success:(successCompletionBlock)successBlock - failure:(failedVerificationBlock)failureBlock -{ - - NSString *authToken = [self generateNewAccountAuthenticationToken]; - NSString *signalingKey = [self generateNewSignalingKeyToken]; - NSString *phoneNumber = [[tsToken componentsSeparatedByString:@":"] objectAtIndex:0]; - - require(phoneNumber != nil); - require(signalingKey != nil); - require(authToken != nil); - require(pushToken != nil); - - TSRegisterWithTokenRequest *request = [[TSRegisterWithTokenRequest alloc] initWithVerificationToken:tsToken signalingKey:signalingKey authKey:authToken number:phoneNumber]; - - [[TSNetworkManager sharedManager] queueAuthenticatedRequest:request success:^(NSURLSessionDataTask *task, id responseObject) { - - NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response; - long statuscode = response.statusCode; - - if (statuscode == 200 || statuscode == 204) { - - [TSStorageManager storeServerToken:authToken signalingKey:signalingKey phoneNumber:phoneNumber]; - - [self registerForPushNotifications:pushToken voipToken:voipToken success:^{ - [self registerPreKeys:^{ - successBlock(); - [TSSocketManager becomeActiveFromForeground]; - } failure:failureBlock]; - } failure:^(NSError *error) { - failureBlock([self errorForRegistrationFailure:kTSRegistrationFailureNetwork HTTPStatusCode:0]); - }]; - - } else{ - failureBlock([self errorForRegistrationFailure:kTSRegistrationFailureNetwork HTTPStatusCode:statuscode]); - } - - } failure:^(NSURLSessionDataTask *task, NSError *error) { - DDLogError(@"Error registering with TextSecure: %@", error.debugDescription); - //TODO: Cover all error types: https://github.com/WhisperSystems/TextSecure-Server/wiki/API-Protocol - // Above link doesn't appear to document the endpoint /v1/accounts/token/{token} - is it similar to /v1/accounts/code/{code} ? - failureBlock([self errorForRegistrationFailure:kTSRegistrationFailureNetwork HTTPStatusCode:[task statusCode]]); - }]; -} - -+ (void)registerPreKeysAfterPush:(NSData*)pushToken - voipToken:(NSData*)voipToken - success:(successCompletionBlock)successBlock - failure:(failedVerificationBlock)failureBlock -{ - [self registerForPushNotifications:pushToken voipToken:voipToken success:^{ - [self registerPreKeys:successBlock - failure:failureBlock]; - } failure:failureBlock]; -} - -+ (void)registerPreKeys:(successCompletionBlock)successBlock failure:(failedVerificationBlock)failureBlock { - [TSPreKeyManager registerPreKeysWithSuccess:^{ - [TSAccountManager setRegistered:YES]; - successBlock(); - } failure:failureBlock]; -} - -#pragma mark Errors - -+ (NSError *)errorForRegistrationFailure:(TSRegistrationFailure)failureType HTTPStatusCode:(long)HTTPStatus { - - NSString *description = NSLocalizedString(@"REGISTRATION_ERROR", @""); - NSString *failureReason = nil; - - // TODO: Need localized strings for the rest of the values in the TSRegistrationFailure enum - if (failureType == kTSRegistrationFailureWrongCode) { - failureReason = NSLocalizedString(@"REGISTER_CHALLENGE_ALERT_VIEW_BODY", @""); - } else if (failureType == kTSRegistrationFailureRateLimit) { - failureReason = NSLocalizedString(@"REGISTER_RATE_LIMITING_BODY", @""); - } else if (failureType == kTSRegistrationFailureNetwork) { - failureReason = NSLocalizedString(@"REGISTRATION_BODY", @""); - } else { - failureReason = NSLocalizedString(@"REGISTER_CHALLENGE_UNKNOWN_ERROR", @""); - } - - NSMutableDictionary *userInfo = NSMutableDictionary.new; - - userInfo[NSLocalizedDescriptionKey] = description; - - if (failureReason != nil) { - userInfo[NSLocalizedFailureReasonErrorKey] = failureReason; - } - if (HTTPStatus != 0) { - userInfo[TSRegistrationErrorUserInfoHTTPStatus] = @(HTTPStatus); - } - - NSError *error = [NSError errorWithDomain:TSRegistrationErrorDomain code:failureType userInfo:userInfo]; - - return error; -} - -#pragma mark Server keying material - -+ (NSString*)generateNewAccountAuthenticationToken { - NSData *authToken = [SecurityUtils generateRandomBytes:16]; - NSString *authTokenPrint = [[NSData dataWithData:authToken] hexadecimalString]; - return authTokenPrint; -} - -+ (NSString*)generateNewSignalingKeyToken { - /*The signalingKey is 32 bytes of AES material (256bit AES) and 20 bytes of Hmac key material (HmacSHA1) concatenated into a 52 byte slug that is base64 encoded. */ - NSData *signalingKeyToken = [SecurityUtils generateRandomBytes:52]; - NSString *signalingKeyTokenPrint = [[NSData dataWithData:signalingKeyToken] base64EncodedString]; - return signalingKeyTokenPrint; -} - -+ (void)unregisterTextSecureWithSuccess:(successCompletionBlock)success failure:(failedVerificationBlock)failureBlock{ - [[TSNetworkManager sharedManager] queueAuthenticatedRequest:[[TSUnregisterAccountRequest alloc] init] success:^(NSURLSessionDataTask *task, id responseObject) { - success(); - } failure:^(NSURLSessionDataTask *task, NSError *error) { - failureBlock(error); - }]; - -} - -@end diff --git a/Signal/src/textsecure/Account/TSAttributes.h b/Signal/src/textsecure/Account/TSAttributes.h deleted file mode 100644 index 18cf72933..000000000 --- a/Signal/src/textsecure/Account/TSAttributes.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// TSAttributes.h -// Signal -// -// Created by Frederic Jacobs on 22/08/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import - -@interface TSAttributes : NSObject - -+ (NSDictionary*)attributesFromStorage; -+ (NSDictionary*)attributesWithSignalingKey:(NSString*)signalingKey - serverAuthToken:(NSString*)authToken; - -@end diff --git a/Signal/src/textsecure/Account/TSAttributes.m b/Signal/src/textsecure/Account/TSAttributes.m deleted file mode 100644 index 7d8355677..000000000 --- a/Signal/src/textsecure/Account/TSAttributes.m +++ /dev/null @@ -1,33 +0,0 @@ -// -// TSAttributes.m -// Signal -// -// Created by Frederic Jacobs on 22/08/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import "TSAttributes.h" - -#import "TSAccountManager.h" -#import "TSStorageHeaders.h" - -@implementation TSAttributes - - -+ (NSDictionary*)attributesFromStorage { - return [self attributesWithSignalingKey:[TSStorageManager signalingKey] - serverAuthToken:[TSStorageManager serverAuthToken]]; -} - -+ (NSDictionary*)attributesWithSignalingKey:(NSString*)signalingKey - serverAuthToken:(NSString*)authToken - -{ - return @{@"signalingKey" : signalingKey, - @"AuthKey" : authToken, - @"voice" : @YES, - @"registrationId": [NSString stringWithFormat:@"%i",[TSAccountManager getOrGenerateRegistrationId]] - }; -} - -@end diff --git a/Signal/src/textsecure/Account/TSPreKeyManager.h b/Signal/src/textsecure/Account/TSPreKeyManager.h deleted file mode 100644 index f28e1f700..000000000 --- a/Signal/src/textsecure/Account/TSPreKeyManager.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// TSPrekeyManager.h -// TextSecureKit -// -// Created by Frederic Jacobs on 07/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import -#import "TSConstants.h" -#import "TSAccountManager.h" - -// Time before deletion of signed PreKeys (measured in seconds) -#define SignedPreKeysDeletionTime 14*24*60*60 - -@interface TSPreKeyManager : NSObject - -+ (void)registerPreKeysWithSuccess:(successCompletionBlock)success failure:(failedVerificationBlock)failureBlock; - -+ (void)refreshPreKeys; - -@end diff --git a/Signal/src/textsecure/Account/TSPreKeyManager.m b/Signal/src/textsecure/Account/TSPreKeyManager.m deleted file mode 100644 index 823285bcc..000000000 --- a/Signal/src/textsecure/Account/TSPreKeyManager.m +++ /dev/null @@ -1,120 +0,0 @@ -// -// TSPrekeyManager.m -// TextSecureKit -// -// Created by Frederic Jacobs on 07/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSPreKeyManager.h" - -#import "TSStorageHeaders.h" -#import "TSNetworkManager.h" - -#define EPHEMERAL_PREKEYS_MINIMUM 15 - -@implementation TSPreKeyManager - -+ (void)registerPreKeysWithSuccess:(successCompletionBlock)success failure:(failedVerificationBlock)failureBlock{ - TSStorageManager *storageManager = [TSStorageManager sharedManager]; - ECKeyPair *identityKeyPair = [storageManager identityKeyPair]; - - if (!identityKeyPair) { - [storageManager generateNewIdentityKey]; - identityKeyPair = [storageManager identityKeyPair]; - } - - PreKeyRecord *lastResortPreKey = [storageManager getOrGenerateLastResortKey]; - SignedPreKeyRecord *signedPreKey = [storageManager generateRandomSignedRecord]; - - NSArray *preKeys = [storageManager generatePreKeyRecords]; - - TSRegisterPrekeysRequest *request = [[TSRegisterPrekeysRequest alloc] initWithPrekeyArray:preKeys - identityKey:[storageManager identityKeyPair].publicKey - signedPreKeyRecord:signedPreKey - preKeyLastResort:lastResortPreKey]; - - [[TSNetworkManager sharedManager] queueAuthenticatedRequest:request success:^(NSURLSessionDataTask *task, id responseObject) { - [storageManager storePreKeyRecords:preKeys]; - [storageManager storeSignedPreKey:signedPreKey.Id signedPreKeyRecord:signedPreKey]; - - success(); - - } failure:^(NSURLSessionDataTask *task, NSError *error) { - failureBlock([TSAccountManager errorForRegistrationFailure:kTSRegistrationFailureNetwork HTTPStatusCode:0]); - }]; - -} - -+ (void)refreshPreKeys { - TSAvailablePreKeysCountRequest *preKeyCountRequest = [[TSAvailablePreKeysCountRequest alloc] init]; - [[TSNetworkManager sharedManager] queueAuthenticatedRequest:preKeyCountRequest success:^(NSURLSessionDataTask *task, NSDictionary* responseObject){ - NSString *preKeyCountKey = @"count"; - NSNumber *count = [responseObject objectForKey:preKeyCountKey]; - - if (count.integerValue > EPHEMERAL_PREKEYS_MINIMUM) { - DDLogVerbose(@"Available prekeys sufficient: %@", count.stringValue); - return; - } else { - [self registerPreKeysWithSuccess:^{ - DDLogInfo(@"New PreKeys registered with server."); - - [self clearSignedPreKeyRecords]; - } failure:^(NSError *error) { - DDLogWarn(@"Failed to update prekeys with the server"); - }]; - } - } failure:^(NSURLSessionDataTask *task, NSError *error) { - DDLogError(@"Failed to retrieve the number of available prekeys."); - }]; -} - -+ (void)clearSignedPreKeyRecords { - - TSRequest *currentSignedPreKey = [[TSCurrentSignedPreKeyRequest alloc] init]; - [[TSNetworkManager sharedManager] queueAuthenticatedRequest:currentSignedPreKey success:^(NSURLSessionDataTask *task, NSDictionary* responseObject) { - NSString *keyIdDictKey = @"keyId"; - NSNumber *keyId = [responseObject objectForKey:keyIdDictKey]; - - [self clearSignedPreKeyRecordsWithKeyId:keyId]; - - } failure:^(NSURLSessionDataTask *task, NSError *error) { - DDLogWarn(@"Failed to retrieve current prekey."); - }]; -} - -+ (void)clearSignedPreKeyRecordsWithKeyId:(NSNumber*)keyId{ - if (!keyId) { - DDLogError(@"The server returned an incomplete "); - return; - } - - TSStorageManager *storageManager = [TSStorageManager sharedManager]; - SignedPreKeyRecord *currentRecord = [storageManager loadSignedPrekey:keyId.intValue]; - NSArray *allSignedPrekeys = [storageManager loadSignedPreKeys]; - NSArray *oldSignedPrekeys = [self removeCurrentRecord:currentRecord fromRecords:allSignedPrekeys]; - - if ([oldSignedPrekeys count] > 3) { - for (SignedPreKeyRecord *deletionCandidate in oldSignedPrekeys) { - DDLogInfo(@"Old signed prekey record: %@", deletionCandidate.generatedAt); - - if ([deletionCandidate.generatedAt timeIntervalSinceNow] > SignedPreKeysDeletionTime) { - [storageManager removeSignedPreKey:deletionCandidate.Id]; - } - } - } -} - -+ (NSArray*)removeCurrentRecord:(SignedPreKeyRecord*)currentRecord fromRecords:(NSArray*)allRecords { - NSMutableArray *oldRecords = [NSMutableArray array]; - - for (SignedPreKeyRecord *record in allRecords) { - if (currentRecord.Id != record.Id) { - [oldRecords addObject:record]; - } - } - - return oldRecords; -} - -@end diff --git a/Signal/src/textsecure/Contacts/SignalRecipient.h b/Signal/src/textsecure/Contacts/SignalRecipient.h deleted file mode 100644 index 71fcabfc1..000000000 --- a/Signal/src/textsecure/Contacts/SignalRecipient.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// TSRecipient.h -// TextSecureKit -// -// Created by Frederic Jacobs on 17/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSYapDatabaseObject.h" - -@interface SignalRecipient : TSYapDatabaseObject - -- (instancetype)initWithTextSecureIdentifier:(NSString*)textSecureIdentifier - relay:(NSString *)relay - supportsVoice:(BOOL)voiceCapable; - -+ (instancetype)recipientWithTextSecureIdentifier:(NSString*)textSecureIdentifier - withTransaction:(YapDatabaseReadTransaction*)transaction; - -- (void)addDevices:(NSSet *)set; - -- (void)removeDevices:(NSSet *)set; - -@property (nonatomic) NSString *relay; -@property (nonatomic, retain) NSMutableOrderedSet *devices; -@property BOOL supportsVoice; - -@end diff --git a/Signal/src/textsecure/Contacts/SignalRecipient.m b/Signal/src/textsecure/Contacts/SignalRecipient.m deleted file mode 100644 index 1ce51a64a..000000000 --- a/Signal/src/textsecure/Contacts/SignalRecipient.m +++ /dev/null @@ -1,57 +0,0 @@ -// -// TSRecipient.m -// TextSecureKit -// -// Created by Frederic Jacobs on 17/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager+IdentityKeyStore.h" -#import "SignalRecipient.h" - -@implementation SignalRecipient - -+ (NSString*)collection{ - return @"SignalRecipient"; -} - -- (instancetype)initWithTextSecureIdentifier:(NSString*)textSecureIdentifier - relay:(NSString *)relay - supportsVoice:(BOOL)voiceCapable -{ - self = [super initWithUniqueId:textSecureIdentifier]; - - if (self) { - _devices = [NSMutableOrderedSet orderedSetWithObject:[NSNumber numberWithInt:1]]; - _relay = relay; - _supportsVoice = voiceCapable; - } - - return self; -} - -+ (instancetype)recipientWithTextSecureIdentifier:(NSString*)textSecureIdentifier withTransaction:(YapDatabaseReadTransaction*)transaction{ - return [self fetchObjectWithUniqueID:textSecureIdentifier transaction:transaction]; -} - -- (NSMutableOrderedSet*)devices{ - return [_devices copy]; -} - -- (void)addDevices:(NSSet *)set{ - [self checkDevices]; - [_devices unionSet:set]; -} - -- (void)removeDevices:(NSSet *)set{ - [self checkDevices]; - [_devices minusSet:set]; -} - -- (void)checkDevices { - if (_devices == nil || ![_devices isKindOfClass:[NSMutableOrderedSet class]]) { - _devices = [NSMutableOrderedSet orderedSetWithObject:[NSNumber numberWithInt:1]]; - } -} - -@end diff --git a/Signal/src/textsecure/Contacts/TSThread.h b/Signal/src/textsecure/Contacts/TSThread.h deleted file mode 100644 index 312d4b181..000000000 --- a/Signal/src/textsecure/Contacts/TSThread.h +++ /dev/null @@ -1,129 +0,0 @@ -// -// TSThread.h -// TextSecureKit -// -// Created by Frederic Jacobs on 16/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import -#import "TSYapDatabaseObject.h" - -@class TSInteraction; - -/** - * TSThread is the superclass of TSContactThread and TSGroupThread - */ - -@interface TSThread : TSYapDatabaseObject - -/** - * Whether the object is a group thread or not. - * - * @return YES if is a group thread, NO otherwise. - */ -- (BOOL)isGroupThread; - -/** - * Returns the name of the thread. - * - * @return The name of the thread. - */ -- (NSString *)name; - -/** - * Returns the image representing the thread. Nil if not available. - * - * @return UIImage of the thread, or nil. - */ -- (UIImage *)image; - -#pragma mark Read Status - -/** - * Returns whether or not the thread has unread messages. - * - * @return YES if it has unread TSIncomingMessages, NO otherwise. - */ -- (BOOL)hasUnreadMessages; - -- (void)markAllAsReadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction; - -#pragma mark Last Interactions - -/** - * Returns the latest date of a message in the thread or the thread creation date if there are no messages in that - *thread. - * - * @return The date of the last message or thread creation date. - */ -- (NSDate *)lastMessageDate; - -/** - * Returns the string that will be displayed typically in a conversations view as a preview of the last message - *received in this thread. - * - * @return Thread preview string. - */ -- (NSString *)lastMessageLabel; - -/** - * Updates the thread's caches of the latest interaction. - * - * @param lastMessage Latest Interaction to take into consideration. - * @param transaction Database transaction. - */ -- (void)updateWithLastMessage:(TSInteraction *)lastMessage transaction:(YapDatabaseReadWriteTransaction *)transaction; - -#pragma mark Archival - -/** - * Returns the last date at which a string was archived or nil if the thread was never archived or brought back to the - *inbox. - * - * @return Last archival date. - */ -- (NSDate *)archivalDate; - -/** - * Archives a thread with the current date. - * - * @param transaction Database transaction. - */ -- (void)archiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction; - -/** - * Archives a thread with the reference date. This is currently only used for migrating older data that has already been archived. - * - * @param transaction Database transaction. - * @param date Date at which the thread was archived. - */ -- (void)archiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction referenceDate:(NSDate *)date; - -/** - * Unarchives a thread that was archived previously. - * - * @param transaction Database transaction. - */ -- (void)unarchiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction; - -#pragma mark Drafts - -/** - * Returns the last known draft for that thread. Always returns a string. Empty string if nil. - * - * @param transaction Database transaction. - * - * @return Last known draft for that thread. - */ -- (NSString *)currentDraftWithTransaction:(YapDatabaseReadTransaction *)transaction; - -/** - * Sets the draft of a thread. Typically called when leaving a conversation view. - * - * @param draftString Draft string to be saved. - * @param transaction Database transaction. - */ -- (void)setDraft:(NSString *)draftString transaction:(YapDatabaseReadWriteTransaction *)transaction; - -@end diff --git a/Signal/src/textsecure/Contacts/TSThread.m b/Signal/src/textsecure/Contacts/TSThread.m deleted file mode 100644 index bf7204e95..000000000 --- a/Signal/src/textsecure/Contacts/TSThread.m +++ /dev/null @@ -1,181 +0,0 @@ -// -// TSThread.m -// TextSecureKit -// -// Created by Frederic Jacobs on 16/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSThread.h" -#import "TSDatabaseView.h" -#import "TSInteraction.h" -#import "TSStorageManager.h" - -#import "TSOutgoingMessage.h" -#import "TSIncomingMessage.h" - -@interface TSThread () - -@property (nonatomic, retain) NSDate *creationDate; -@property (nonatomic, copy ) NSDate *archivalDate; -@property (nonatomic, retain) NSDate *lastMessageDate; -@property (nonatomic, copy ) NSString *latestMessageId; -@property (nonatomic, copy ) NSString *messageDraft; -@end - -@implementation TSThread - -+ (NSString *)collection -{ - return @"TSThread"; -} - -- (instancetype)initWithUniqueId:(NSString *)uniqueId -{ - self = [super initWithUniqueId:uniqueId]; - - if (self) { - _archivalDate = nil; - _latestMessageId = nil; - _lastMessageDate = nil; - _creationDate = [NSDate date]; - _messageDraft = nil; - } - - return self; -} - -#pragma mark To be subclassed. - -- (BOOL)isGroupThread -{ - NSAssert(false, @"An abstract method on TSThread was called."); - return FALSE; -} - -- (NSString *)name -{ - NSAssert(FALSE, @"Should be implemented in subclasses"); - return nil; -} - -- (UIImage *)image -{ - return nil; -} - -#pragma mark Read Status - -- (BOOL)hasUnreadMessages -{ - __block TSInteraction *interaction; - __block BOOL hasUnread = NO; - [[TSStorageManager sharedManager].dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - interaction = [TSInteraction fetchObjectWithUniqueID:self.latestMessageId transaction:transaction]; - if ([interaction isKindOfClass:[TSIncomingMessage class]]) { - hasUnread = ![(TSIncomingMessage *)interaction wasRead]; - } - }]; - - return hasUnread; -} - -- (void)markAllAsReadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction -{ - YapDatabaseViewTransaction *viewTransaction = [transaction ext:TSUnreadDatabaseViewExtensionName]; - NSMutableArray *array = [NSMutableArray array]; - [viewTransaction enumerateRowsInGroup:self.uniqueId - usingBlock:^(NSString *collection, NSString *key, id object, id metadata, - NSUInteger index, BOOL *stop) { - [array addObject:object]; - }]; - - for (TSIncomingMessage *message in array) { - message.read = YES; - [message saveWithTransaction:transaction]; - } -} - -#pragma mark Last Interactions - -- (NSDate *)lastMessageDate -{ - if (_lastMessageDate) { - return _lastMessageDate; - } else { - return _creationDate; - } -} - -- (NSString *)lastMessageLabel -{ - __block TSInteraction *interaction; - [[TSStorageManager sharedManager].dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - interaction = [TSInteraction fetchObjectWithUniqueID:self.latestMessageId transaction:transaction]; - }]; - return interaction.description; -} - -- (void)updateWithLastMessage:(TSInteraction *)lastMessage transaction:(YapDatabaseReadWriteTransaction *)transaction -{ - NSDate *lastMessageDate = lastMessage.date; - - if ([lastMessage isKindOfClass:[TSIncomingMessage class]]) { - TSIncomingMessage *message = (TSIncomingMessage*)lastMessage; - lastMessageDate = message.receivedAt; - } - - if (!_lastMessageDate || [lastMessageDate timeIntervalSinceDate:self.lastMessageDate] > 0) { - _latestMessageId = lastMessage.uniqueId; - _lastMessageDate = lastMessageDate; - - [self saveWithTransaction:transaction]; - } -} - -#pragma mark Archival - -- (NSDate *)archivalDate -{ - return _archivalDate; -} - -- (void)archiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction -{ - [self archiveThreadWithTransaction:transaction referenceDate:[NSDate date]]; -} - -- (void)archiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction referenceDate:(NSDate *)date -{ - [self markAllAsReadWithTransaction:transaction]; - _archivalDate = date; - - [self saveWithTransaction:transaction]; -} - -- (void)unarchiveThreadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction -{ - _archivalDate = nil; - [self saveWithTransaction:transaction]; -} - -#pragma mark Drafts - -- (NSString *)currentDraftWithTransaction:(YapDatabaseReadTransaction *)transaction -{ - TSThread *thread = [TSThread fetchObjectWithUniqueID:self.uniqueId transaction:transaction]; - if (thread.messageDraft) { - return thread.messageDraft; - } else { - return @""; - } -} - -- (void)setDraft:(NSString *)draftString transaction:(YapDatabaseReadWriteTransaction *)transaction -{ - TSThread *thread = [TSThread fetchObjectWithUniqueID:self.uniqueId transaction:transaction]; - thread.messageDraft = draftString; - [thread saveWithTransaction:transaction]; -} - -@end diff --git a/Signal/src/textsecure/Contacts/Threads/TSContactThread.h b/Signal/src/textsecure/Contacts/Threads/TSContactThread.h deleted file mode 100644 index fd236ad07..000000000 --- a/Signal/src/textsecure/Contacts/Threads/TSContactThread.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// TSContactThread.h -// TextSecureKit -// -// Created by Frederic Jacobs on 16/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import - -#import "TSThread.h" -#import "SignalRecipient.h" - -@class IncomingPushMessageSignal; - -@interface TSContactThread : TSThread - -+ (instancetype)getOrCreateThreadWithContactId:(NSString*)contactId transaction:(YapDatabaseReadWriteTransaction*)transaction; -+ (instancetype)getOrCreateThreadWithContactId:(NSString*)contactId transaction:(YapDatabaseReadWriteTransaction*)transaction pushSignal:(IncomingPushMessageSignal*)pushSignal; - -- (NSString*)contactIdentifier; - -@end diff --git a/Signal/src/textsecure/Contacts/Threads/TSContactThread.m b/Signal/src/textsecure/Contacts/Threads/TSContactThread.m deleted file mode 100644 index 810a86d7a..000000000 --- a/Signal/src/textsecure/Contacts/Threads/TSContactThread.m +++ /dev/null @@ -1,89 +0,0 @@ -// -// TSContactThread.m -// TextSecureKit -// -// Created by Frederic Jacobs on 16/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSContactThread.h" - -#import "Environment.h" -#import "IncomingPushMessageSignal.pb.h" -#import "ContactsManager+updater.h" - -#define TSContactThreadPrefix @"c" - -@implementation TSContactThread - -- (instancetype)initWithContactId:(NSString*)contactId{ - - NSString *uniqueIdentifier = [[self class] threadIdFromContactId:contactId]; - - self = [super initWithUniqueId:uniqueIdentifier]; - - return self; -} - -+ (instancetype)getOrCreateThreadWithContactId:(NSString*)contactId transaction:(YapDatabaseReadWriteTransaction*)transaction pushSignal:(IncomingPushMessageSignal*)pushSignal{ - SignalRecipient *recipient = [SignalRecipient recipientWithTextSecureIdentifier:contactId withTransaction:transaction]; - - if (!recipient) { - NSString *relay = pushSignal.hasRelay && ![pushSignal.relay isEqualToString:@""]?pushSignal.relay:nil; - recipient = [[SignalRecipient alloc] initWithTextSecureIdentifier:contactId relay:relay supportsVoice:YES]; - [[Environment getCurrent].contactsManager lookupIdentifier:contactId - success:^(NSSet *matchedIds) {} - failure:^(NSError *error) { - DDLogInfo(@"Failed to retreive call status. Will be retreived on next contact intersection."); - }]; - [recipient saveWithTransaction:transaction]; - } - - return [self getOrCreateThreadWithContactId:contactId transaction:transaction]; -} - -+ (instancetype)getOrCreateThreadWithContactId:(NSString*)contactId transaction:(YapDatabaseReadWriteTransaction*)transaction { - - TSContactThread *thread = [self fetchObjectWithUniqueID:[self threadIdFromContactId:contactId] transaction:transaction]; - - if (!thread) { - thread = [[TSContactThread alloc] initWithContactId:contactId]; - [thread saveWithTransaction:transaction]; - } - - return thread; -} - -- (NSString*)contactIdentifier{ - return [[self class]contactIdFromThreadId:self.uniqueId]; -} - -- (BOOL)isGroupThread{ - return false; -} - -- (NSString*)name{ - NSString *contactId = [self contactIdentifier]; - NSString *name = [[Environment getCurrent].contactsManager nameStringForPhoneIdentifier:contactId]; - - if (!name) { - name = contactId; - } - - return name; -} - -- (UIImage*)image{ - UIImage *image = [[Environment getCurrent].contactsManager imageForPhoneIdentifier:self.contactIdentifier]; - return image; -} - -+ (NSString*)threadIdFromContactId:(NSString*)contactId{ - return [TSContactThreadPrefix stringByAppendingString:contactId]; -} - -+ (NSString*)contactIdFromThreadId:(NSString*)threadId{ - return [threadId substringWithRange:NSMakeRange(1, threadId.length-1)]; -} - -@end diff --git a/Signal/src/textsecure/Contacts/Threads/TSGroupThread.h b/Signal/src/textsecure/Contacts/Threads/TSGroupThread.h deleted file mode 100644 index b7939c154..000000000 --- a/Signal/src/textsecure/Contacts/Threads/TSGroupThread.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// TSGroupThread.h -// TextSecureKit -// -// Created by Frederic Jacobs on 16/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSThread.h" -#import "TSGroupModel.h" - -@interface TSGroupThread : TSThread -@property (nonatomic,strong) TSGroupModel* groupModel; -+ (instancetype)getOrCreateThreadWithGroupModel:(TSGroupModel *)groupModel transaction:(YapDatabaseReadWriteTransaction*)transaction; - -+ (instancetype)threadWithGroupModel:(TSGroupModel *)groupModel transaction:(YapDatabaseReadTransaction*)transaction; -- (NSData*)groupId; - -@end diff --git a/Signal/src/textsecure/Contacts/Threads/TSGroupThread.m b/Signal/src/textsecure/Contacts/Threads/TSGroupThread.m deleted file mode 100644 index a76726f38..000000000 --- a/Signal/src/textsecure/Contacts/Threads/TSGroupThread.m +++ /dev/null @@ -1,61 +0,0 @@ -// -// TSGroupThread.m -// TextSecureKit -// -// Created by Frederic Jacobs on 16/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSGroupThread.h" -#import "SignalRecipient.h" -#import "NSData+Base64.h" - -@implementation TSGroupThread - -#define TSGroupThreadPrefix @"g" - -- (instancetype)initWithGroupModel:(TSGroupModel *)groupModel{ - - NSString *uniqueIdentifier = [[self class] threadIdFromGroupId:groupModel.groupId]; - - self = [super initWithUniqueId:uniqueIdentifier]; - _groupModel = groupModel; - return self; -} - - -+ (instancetype)threadWithGroupModel:(TSGroupModel *)groupModel transaction:(YapDatabaseReadTransaction*)transaction { - return [self fetchObjectWithUniqueID:[self threadIdFromGroupId:groupModel.groupId] transaction:transaction]; -} - -+ (instancetype)getOrCreateThreadWithGroupModel:(TSGroupModel *)groupModel transaction:(YapDatabaseReadWriteTransaction*)transaction{ - TSGroupThread *thread = [self fetchObjectWithUniqueID:[self threadIdFromGroupId:groupModel.groupId] transaction:transaction]; - - if (!thread) { - thread = [[TSGroupThread alloc] initWithGroupModel:groupModel]; - [thread saveWithTransaction:transaction]; - } - return thread; -} - -- (BOOL)isGroupThread{ - return true; -} - -- (NSData *)groupId{ - return [[self class] groupIdFromThreadId:self.uniqueId]; -} - -- (NSString*)name{ - return self.groupModel.groupName; -} - -+ (NSString*)threadIdFromGroupId:(NSData*)groupId{ - return [TSGroupThreadPrefix stringByAppendingString:[groupId base64EncodedString]]; -} - -+ (NSData*)groupIdFromThreadId:(NSString*)threadId{ - return [NSData dataFromBase64String:[threadId substringWithRange:NSMakeRange(1, threadId.length-1)]]; -} - -@end diff --git a/Signal/src/textsecure/Messages/Attachements/TSAttachmentPointer.h b/Signal/src/textsecure/Messages/Attachements/TSAttachmentPointer.h deleted file mode 100644 index 5a73660d0..000000000 --- a/Signal/src/textsecure/Messages/Attachements/TSAttachmentPointer.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// TSAttachementPointer.h -// Signal -// -// Created by Frederic Jacobs on 17/12/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import - -#import "TSAttachment.h" - -@interface TSAttachmentPointer : TSAttachment - -- (instancetype)initWithIdentifier:(uint64_t)identifier - key:(NSData*)key - contentType:(NSString*)contentType - relay:(NSString*)relay NS_DESIGNATED_INITIALIZER; - -- (instancetype)initWithIdentifier:(uint64_t)identifier - key:(NSData*)key - contentType:(NSString*)contentType - relay:(NSString*)relay - avatarOfGroupId:(NSData*)avatarOfGroupId; - -@property NSString *relay; -@property NSData *avatarOfGroupId; - -@property (getter=isDownloading) BOOL downloading; -@property (getter=hasFailed) BOOL failed; - -@end diff --git a/Signal/src/textsecure/Messages/Attachements/TSAttachmentPointer.m b/Signal/src/textsecure/Messages/Attachements/TSAttachmentPointer.m deleted file mode 100644 index a0ed70119..000000000 --- a/Signal/src/textsecure/Messages/Attachements/TSAttachmentPointer.m +++ /dev/null @@ -1,54 +0,0 @@ -// -// TSAttachementPointer.m -// Signal -// -// Created by Frederic Jacobs on 17/12/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSAttachmentPointer.h" - -@implementation TSAttachmentPointer - -- (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) { - _failed = FALSE; - _downloading = FALSE; - _relay = relay; - } - - return self; -} - - - -- (instancetype)initWithIdentifier:(uint64_t)identifier - key:(NSData*)key - contentType:(NSString*)contentType - relay:(NSString*)relay - avatarOfGroupId:(NSData *)avatarOfGroupId { - - self = [self initWithIdentifier:identifier - key:key - contentType:contentType - relay:relay]; - if(self){ - _relay = relay; - _avatarOfGroupId = avatarOfGroupId; - } - return self; -} - - -- (BOOL)isDownloaded{ - return NO; -} - - -@end diff --git a/Signal/src/textsecure/Messages/Attachements/TSAttachmentStream.h b/Signal/src/textsecure/Messages/Attachements/TSAttachmentStream.h deleted file mode 100644 index bd4ad5d14..000000000 --- a/Signal/src/textsecure/Messages/Attachements/TSAttachmentStream.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// TSAttachementStream.h -// Signal -// -// Created by Frederic Jacobs on 17/12/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSAttachment.h" - -@interface TSAttachmentStream : TSAttachment - -@property (nonatomic) BOOL isDownloaded; - -- (instancetype)initWithIdentifier:(NSString*)identifier - data:(NSData*)data - key:(NSData*)key - contentType:(NSString*)contentType NS_DESIGNATED_INITIALIZER;; - -- (UIImage *)image; - -- (BOOL)isAnimated; -- (BOOL)isImage; -- (BOOL)isVideo; --(NSURL*)mediaURL; - -+ (void)deleteAttachments; -+ (NSString*)attachmentsFolder; - -@end diff --git a/Signal/src/textsecure/Messages/Attachements/TSAttachmentStream.m b/Signal/src/textsecure/Messages/Attachements/TSAttachmentStream.m deleted file mode 100644 index f2070cf2d..000000000 --- a/Signal/src/textsecure/Messages/Attachements/TSAttachmentStream.m +++ /dev/null @@ -1,109 +0,0 @@ -// -// TSattachmentStream.m -// Signal -// -// Created by Frederic Jacobs on 17/12/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSAttachmentStream.h" -#import -#import "MIMETypeUtil.h" -NSString * const TSAttachementFileRelationshipEdge = @"TSAttachementFileEdge"; - -@implementation TSAttachmentStream - -- (instancetype)initWithIdentifier:(NSString*)identifier - data:(NSData*)data - key:(NSData*)key - contentType:(NSString*)contentType { - self = [super initWithIdentifier:identifier encryptionKey:key contentType:contentType]; - - [[NSFileManager defaultManager] createFileAtPath:self.filePath contents:data attributes:nil]; - - _isDownloaded = YES; - return self; -} - -- (NSArray *)yapDatabaseRelationshipEdges { - YapDatabaseRelationshipEdge *attachmentFileEdge = [YapDatabaseRelationshipEdge edgeWithName:TSAttachementFileRelationshipEdge - destinationFilePath:[self filePath] - nodeDeleteRules:YDB_DeleteDestinationIfSourceDeleted]; - - return @[attachmentFileEdge]; -} - -+ (NSString*)attachmentsFolder { - NSFileManager* fileManager = [NSFileManager defaultManager]; - NSURL *fileURL = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; - NSString *path = [fileURL path]; - NSString *attachmentFolder = [path stringByAppendingFormat:@"/Attachments"]; - - NSError * error = nil; - [[NSFileManager defaultManager] createDirectoryAtPath:attachmentFolder - withIntermediateDirectories:YES - attributes:nil - error:&error]; - if (error != nil) { - DDLogError(@"Failed to create attachments directory: %@", error.description); - } - - return attachmentFolder; -} - -- (NSString*)filePath { - return [MIMETypeUtil filePathForAttachment:self.uniqueId ofMIMEType:self.contentType inFolder:[[self class] attachmentsFolder]]; -} - --(NSURL*) mediaURL { - return [NSURL fileURLWithPath:[self filePath]]; -} - -- (BOOL)isAnimated { - return [MIMETypeUtil isAnimated:self.contentType]; -} - -- (BOOL)isImage { - return [MIMETypeUtil isImage:self.contentType]; -} - -- (BOOL)isVideo { - return [MIMETypeUtil isVideo:self.contentType]; -} - --(BOOL)isAudio { - return [MIMETypeUtil isAudio:self.contentType]; -} - -- (UIImage*)image { - if ([self isVideo] || [self isAudio]) { - return [self videoThumbnail]; - } - else { - // [self isAnimated] || [self isImage] - return [UIImage imageWithData:[NSData dataWithContentsOfURL:[self mediaURL]]]; - } -} - - -- (UIImage*)videoThumbnail { - AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:self.filePath] options:nil]; - AVAssetImageGenerator *generate = [[AVAssetImageGenerator alloc] initWithAsset:asset]; - generate.appliesPreferredTrackTransform = YES; - NSError *err = NULL; - CMTime time = CMTimeMake(1, 60); - CGImageRef imgRef = [generate copyCGImageAtTime:time actualTime:NULL error:&err]; - return [[UIImage alloc] initWithCGImage:imgRef]; - -} - -+ (void)deleteAttachments { - NSFileManager *fm = [NSFileManager defaultManager]; - NSError *error; - [fm removeItemAtPath:[self attachmentsFolder] error:&error]; - if (error) { - DDLogError(@"Failed to delete attachment folder with error: %@", error.debugDescription); - } -} - -@end diff --git a/Signal/src/textsecure/Messages/IncomingPushMessageSignal.pb.h b/Signal/src/textsecure/Messages/IncomingPushMessageSignal.pb.h deleted file mode 100644 index 3da22febf..000000000 --- a/Signal/src/textsecure/Messages/IncomingPushMessageSignal.pb.h +++ /dev/null @@ -1,387 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! - -#import - -// @@protoc_insertion_point(imports) - -@class IncomingPushMessageSignal; -@class IncomingPushMessageSignalBuilder; -@class PushMessageContent; -@class PushMessageContentAttachmentPointer; -@class PushMessageContentAttachmentPointerBuilder; -@class PushMessageContentBuilder; -@class PushMessageContentGroupContext; -@class PushMessageContentGroupContextBuilder; -#ifndef __has_feature - #define __has_feature(x) 0 // Compatibility with non-clang compilers. -#endif // __has_feature - -#ifndef NS_RETURNS_NOT_RETAINED - #if __has_feature(attribute_ns_returns_not_retained) - #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained)) - #else - #define NS_RETURNS_NOT_RETAINED - #endif -#endif - -typedef enum { - IncomingPushMessageSignalTypeUnknown = 0, - IncomingPushMessageSignalTypeCiphertext = 1, - IncomingPushMessageSignalTypeKeyExchange = 2, - IncomingPushMessageSignalTypePrekeyBundle = 3, - IncomingPushMessageSignalTypePlaintext = 4, - IncomingPushMessageSignalTypeReceipt = 5, -} IncomingPushMessageSignalType; - -BOOL IncomingPushMessageSignalTypeIsValidValue(IncomingPushMessageSignalType value); - -typedef enum { - PushMessageContentFlagsEndSession = 1, -} PushMessageContentFlags; - -BOOL PushMessageContentFlagsIsValidValue(PushMessageContentFlags value); - -typedef enum { - PushMessageContentGroupContextTypeUnknown = 0, - PushMessageContentGroupContextTypeUpdate = 1, - PushMessageContentGroupContextTypeDeliver = 2, - PushMessageContentGroupContextTypeQuit = 3, -} PushMessageContentGroupContextType; - -BOOL PushMessageContentGroupContextTypeIsValidValue(PushMessageContentGroupContextType value); - - -@interface IncomingPushMessageSignalRoot : NSObject { -} -+ (PBExtensionRegistry*) extensionRegistry; -+ (void) registerAllExtensions:(PBMutableExtensionRegistry*) registry; -@end - -@interface IncomingPushMessageSignal : PBGeneratedMessage { -@private - BOOL hasTimestamp_:1; - BOOL hasSource_:1; - BOOL hasRelay_:1; - BOOL hasMessage_:1; - BOOL hasSourceDevice_:1; - BOOL hasType_:1; - UInt64 timestamp; - NSString* source; - NSString* relay; - NSData* message; - UInt32 sourceDevice; - IncomingPushMessageSignalType type; -} -- (BOOL) hasType; -- (BOOL) hasSource; -- (BOOL) hasSourceDevice; -- (BOOL) hasRelay; -- (BOOL) hasTimestamp; -- (BOOL) hasMessage; -@property (readonly) IncomingPushMessageSignalType type; -@property (readonly, strong) NSString* source; -@property (readonly) UInt32 sourceDevice; -@property (readonly, strong) NSString* relay; -@property (readonly) UInt64 timestamp; -@property (readonly, strong) NSData* message; - -+ (IncomingPushMessageSignal*) defaultInstance; -- (IncomingPushMessageSignal*) defaultInstance; - -- (BOOL) isInitialized; -- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output; -- (IncomingPushMessageSignalBuilder*) builder; -+ (IncomingPushMessageSignalBuilder*) builder; -+ (IncomingPushMessageSignalBuilder*) builderWithPrototype:(IncomingPushMessageSignal*) prototype; -- (IncomingPushMessageSignalBuilder*) toBuilder; - -+ (IncomingPushMessageSignal*) parseFromData:(NSData*) data; -+ (IncomingPushMessageSignal*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -+ (IncomingPushMessageSignal*) parseFromInputStream:(NSInputStream*) input; -+ (IncomingPushMessageSignal*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -+ (IncomingPushMessageSignal*) parseFromCodedInputStream:(PBCodedInputStream*) input; -+ (IncomingPushMessageSignal*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -@end - -@interface IncomingPushMessageSignalBuilder : PBGeneratedMessageBuilder { -@private - IncomingPushMessageSignal* result; -} - -- (IncomingPushMessageSignal*) defaultInstance; - -- (IncomingPushMessageSignalBuilder*) clear; -- (IncomingPushMessageSignalBuilder*) clone; - -- (IncomingPushMessageSignal*) build; -- (IncomingPushMessageSignal*) buildPartial; - -- (IncomingPushMessageSignalBuilder*) mergeFrom:(IncomingPushMessageSignal*) other; -- (IncomingPushMessageSignalBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input; -- (IncomingPushMessageSignalBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; - -- (BOOL) hasType; -- (IncomingPushMessageSignalType) type; -- (IncomingPushMessageSignalBuilder*) setType:(IncomingPushMessageSignalType) value; -- (IncomingPushMessageSignalBuilder*) clearType; - -- (BOOL) hasSource; -- (NSString*) source; -- (IncomingPushMessageSignalBuilder*) setSource:(NSString*) value; -- (IncomingPushMessageSignalBuilder*) clearSource; - -- (BOOL) hasSourceDevice; -- (UInt32) sourceDevice; -- (IncomingPushMessageSignalBuilder*) setSourceDevice:(UInt32) value; -- (IncomingPushMessageSignalBuilder*) clearSourceDevice; - -- (BOOL) hasRelay; -- (NSString*) relay; -- (IncomingPushMessageSignalBuilder*) setRelay:(NSString*) value; -- (IncomingPushMessageSignalBuilder*) clearRelay; - -- (BOOL) hasTimestamp; -- (UInt64) timestamp; -- (IncomingPushMessageSignalBuilder*) setTimestamp:(UInt64) value; -- (IncomingPushMessageSignalBuilder*) clearTimestamp; - -- (BOOL) hasMessage; -- (NSData*) message; -- (IncomingPushMessageSignalBuilder*) setMessage:(NSData*) value; -- (IncomingPushMessageSignalBuilder*) clearMessage; -@end - -@interface PushMessageContent : PBGeneratedMessage { -@private - BOOL hasBody_:1; - BOOL hasGroup_:1; - BOOL hasFlags_:1; - NSString* body; - PushMessageContentGroupContext* group; - UInt32 flags; - NSMutableArray * attachmentsArray; -} -- (BOOL) hasBody; -- (BOOL) hasGroup; -- (BOOL) hasFlags; -@property (readonly, strong) NSString* body; -@property (readonly, strong) NSArray * attachments; -@property (readonly, strong) PushMessageContentGroupContext* group; -@property (readonly) UInt32 flags; -- (PushMessageContentAttachmentPointer*)attachmentsAtIndex:(NSUInteger)index; - -+ (PushMessageContent*) defaultInstance; -- (PushMessageContent*) defaultInstance; - -- (BOOL) isInitialized; -- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output; -- (PushMessageContentBuilder*) builder; -+ (PushMessageContentBuilder*) builder; -+ (PushMessageContentBuilder*) builderWithPrototype:(PushMessageContent*) prototype; -- (PushMessageContentBuilder*) toBuilder; - -+ (PushMessageContent*) parseFromData:(NSData*) data; -+ (PushMessageContent*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -+ (PushMessageContent*) parseFromInputStream:(NSInputStream*) input; -+ (PushMessageContent*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -+ (PushMessageContent*) parseFromCodedInputStream:(PBCodedInputStream*) input; -+ (PushMessageContent*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -@end - -@interface PushMessageContentAttachmentPointer : PBGeneratedMessage { -@private - BOOL hasId_:1; - BOOL hasContentType_:1; - BOOL hasKey_:1; - UInt64 id; - NSString* contentType; - NSData* key; -} -- (BOOL) hasId; -- (BOOL) hasContentType; -- (BOOL) hasKey; -@property (readonly) UInt64 id; -@property (readonly, strong) NSString* contentType; -@property (readonly, strong) NSData* key; - -+ (PushMessageContentAttachmentPointer*) defaultInstance; -- (PushMessageContentAttachmentPointer*) defaultInstance; - -- (BOOL) isInitialized; -- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output; -- (PushMessageContentAttachmentPointerBuilder*) builder; -+ (PushMessageContentAttachmentPointerBuilder*) builder; -+ (PushMessageContentAttachmentPointerBuilder*) builderWithPrototype:(PushMessageContentAttachmentPointer*) prototype; -- (PushMessageContentAttachmentPointerBuilder*) toBuilder; - -+ (PushMessageContentAttachmentPointer*) parseFromData:(NSData*) data; -+ (PushMessageContentAttachmentPointer*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -+ (PushMessageContentAttachmentPointer*) parseFromInputStream:(NSInputStream*) input; -+ (PushMessageContentAttachmentPointer*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -+ (PushMessageContentAttachmentPointer*) parseFromCodedInputStream:(PBCodedInputStream*) input; -+ (PushMessageContentAttachmentPointer*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -@end - -@interface PushMessageContentAttachmentPointerBuilder : PBGeneratedMessageBuilder { -@private - PushMessageContentAttachmentPointer* result; -} - -- (PushMessageContentAttachmentPointer*) defaultInstance; - -- (PushMessageContentAttachmentPointerBuilder*) clear; -- (PushMessageContentAttachmentPointerBuilder*) clone; - -- (PushMessageContentAttachmentPointer*) build; -- (PushMessageContentAttachmentPointer*) buildPartial; - -- (PushMessageContentAttachmentPointerBuilder*) mergeFrom:(PushMessageContentAttachmentPointer*) other; -- (PushMessageContentAttachmentPointerBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input; -- (PushMessageContentAttachmentPointerBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; - -- (BOOL) hasId; -- (UInt64) id; -- (PushMessageContentAttachmentPointerBuilder*) setId:(UInt64) value; -- (PushMessageContentAttachmentPointerBuilder*) clearId; - -- (BOOL) hasContentType; -- (NSString*) contentType; -- (PushMessageContentAttachmentPointerBuilder*) setContentType:(NSString*) value; -- (PushMessageContentAttachmentPointerBuilder*) clearContentType; - -- (BOOL) hasKey; -- (NSData*) key; -- (PushMessageContentAttachmentPointerBuilder*) setKey:(NSData*) value; -- (PushMessageContentAttachmentPointerBuilder*) clearKey; -@end - -@interface PushMessageContentGroupContext : PBGeneratedMessage { -@private - BOOL hasName_:1; - BOOL hasAvatar_:1; - BOOL hasId_:1; - BOOL hasType_:1; - NSString* name; - PushMessageContentAttachmentPointer* avatar; - NSData* id; - PushMessageContentGroupContextType type; - NSMutableArray * membersArray; -} -- (BOOL) hasId; -- (BOOL) hasType; -- (BOOL) hasName; -- (BOOL) hasAvatar; -@property (readonly, strong) NSData* id; -@property (readonly) PushMessageContentGroupContextType type; -@property (readonly, strong) NSString* name; -@property (readonly, strong) PushMessageContentAttachmentPointer* avatar; -- (NSArray *)members; -- (NSString*)membersAtIndex:(NSUInteger)index; - -+ (PushMessageContentGroupContext*) defaultInstance; -- (PushMessageContentGroupContext*) defaultInstance; - -- (BOOL) isInitialized; -- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output; -- (PushMessageContentGroupContextBuilder*) builder; -+ (PushMessageContentGroupContextBuilder*) builder; -+ (PushMessageContentGroupContextBuilder*) builderWithPrototype:(PushMessageContentGroupContext*) prototype; -- (PushMessageContentGroupContextBuilder*) toBuilder; - -+ (PushMessageContentGroupContext*) parseFromData:(NSData*) data; -+ (PushMessageContentGroupContext*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -+ (PushMessageContentGroupContext*) parseFromInputStream:(NSInputStream*) input; -+ (PushMessageContentGroupContext*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -+ (PushMessageContentGroupContext*) parseFromCodedInputStream:(PBCodedInputStream*) input; -+ (PushMessageContentGroupContext*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -@end - -@interface PushMessageContentGroupContextBuilder : PBGeneratedMessageBuilder { -@private - PushMessageContentGroupContext* result; -} - -- (PushMessageContentGroupContext*) defaultInstance; - -- (PushMessageContentGroupContextBuilder*) clear; -- (PushMessageContentGroupContextBuilder*) clone; - -- (PushMessageContentGroupContext*) build; -- (PushMessageContentGroupContext*) buildPartial; - -- (PushMessageContentGroupContextBuilder*) mergeFrom:(PushMessageContentGroupContext*) other; -- (PushMessageContentGroupContextBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input; -- (PushMessageContentGroupContextBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; - -- (BOOL) hasId; -- (NSData*) id; -- (PushMessageContentGroupContextBuilder*) setId:(NSData*) value; -- (PushMessageContentGroupContextBuilder*) clearId; - -- (BOOL) hasType; -- (PushMessageContentGroupContextType) type; -- (PushMessageContentGroupContextBuilder*) setType:(PushMessageContentGroupContextType) value; -- (PushMessageContentGroupContextBuilder*) clearType; - -- (BOOL) hasName; -- (NSString*) name; -- (PushMessageContentGroupContextBuilder*) setName:(NSString*) value; -- (PushMessageContentGroupContextBuilder*) clearName; - -- (NSMutableArray *)members; -- (NSString*)membersAtIndex:(NSUInteger)index; -- (PushMessageContentGroupContextBuilder *)addMembers:(NSString*)value; -- (PushMessageContentGroupContextBuilder *)setMembersArray:(NSArray *)array; -- (PushMessageContentGroupContextBuilder *)clearMembers; - -- (BOOL) hasAvatar; -- (PushMessageContentAttachmentPointer*) avatar; -- (PushMessageContentGroupContextBuilder*) setAvatar:(PushMessageContentAttachmentPointer*) value; -- (PushMessageContentGroupContextBuilder*) setAvatarBuilder:(PushMessageContentAttachmentPointerBuilder*) builderForValue; -- (PushMessageContentGroupContextBuilder*) mergeAvatar:(PushMessageContentAttachmentPointer*) value; -- (PushMessageContentGroupContextBuilder*) clearAvatar; -@end - -@interface PushMessageContentBuilder : PBGeneratedMessageBuilder { -@private - PushMessageContent* result; -} - -- (PushMessageContent*) defaultInstance; - -- (PushMessageContentBuilder*) clear; -- (PushMessageContentBuilder*) clone; - -- (PushMessageContent*) build; -- (PushMessageContent*) buildPartial; - -- (PushMessageContentBuilder*) mergeFrom:(PushMessageContent*) other; -- (PushMessageContentBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input; -- (PushMessageContentBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; - -- (BOOL) hasBody; -- (NSString*) body; -- (PushMessageContentBuilder*) setBody:(NSString*) value; -- (PushMessageContentBuilder*) clearBody; - -- (NSMutableArray *)attachments; -- (PushMessageContentAttachmentPointer*)attachmentsAtIndex:(NSUInteger)index; -- (PushMessageContentBuilder *)addAttachments:(PushMessageContentAttachmentPointer*)value; -- (PushMessageContentBuilder *)setAttachmentsArray:(NSArray *)array; -- (PushMessageContentBuilder *)clearAttachments; - -- (BOOL) hasGroup; -- (PushMessageContentGroupContext*) group; -- (PushMessageContentBuilder*) setGroup:(PushMessageContentGroupContext*) value; -- (PushMessageContentBuilder*) setGroupBuilder:(PushMessageContentGroupContextBuilder*) builderForValue; -- (PushMessageContentBuilder*) mergeGroup:(PushMessageContentGroupContext*) value; -- (PushMessageContentBuilder*) clearGroup; - -- (BOOL) hasFlags; -- (UInt32) flags; -- (PushMessageContentBuilder*) setFlags:(UInt32) value; -- (PushMessageContentBuilder*) clearFlags; -@end - - -// @@protoc_insertion_point(global_scope) diff --git a/Signal/src/textsecure/Messages/IncomingPushMessageSignal.pb.m b/Signal/src/textsecure/Messages/IncomingPushMessageSignal.pb.m deleted file mode 100644 index f3c13466b..000000000 --- a/Signal/src/textsecure/Messages/IncomingPushMessageSignal.pb.m +++ /dev/null @@ -1,1580 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! - -#import "IncomingPushMessageSignal.pb.h" -// @@protoc_insertion_point(imports) - -@implementation IncomingPushMessageSignalRoot -static PBExtensionRegistry* extensionRegistry = nil; -+ (PBExtensionRegistry*) extensionRegistry { - return extensionRegistry; -} - -+ (void) initialize { - if (self == [IncomingPushMessageSignalRoot class]) { - PBMutableExtensionRegistry* registry = [PBMutableExtensionRegistry registry]; - [self registerAllExtensions:registry]; - extensionRegistry = registry; - } -} -+ (void) registerAllExtensions:(PBMutableExtensionRegistry*) registry { -} -@end - -@interface IncomingPushMessageSignal () -@property IncomingPushMessageSignalType type; -@property (strong) NSString* source; -@property UInt32 sourceDevice; -@property (strong) NSString* relay; -@property UInt64 timestamp; -@property (strong) NSData* message; -@end - -@implementation IncomingPushMessageSignal - -- (BOOL) hasType { - return !!hasType_; -} -- (void) setHasType:(BOOL) value_ { - hasType_ = !!value_; -} -@synthesize type; -- (BOOL) hasSource { - return !!hasSource_; -} -- (void) setHasSource:(BOOL) value_ { - hasSource_ = !!value_; -} -@synthesize source; -- (BOOL) hasSourceDevice { - return !!hasSourceDevice_; -} -- (void) setHasSourceDevice:(BOOL) value_ { - hasSourceDevice_ = !!value_; -} -@synthesize sourceDevice; -- (BOOL) hasRelay { - return !!hasRelay_; -} -- (void) setHasRelay:(BOOL) value_ { - hasRelay_ = !!value_; -} -@synthesize relay; -- (BOOL) hasTimestamp { - return !!hasTimestamp_; -} -- (void) setHasTimestamp:(BOOL) value_ { - hasTimestamp_ = !!value_; -} -@synthesize timestamp; -- (BOOL) hasMessage { - return !!hasMessage_; -} -- (void) setHasMessage:(BOOL) value_ { - hasMessage_ = !!value_; -} -@synthesize message; -- (id) init { - if ((self = [super init])) { - self.type = IncomingPushMessageSignalTypeUnknown; - self.source = @""; - self.sourceDevice = 0; - self.relay = @""; - self.timestamp = 0L; - self.message = [NSData data]; - } - return self; -} -static IncomingPushMessageSignal* defaultIncomingPushMessageSignalInstance = nil; -+ (void) initialize { - if (self == [IncomingPushMessageSignal class]) { - defaultIncomingPushMessageSignalInstance = [[IncomingPushMessageSignal alloc] init]; - } -} -+ (IncomingPushMessageSignal*) defaultInstance { - return defaultIncomingPushMessageSignalInstance; -} -- (IncomingPushMessageSignal*) defaultInstance { - return defaultIncomingPushMessageSignalInstance; -} -- (BOOL) isInitialized { - return YES; -} -- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output { - if (self.hasType) { - [output writeEnum:1 value:self.type]; - } - if (self.hasSource) { - [output writeString:2 value:self.source]; - } - if (self.hasRelay) { - [output writeString:3 value:self.relay]; - } - if (self.hasTimestamp) { - [output writeUInt64:5 value:self.timestamp]; - } - if (self.hasMessage) { - [output writeData:6 value:self.message]; - } - if (self.hasSourceDevice) { - [output writeUInt32:7 value:self.sourceDevice]; - } - [self.unknownFields writeToCodedOutputStream:output]; -} -- (SInt32) serializedSize { - __block SInt32 size_ = memoizedSerializedSize; - if (size_ != -1) { - return size_; - } - - size_ = 0; - if (self.hasType) { - size_ += computeEnumSize(1, self.type); - } - if (self.hasSource) { - size_ += computeStringSize(2, self.source); - } - if (self.hasRelay) { - size_ += computeStringSize(3, self.relay); - } - if (self.hasTimestamp) { - size_ += computeUInt64Size(5, self.timestamp); - } - if (self.hasMessage) { - size_ += computeDataSize(6, self.message); - } - if (self.hasSourceDevice) { - size_ += computeUInt32Size(7, self.sourceDevice); - } - size_ += self.unknownFields.serializedSize; - memoizedSerializedSize = size_; - return size_; -} -+ (IncomingPushMessageSignal*) parseFromData:(NSData*) data { - return (IncomingPushMessageSignal*)[[[IncomingPushMessageSignal builder] mergeFromData:data] build]; -} -+ (IncomingPushMessageSignal*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (IncomingPushMessageSignal*)[[[IncomingPushMessageSignal builder] mergeFromData:data extensionRegistry:extensionRegistry] build]; -} -+ (IncomingPushMessageSignal*) parseFromInputStream:(NSInputStream*) input { - return (IncomingPushMessageSignal*)[[[IncomingPushMessageSignal builder] mergeFromInputStream:input] build]; -} -+ (IncomingPushMessageSignal*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (IncomingPushMessageSignal*)[[[IncomingPushMessageSignal builder] mergeFromInputStream:input extensionRegistry:extensionRegistry] build]; -} -+ (IncomingPushMessageSignal*) parseFromCodedInputStream:(PBCodedInputStream*) input { - return (IncomingPushMessageSignal*)[[[IncomingPushMessageSignal builder] mergeFromCodedInputStream:input] build]; -} -+ (IncomingPushMessageSignal*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (IncomingPushMessageSignal*)[[[IncomingPushMessageSignal builder] mergeFromCodedInputStream:input extensionRegistry:extensionRegistry] build]; -} -+ (IncomingPushMessageSignalBuilder*) builder { - return [[IncomingPushMessageSignalBuilder alloc] init]; -} -+ (IncomingPushMessageSignalBuilder*) builderWithPrototype:(IncomingPushMessageSignal*) prototype { - return [[IncomingPushMessageSignal builder] mergeFrom:prototype]; -} -- (IncomingPushMessageSignalBuilder*) builder { - return [IncomingPushMessageSignal builder]; -} -- (IncomingPushMessageSignalBuilder*) toBuilder { - return [IncomingPushMessageSignal builderWithPrototype:self]; -} -- (void) writeDescriptionTo:(NSMutableString*) output withIndent:(NSString*) indent { - if (self.hasType) { - [output appendFormat:@"%@%@: %d\n", indent, @"type", self.type]; - } - if (self.hasSource) { - [output appendFormat:@"%@%@: %@\n", indent, @"source", self.source]; - } - if (self.hasRelay) { - [output appendFormat:@"%@%@: %@\n", indent, @"relay", self.relay]; - } - if (self.hasTimestamp) { - [output appendFormat:@"%@%@: %@\n", indent, @"timestamp", [NSNumber numberWithLongLong:self.timestamp]]; - } - if (self.hasMessage) { - [output appendFormat:@"%@%@: %@\n", indent, @"message", self.message]; - } - if (self.hasSourceDevice) { - [output appendFormat:@"%@%@: %@\n", indent, @"sourceDevice", [NSNumber numberWithInteger:self.sourceDevice]]; - } - [self.unknownFields writeDescriptionTo:output withIndent:indent]; -} -- (BOOL) isEqual:(id)other { - if (other == self) { - return YES; - } - if (![other isKindOfClass:[IncomingPushMessageSignal class]]) { - return NO; - } - IncomingPushMessageSignal *otherMessage = other; - return - self.hasType == otherMessage.hasType && - (!self.hasType || self.type == otherMessage.type) && - self.hasSource == otherMessage.hasSource && - (!self.hasSource || [self.source isEqual:otherMessage.source]) && - self.hasRelay == otherMessage.hasRelay && - (!self.hasRelay || [self.relay isEqual:otherMessage.relay]) && - self.hasTimestamp == otherMessage.hasTimestamp && - (!self.hasTimestamp || self.timestamp == otherMessage.timestamp) && - self.hasMessage == otherMessage.hasMessage && - (!self.hasMessage || [self.message isEqual:otherMessage.message]) && - self.hasSourceDevice == otherMessage.hasSourceDevice && - (!self.hasSourceDevice || self.sourceDevice == otherMessage.sourceDevice) && - (self.unknownFields == otherMessage.unknownFields || (self.unknownFields != nil && [self.unknownFields isEqual:otherMessage.unknownFields])); -} -- (NSUInteger) hash { - __block NSUInteger hashCode = 7; - if (self.hasType) { - hashCode = hashCode * 31 + self.type; - } - if (self.hasSource) { - hashCode = hashCode * 31 + [self.source hash]; - } - if (self.hasRelay) { - hashCode = hashCode * 31 + [self.relay hash]; - } - if (self.hasTimestamp) { - hashCode = hashCode * 31 + [[NSNumber numberWithLongLong:self.timestamp] hash]; - } - if (self.hasMessage) { - hashCode = hashCode * 31 + [self.message hash]; - } - if (self.hasSourceDevice) { - hashCode = hashCode * 31 + [[NSNumber numberWithInteger:self.sourceDevice] hash]; - } - hashCode = hashCode * 31 + [self.unknownFields hash]; - return hashCode; -} -@end - -BOOL IncomingPushMessageSignalTypeIsValidValue(IncomingPushMessageSignalType value) { - switch (value) { - case IncomingPushMessageSignalTypeUnknown: - case IncomingPushMessageSignalTypeCiphertext: - case IncomingPushMessageSignalTypeKeyExchange: - case IncomingPushMessageSignalTypePrekeyBundle: - case IncomingPushMessageSignalTypePlaintext: - case IncomingPushMessageSignalTypeReceipt: - return YES; - default: - return NO; - } -} -@interface IncomingPushMessageSignalBuilder() -@property (strong) IncomingPushMessageSignal* result; -@end - -@implementation IncomingPushMessageSignalBuilder -@synthesize result; -- (id) init { - if ((self = [super init])) { - self.result = [[IncomingPushMessageSignal alloc] init]; - } - return self; -} -- (PBGeneratedMessage*) internalGetResult { - return result; -} -- (IncomingPushMessageSignalBuilder*) clear { - self.result = [[IncomingPushMessageSignal alloc] init]; - return self; -} -- (IncomingPushMessageSignalBuilder*) clone { - return [IncomingPushMessageSignal builderWithPrototype:result]; -} -- (IncomingPushMessageSignal*) defaultInstance { - return [IncomingPushMessageSignal defaultInstance]; -} -- (IncomingPushMessageSignal*) build { - [self checkInitialized]; - return [self buildPartial]; -} -- (IncomingPushMessageSignal*) buildPartial { - IncomingPushMessageSignal* returnMe = result; - self.result = nil; - return returnMe; -} -- (IncomingPushMessageSignalBuilder*) mergeFrom:(IncomingPushMessageSignal*) other { - if (other == [IncomingPushMessageSignal defaultInstance]) { - return self; - } - if (other.hasType) { - [self setType:other.type]; - } - if (other.hasSource) { - [self setSource:other.source]; - } - if (other.hasSourceDevice) { - [self setSourceDevice:other.sourceDevice]; - } - if (other.hasRelay) { - [self setRelay:other.relay]; - } - if (other.hasTimestamp) { - [self setTimestamp:other.timestamp]; - } - if (other.hasMessage) { - [self setMessage:other.message]; - } - [self mergeUnknownFields:other.unknownFields]; - return self; -} -- (IncomingPushMessageSignalBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input { - return [self mergeFromCodedInputStream:input extensionRegistry:[PBExtensionRegistry emptyRegistry]]; -} -- (IncomingPushMessageSignalBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - PBUnknownFieldSetBuilder* unknownFields = [PBUnknownFieldSet builderWithUnknownFields:self.unknownFields]; - while (YES) { - SInt32 tag = [input readTag]; - switch (tag) { - case 0: - [self setUnknownFields:[unknownFields build]]; - return self; - default: { - if (![self parseUnknownField:input unknownFields:unknownFields extensionRegistry:extensionRegistry tag:tag]) { - [self setUnknownFields:[unknownFields build]]; - return self; - } - break; - } - case 8: { - IncomingPushMessageSignalType value = (IncomingPushMessageSignalType)[input readEnum]; - if (IncomingPushMessageSignalTypeIsValidValue(value)) { - [self setType:value]; - } else { - [unknownFields mergeVarintField:1 value:value]; - } - break; - } - case 18: { - [self setSource:[input readString]]; - break; - } - case 26: { - [self setRelay:[input readString]]; - break; - } - case 40: { - [self setTimestamp:[input readUInt64]]; - break; - } - case 50: { - [self setMessage:[input readData]]; - break; - } - case 56: { - [self setSourceDevice:[input readUInt32]]; - break; - } - } - } -} -- (BOOL) hasType { - return result.hasType; -} -- (IncomingPushMessageSignalType) type { - return result.type; -} -- (IncomingPushMessageSignalBuilder*) setType:(IncomingPushMessageSignalType) value { - result.hasType = YES; - result.type = value; - return self; -} -- (IncomingPushMessageSignalBuilder*) clearType { - result.hasType = NO; - result.type = IncomingPushMessageSignalTypeUnknown; - return self; -} -- (BOOL) hasSource { - return result.hasSource; -} -- (NSString*) source { - return result.source; -} -- (IncomingPushMessageSignalBuilder*) setSource:(NSString*) value { - result.hasSource = YES; - result.source = value; - return self; -} -- (IncomingPushMessageSignalBuilder*) clearSource { - result.hasSource = NO; - result.source = @""; - return self; -} -- (BOOL) hasSourceDevice { - return result.hasSourceDevice; -} -- (UInt32) sourceDevice { - return result.sourceDevice; -} -- (IncomingPushMessageSignalBuilder*) setSourceDevice:(UInt32) value { - result.hasSourceDevice = YES; - result.sourceDevice = value; - return self; -} -- (IncomingPushMessageSignalBuilder*) clearSourceDevice { - result.hasSourceDevice = NO; - result.sourceDevice = 0; - return self; -} -- (BOOL) hasRelay { - return result.hasRelay; -} -- (NSString*) relay { - return result.relay; -} -- (IncomingPushMessageSignalBuilder*) setRelay:(NSString*) value { - result.hasRelay = YES; - result.relay = value; - return self; -} -- (IncomingPushMessageSignalBuilder*) clearRelay { - result.hasRelay = NO; - result.relay = @""; - return self; -} -- (BOOL) hasTimestamp { - return result.hasTimestamp; -} -- (UInt64) timestamp { - return result.timestamp; -} -- (IncomingPushMessageSignalBuilder*) setTimestamp:(UInt64) value { - result.hasTimestamp = YES; - result.timestamp = value; - return self; -} -- (IncomingPushMessageSignalBuilder*) clearTimestamp { - result.hasTimestamp = NO; - result.timestamp = 0L; - return self; -} -- (BOOL) hasMessage { - return result.hasMessage; -} -- (NSData*) message { - return result.message; -} -- (IncomingPushMessageSignalBuilder*) setMessage:(NSData*) value { - result.hasMessage = YES; - result.message = value; - return self; -} -- (IncomingPushMessageSignalBuilder*) clearMessage { - result.hasMessage = NO; - result.message = [NSData data]; - return self; -} -@end - -@interface PushMessageContent () -@property (strong) NSString* body; -@property (strong) NSMutableArray * attachmentsArray; -@property (strong) PushMessageContentGroupContext* group; -@property UInt32 flags; -@end - -@implementation PushMessageContent - -- (BOOL) hasBody { - return !!hasBody_; -} -- (void) setHasBody:(BOOL) value_ { - hasBody_ = !!value_; -} -@synthesize body; -@synthesize attachmentsArray; -@dynamic attachments; -- (BOOL) hasGroup { - return !!hasGroup_; -} -- (void) setHasGroup:(BOOL) value_ { - hasGroup_ = !!value_; -} -@synthesize group; -- (BOOL) hasFlags { - return !!hasFlags_; -} -- (void) setHasFlags:(BOOL) value_ { - hasFlags_ = !!value_; -} -@synthesize flags; -- (id) init { - if ((self = [super init])) { - self.body = @""; - self.group = [PushMessageContentGroupContext defaultInstance]; - self.flags = 0; - } - return self; -} -static PushMessageContent* defaultPushMessageContentInstance = nil; -+ (void) initialize { - if (self == [PushMessageContent class]) { - defaultPushMessageContentInstance = [[PushMessageContent alloc] init]; - } -} -+ (PushMessageContent*) defaultInstance { - return defaultPushMessageContentInstance; -} -- (PushMessageContent*) defaultInstance { - return defaultPushMessageContentInstance; -} -- (NSArray *)attachments { - return attachmentsArray; -} -- (PushMessageContentAttachmentPointer*)attachmentsAtIndex:(NSUInteger)index { - return [attachmentsArray objectAtIndex:index]; -} -- (BOOL) isInitialized { - return YES; -} -- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output { - if (self.hasBody) { - [output writeString:1 value:self.body]; - } - [self.attachmentsArray enumerateObjectsUsingBlock:^(PushMessageContentAttachmentPointer *element, NSUInteger idx, BOOL *stop) { - [output writeMessage:2 value:element]; - }]; - if (self.hasGroup) { - [output writeMessage:3 value:self.group]; - } - if (self.hasFlags) { - [output writeUInt32:4 value:self.flags]; - } - [self.unknownFields writeToCodedOutputStream:output]; -} -- (SInt32) serializedSize { - __block SInt32 size_ = memoizedSerializedSize; - if (size_ != -1) { - return size_; - } - - size_ = 0; - if (self.hasBody) { - size_ += computeStringSize(1, self.body); - } - [self.attachmentsArray enumerateObjectsUsingBlock:^(PushMessageContentAttachmentPointer *element, NSUInteger idx, BOOL *stop) { - size_ += computeMessageSize(2, element); - }]; - if (self.hasGroup) { - size_ += computeMessageSize(3, self.group); - } - if (self.hasFlags) { - size_ += computeUInt32Size(4, self.flags); - } - size_ += self.unknownFields.serializedSize; - memoizedSerializedSize = size_; - return size_; -} -+ (PushMessageContent*) parseFromData:(NSData*) data { - return (PushMessageContent*)[[[PushMessageContent builder] mergeFromData:data] build]; -} -+ (PushMessageContent*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (PushMessageContent*)[[[PushMessageContent builder] mergeFromData:data extensionRegistry:extensionRegistry] build]; -} -+ (PushMessageContent*) parseFromInputStream:(NSInputStream*) input { - return (PushMessageContent*)[[[PushMessageContent builder] mergeFromInputStream:input] build]; -} -+ (PushMessageContent*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (PushMessageContent*)[[[PushMessageContent builder] mergeFromInputStream:input extensionRegistry:extensionRegistry] build]; -} -+ (PushMessageContent*) parseFromCodedInputStream:(PBCodedInputStream*) input { - return (PushMessageContent*)[[[PushMessageContent builder] mergeFromCodedInputStream:input] build]; -} -+ (PushMessageContent*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (PushMessageContent*)[[[PushMessageContent builder] mergeFromCodedInputStream:input extensionRegistry:extensionRegistry] build]; -} -+ (PushMessageContentBuilder*) builder { - return [[PushMessageContentBuilder alloc] init]; -} -+ (PushMessageContentBuilder*) builderWithPrototype:(PushMessageContent*) prototype { - return [[PushMessageContent builder] mergeFrom:prototype]; -} -- (PushMessageContentBuilder*) builder { - return [PushMessageContent builder]; -} -- (PushMessageContentBuilder*) toBuilder { - return [PushMessageContent builderWithPrototype:self]; -} -- (void) writeDescriptionTo:(NSMutableString*) output withIndent:(NSString*) indent { - if (self.hasBody) { - [output appendFormat:@"%@%@: %@\n", indent, @"body", self.body]; - } - [self.attachmentsArray enumerateObjectsUsingBlock:^(PushMessageContentAttachmentPointer *element, NSUInteger idx, BOOL *stop) { - [output appendFormat:@"%@%@ {\n", indent, @"attachments"]; - [element writeDescriptionTo:output - withIndent:[NSString stringWithFormat:@"%@ ", indent]]; - [output appendFormat:@"%@}\n", indent]; - }]; - if (self.hasGroup) { - [output appendFormat:@"%@%@ {\n", indent, @"group"]; - [self.group writeDescriptionTo:output - withIndent:[NSString stringWithFormat:@"%@ ", indent]]; - [output appendFormat:@"%@}\n", indent]; - } - if (self.hasFlags) { - [output appendFormat:@"%@%@: %@\n", indent, @"flags", [NSNumber numberWithInteger:self.flags]]; - } - [self.unknownFields writeDescriptionTo:output withIndent:indent]; -} -- (BOOL) isEqual:(id)other { - if (other == self) { - return YES; - } - if (![other isKindOfClass:[PushMessageContent class]]) { - return NO; - } - PushMessageContent *otherMessage = other; - return - self.hasBody == otherMessage.hasBody && - (!self.hasBody || [self.body isEqual:otherMessage.body]) && - [self.attachmentsArray isEqualToArray:otherMessage.attachmentsArray] && - self.hasGroup == otherMessage.hasGroup && - (!self.hasGroup || [self.group isEqual:otherMessage.group]) && - self.hasFlags == otherMessage.hasFlags && - (!self.hasFlags || self.flags == otherMessage.flags) && - (self.unknownFields == otherMessage.unknownFields || (self.unknownFields != nil && [self.unknownFields isEqual:otherMessage.unknownFields])); -} -- (NSUInteger) hash { - __block NSUInteger hashCode = 7; - if (self.hasBody) { - hashCode = hashCode * 31 + [self.body hash]; - } - [self.attachmentsArray enumerateObjectsUsingBlock:^(PushMessageContentAttachmentPointer *element, NSUInteger idx, BOOL *stop) { - hashCode = hashCode * 31 + [element hash]; - }]; - if (self.hasGroup) { - hashCode = hashCode * 31 + [self.group hash]; - } - if (self.hasFlags) { - hashCode = hashCode * 31 + [[NSNumber numberWithInteger:self.flags] hash]; - } - hashCode = hashCode * 31 + [self.unknownFields hash]; - return hashCode; -} -@end - -BOOL PushMessageContentFlagsIsValidValue(PushMessageContentFlags value) { - switch (value) { - case PushMessageContentFlagsEndSession: - return YES; - default: - return NO; - } -} -@interface PushMessageContentAttachmentPointer () -@property UInt64 id; -@property (strong) NSString* contentType; -@property (strong) NSData* key; -@end - -@implementation PushMessageContentAttachmentPointer - -- (BOOL) hasId { - return !!hasId_; -} -- (void) setHasId:(BOOL) value_ { - hasId_ = !!value_; -} -@synthesize id; -- (BOOL) hasContentType { - return !!hasContentType_; -} -- (void) setHasContentType:(BOOL) value_ { - hasContentType_ = !!value_; -} -@synthesize contentType; -- (BOOL) hasKey { - return !!hasKey_; -} -- (void) setHasKey:(BOOL) value_ { - hasKey_ = !!value_; -} -@synthesize key; -- (id) init { - if ((self = [super init])) { - self.id = 0L; - self.contentType = @""; - self.key = [NSData data]; - } - return self; -} -static PushMessageContentAttachmentPointer* defaultPushMessageContentAttachmentPointerInstance = nil; -+ (void) initialize { - if (self == [PushMessageContentAttachmentPointer class]) { - defaultPushMessageContentAttachmentPointerInstance = [[PushMessageContentAttachmentPointer alloc] init]; - } -} -+ (PushMessageContentAttachmentPointer*) defaultInstance { - return defaultPushMessageContentAttachmentPointerInstance; -} -- (PushMessageContentAttachmentPointer*) defaultInstance { - return defaultPushMessageContentAttachmentPointerInstance; -} -- (BOOL) isInitialized { - return YES; -} -- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output { - if (self.hasId) { - [output writeFixed64:1 value:self.id]; - } - if (self.hasContentType) { - [output writeString:2 value:self.contentType]; - } - if (self.hasKey) { - [output writeData:3 value:self.key]; - } - [self.unknownFields writeToCodedOutputStream:output]; -} -- (SInt32) serializedSize { - __block SInt32 size_ = memoizedSerializedSize; - if (size_ != -1) { - return size_; - } - - size_ = 0; - if (self.hasId) { - size_ += computeFixed64Size(1, self.id); - } - if (self.hasContentType) { - size_ += computeStringSize(2, self.contentType); - } - if (self.hasKey) { - size_ += computeDataSize(3, self.key); - } - size_ += self.unknownFields.serializedSize; - memoizedSerializedSize = size_; - return size_; -} -+ (PushMessageContentAttachmentPointer*) parseFromData:(NSData*) data { - return (PushMessageContentAttachmentPointer*)[[[PushMessageContentAttachmentPointer builder] mergeFromData:data] build]; -} -+ (PushMessageContentAttachmentPointer*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (PushMessageContentAttachmentPointer*)[[[PushMessageContentAttachmentPointer builder] mergeFromData:data extensionRegistry:extensionRegistry] build]; -} -+ (PushMessageContentAttachmentPointer*) parseFromInputStream:(NSInputStream*) input { - return (PushMessageContentAttachmentPointer*)[[[PushMessageContentAttachmentPointer builder] mergeFromInputStream:input] build]; -} -+ (PushMessageContentAttachmentPointer*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (PushMessageContentAttachmentPointer*)[[[PushMessageContentAttachmentPointer builder] mergeFromInputStream:input extensionRegistry:extensionRegistry] build]; -} -+ (PushMessageContentAttachmentPointer*) parseFromCodedInputStream:(PBCodedInputStream*) input { - return (PushMessageContentAttachmentPointer*)[[[PushMessageContentAttachmentPointer builder] mergeFromCodedInputStream:input] build]; -} -+ (PushMessageContentAttachmentPointer*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (PushMessageContentAttachmentPointer*)[[[PushMessageContentAttachmentPointer builder] mergeFromCodedInputStream:input extensionRegistry:extensionRegistry] build]; -} -+ (PushMessageContentAttachmentPointerBuilder*) builder { - return [[PushMessageContentAttachmentPointerBuilder alloc] init]; -} -+ (PushMessageContentAttachmentPointerBuilder*) builderWithPrototype:(PushMessageContentAttachmentPointer*) prototype { - return [[PushMessageContentAttachmentPointer builder] mergeFrom:prototype]; -} -- (PushMessageContentAttachmentPointerBuilder*) builder { - return [PushMessageContentAttachmentPointer builder]; -} -- (PushMessageContentAttachmentPointerBuilder*) toBuilder { - return [PushMessageContentAttachmentPointer builderWithPrototype:self]; -} -- (void) writeDescriptionTo:(NSMutableString*) output withIndent:(NSString*) indent { - if (self.hasId) { - [output appendFormat:@"%@%@: %@\n", indent, @"id", [NSNumber numberWithLongLong:self.id]]; - } - if (self.hasContentType) { - [output appendFormat:@"%@%@: %@\n", indent, @"contentType", self.contentType]; - } - if (self.hasKey) { - [output appendFormat:@"%@%@: %@\n", indent, @"key", self.key]; - } - [self.unknownFields writeDescriptionTo:output withIndent:indent]; -} -- (BOOL) isEqual:(id)other { - if (other == self) { - return YES; - } - if (![other isKindOfClass:[PushMessageContentAttachmentPointer class]]) { - return NO; - } - PushMessageContentAttachmentPointer *otherMessage = other; - return - self.hasId == otherMessage.hasId && - (!self.hasId || self.id == otherMessage.id) && - self.hasContentType == otherMessage.hasContentType && - (!self.hasContentType || [self.contentType isEqual:otherMessage.contentType]) && - self.hasKey == otherMessage.hasKey && - (!self.hasKey || [self.key isEqual:otherMessage.key]) && - (self.unknownFields == otherMessage.unknownFields || (self.unknownFields != nil && [self.unknownFields isEqual:otherMessage.unknownFields])); -} -- (NSUInteger) hash { - __block NSUInteger hashCode = 7; - if (self.hasId) { - hashCode = hashCode * 31 + [[NSNumber numberWithLongLong:self.id] hash]; - } - if (self.hasContentType) { - hashCode = hashCode * 31 + [self.contentType hash]; - } - if (self.hasKey) { - hashCode = hashCode * 31 + [self.key hash]; - } - hashCode = hashCode * 31 + [self.unknownFields hash]; - return hashCode; -} -@end - -@interface PushMessageContentAttachmentPointerBuilder() -@property (strong) PushMessageContentAttachmentPointer* result; -@end - -@implementation PushMessageContentAttachmentPointerBuilder -@synthesize result; -- (id) init { - if ((self = [super init])) { - self.result = [[PushMessageContentAttachmentPointer alloc] init]; - } - return self; -} -- (PBGeneratedMessage*) internalGetResult { - return result; -} -- (PushMessageContentAttachmentPointerBuilder*) clear { - self.result = [[PushMessageContentAttachmentPointer alloc] init]; - return self; -} -- (PushMessageContentAttachmentPointerBuilder*) clone { - return [PushMessageContentAttachmentPointer builderWithPrototype:result]; -} -- (PushMessageContentAttachmentPointer*) defaultInstance { - return [PushMessageContentAttachmentPointer defaultInstance]; -} -- (PushMessageContentAttachmentPointer*) build { - [self checkInitialized]; - return [self buildPartial]; -} -- (PushMessageContentAttachmentPointer*) buildPartial { - PushMessageContentAttachmentPointer* returnMe = result; - self.result = nil; - return returnMe; -} -- (PushMessageContentAttachmentPointerBuilder*) mergeFrom:(PushMessageContentAttachmentPointer*) other { - if (other == [PushMessageContentAttachmentPointer defaultInstance]) { - return self; - } - if (other.hasId) { - [self setId:other.id]; - } - if (other.hasContentType) { - [self setContentType:other.contentType]; - } - if (other.hasKey) { - [self setKey:other.key]; - } - [self mergeUnknownFields:other.unknownFields]; - return self; -} -- (PushMessageContentAttachmentPointerBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input { - return [self mergeFromCodedInputStream:input extensionRegistry:[PBExtensionRegistry emptyRegistry]]; -} -- (PushMessageContentAttachmentPointerBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - PBUnknownFieldSetBuilder* unknownFields = [PBUnknownFieldSet builderWithUnknownFields:self.unknownFields]; - while (YES) { - SInt32 tag = [input readTag]; - switch (tag) { - case 0: - [self setUnknownFields:[unknownFields build]]; - return self; - default: { - if (![self parseUnknownField:input unknownFields:unknownFields extensionRegistry:extensionRegistry tag:tag]) { - [self setUnknownFields:[unknownFields build]]; - return self; - } - break; - } - case 9: { - [self setId:[input readFixed64]]; - break; - } - case 18: { - [self setContentType:[input readString]]; - break; - } - case 26: { - [self setKey:[input readData]]; - break; - } - } - } -} -- (BOOL) hasId { - return result.hasId; -} -- (UInt64) id { - return result.id; -} -- (PushMessageContentAttachmentPointerBuilder*) setId:(UInt64) value { - result.hasId = YES; - result.id = value; - return self; -} -- (PushMessageContentAttachmentPointerBuilder*) clearId { - result.hasId = NO; - result.id = 0L; - return self; -} -- (BOOL) hasContentType { - return result.hasContentType; -} -- (NSString*) contentType { - return result.contentType; -} -- (PushMessageContentAttachmentPointerBuilder*) setContentType:(NSString*) value { - result.hasContentType = YES; - result.contentType = value; - return self; -} -- (PushMessageContentAttachmentPointerBuilder*) clearContentType { - result.hasContentType = NO; - result.contentType = @""; - return self; -} -- (BOOL) hasKey { - return result.hasKey; -} -- (NSData*) key { - return result.key; -} -- (PushMessageContentAttachmentPointerBuilder*) setKey:(NSData*) value { - result.hasKey = YES; - result.key = value; - return self; -} -- (PushMessageContentAttachmentPointerBuilder*) clearKey { - result.hasKey = NO; - result.key = [NSData data]; - return self; -} -@end - -@interface PushMessageContentGroupContext () -@property (strong) NSData* id; -@property PushMessageContentGroupContextType type; -@property (strong) NSString* name; -@property (strong) NSMutableArray * membersArray; -@property (strong) PushMessageContentAttachmentPointer* avatar; -@end - -@implementation PushMessageContentGroupContext - -- (BOOL) hasId { - return !!hasId_; -} -- (void) setHasId:(BOOL) value_ { - hasId_ = !!value_; -} -@synthesize id; -- (BOOL) hasType { - return !!hasType_; -} -- (void) setHasType:(BOOL) value_ { - hasType_ = !!value_; -} -@synthesize type; -- (BOOL) hasName { - return !!hasName_; -} -- (void) setHasName:(BOOL) value_ { - hasName_ = !!value_; -} -@synthesize name; -@synthesize membersArray; -- (BOOL) hasAvatar { - return !!hasAvatar_; -} -- (void) setHasAvatar:(BOOL) value_ { - hasAvatar_ = !!value_; -} -@synthesize avatar; -- (id) init { - if ((self = [super init])) { - self.id = [NSData data]; - self.type = PushMessageContentGroupContextTypeUnknown; - self.name = @""; - self.avatar = [PushMessageContentAttachmentPointer defaultInstance]; - } - return self; -} -static PushMessageContentGroupContext* defaultPushMessageContentGroupContextInstance = nil; -+ (void) initialize { - if (self == [PushMessageContentGroupContext class]) { - defaultPushMessageContentGroupContextInstance = [[PushMessageContentGroupContext alloc] init]; - } -} -+ (PushMessageContentGroupContext*) defaultInstance { - return defaultPushMessageContentGroupContextInstance; -} -- (PushMessageContentGroupContext*) defaultInstance { - return defaultPushMessageContentGroupContextInstance; -} -- (NSArray *)members { - return membersArray; -} -- (NSString*)membersAtIndex:(NSUInteger)index { - return [membersArray objectAtIndex:index]; -} -- (BOOL) isInitialized { - return YES; -} -- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output { - if (self.hasId) { - [output writeData:1 value:self.id]; - } - if (self.hasType) { - [output writeEnum:2 value:self.type]; - } - if (self.hasName) { - [output writeString:3 value:self.name]; - } - [self.membersArray enumerateObjectsUsingBlock:^(NSString *element, NSUInteger idx, BOOL *stop) { - [output writeString:4 value:element]; - }]; - if (self.hasAvatar) { - [output writeMessage:5 value:self.avatar]; - } - [self.unknownFields writeToCodedOutputStream:output]; -} -- (SInt32) serializedSize { - __block SInt32 size_ = memoizedSerializedSize; - if (size_ != -1) { - return size_; - } - - size_ = 0; - if (self.hasId) { - size_ += computeDataSize(1, self.id); - } - if (self.hasType) { - size_ += computeEnumSize(2, self.type); - } - if (self.hasName) { - size_ += computeStringSize(3, self.name); - } - { - __block SInt32 dataSize = 0; - const NSUInteger count = self.membersArray.count; - [self.membersArray enumerateObjectsUsingBlock:^(NSString *element, NSUInteger idx, BOOL *stop) { - dataSize += computeStringSizeNoTag(element); - }]; - size_ += dataSize; - size_ += (SInt32)(1 * count); - } - if (self.hasAvatar) { - size_ += computeMessageSize(5, self.avatar); - } - size_ += self.unknownFields.serializedSize; - memoizedSerializedSize = size_; - return size_; -} -+ (PushMessageContentGroupContext*) parseFromData:(NSData*) data { - return (PushMessageContentGroupContext*)[[[PushMessageContentGroupContext builder] mergeFromData:data] build]; -} -+ (PushMessageContentGroupContext*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (PushMessageContentGroupContext*)[[[PushMessageContentGroupContext builder] mergeFromData:data extensionRegistry:extensionRegistry] build]; -} -+ (PushMessageContentGroupContext*) parseFromInputStream:(NSInputStream*) input { - return (PushMessageContentGroupContext*)[[[PushMessageContentGroupContext builder] mergeFromInputStream:input] build]; -} -+ (PushMessageContentGroupContext*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (PushMessageContentGroupContext*)[[[PushMessageContentGroupContext builder] mergeFromInputStream:input extensionRegistry:extensionRegistry] build]; -} -+ (PushMessageContentGroupContext*) parseFromCodedInputStream:(PBCodedInputStream*) input { - return (PushMessageContentGroupContext*)[[[PushMessageContentGroupContext builder] mergeFromCodedInputStream:input] build]; -} -+ (PushMessageContentGroupContext*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (PushMessageContentGroupContext*)[[[PushMessageContentGroupContext builder] mergeFromCodedInputStream:input extensionRegistry:extensionRegistry] build]; -} -+ (PushMessageContentGroupContextBuilder*) builder { - return [[PushMessageContentGroupContextBuilder alloc] init]; -} -+ (PushMessageContentGroupContextBuilder*) builderWithPrototype:(PushMessageContentGroupContext*) prototype { - return [[PushMessageContentGroupContext builder] mergeFrom:prototype]; -} -- (PushMessageContentGroupContextBuilder*) builder { - return [PushMessageContentGroupContext builder]; -} -- (PushMessageContentGroupContextBuilder*) toBuilder { - return [PushMessageContentGroupContext builderWithPrototype:self]; -} -- (void) writeDescriptionTo:(NSMutableString*) output withIndent:(NSString*) indent { - if (self.hasId) { - [output appendFormat:@"%@%@: %@\n", indent, @"id", self.id]; - } - if (self.hasType) { - [output appendFormat:@"%@%@: %d\n", indent, @"type", self.type]; - } - if (self.hasName) { - [output appendFormat:@"%@%@: %@\n", indent, @"name", self.name]; - } - [self.membersArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - [output appendFormat:@"%@%@: %@\n", indent, @"members", obj]; - }]; - if (self.hasAvatar) { - [output appendFormat:@"%@%@ {\n", indent, @"avatar"]; - [self.avatar writeDescriptionTo:output - withIndent:[NSString stringWithFormat:@"%@ ", indent]]; - [output appendFormat:@"%@}\n", indent]; - } - [self.unknownFields writeDescriptionTo:output withIndent:indent]; -} -- (BOOL) isEqual:(id)other { - if (other == self) { - return YES; - } - if (![other isKindOfClass:[PushMessageContentGroupContext class]]) { - return NO; - } - PushMessageContentGroupContext *otherMessage = other; - return - self.hasId == otherMessage.hasId && - (!self.hasId || [self.id isEqual:otherMessage.id]) && - self.hasType == otherMessage.hasType && - (!self.hasType || self.type == otherMessage.type) && - self.hasName == otherMessage.hasName && - (!self.hasName || [self.name isEqual:otherMessage.name]) && - [self.membersArray isEqualToArray:otherMessage.membersArray] && - self.hasAvatar == otherMessage.hasAvatar && - (!self.hasAvatar || [self.avatar isEqual:otherMessage.avatar]) && - (self.unknownFields == otherMessage.unknownFields || (self.unknownFields != nil && [self.unknownFields isEqual:otherMessage.unknownFields])); -} -- (NSUInteger) hash { - __block NSUInteger hashCode = 7; - if (self.hasId) { - hashCode = hashCode * 31 + [self.id hash]; - } - if (self.hasType) { - hashCode = hashCode * 31 + self.type; - } - if (self.hasName) { - hashCode = hashCode * 31 + [self.name hash]; - } - [self.membersArray enumerateObjectsUsingBlock:^(id element, NSUInteger idx, BOOL *stop) { - hashCode = hashCode * 31 + [element hash]; - }]; - if (self.hasAvatar) { - hashCode = hashCode * 31 + [self.avatar hash]; - } - hashCode = hashCode * 31 + [self.unknownFields hash]; - return hashCode; -} -@end - -BOOL PushMessageContentGroupContextTypeIsValidValue(PushMessageContentGroupContextType value) { - switch (value) { - case PushMessageContentGroupContextTypeUnknown: - case PushMessageContentGroupContextTypeUpdate: - case PushMessageContentGroupContextTypeDeliver: - case PushMessageContentGroupContextTypeQuit: - return YES; - default: - return NO; - } -} -@interface PushMessageContentGroupContextBuilder() -@property (strong) PushMessageContentGroupContext* result; -@end - -@implementation PushMessageContentGroupContextBuilder -@synthesize result; -- (id) init { - if ((self = [super init])) { - self.result = [[PushMessageContentGroupContext alloc] init]; - } - return self; -} -- (PBGeneratedMessage*) internalGetResult { - return result; -} -- (PushMessageContentGroupContextBuilder*) clear { - self.result = [[PushMessageContentGroupContext alloc] init]; - return self; -} -- (PushMessageContentGroupContextBuilder*) clone { - return [PushMessageContentGroupContext builderWithPrototype:result]; -} -- (PushMessageContentGroupContext*) defaultInstance { - return [PushMessageContentGroupContext defaultInstance]; -} -- (PushMessageContentGroupContext*) build { - [self checkInitialized]; - return [self buildPartial]; -} -- (PushMessageContentGroupContext*) buildPartial { - PushMessageContentGroupContext* returnMe = result; - self.result = nil; - return returnMe; -} -- (PushMessageContentGroupContextBuilder*) mergeFrom:(PushMessageContentGroupContext*) other { - if (other == [PushMessageContentGroupContext defaultInstance]) { - return self; - } - if (other.hasId) { - [self setId:other.id]; - } - if (other.hasType) { - [self setType:other.type]; - } - if (other.hasName) { - [self setName:other.name]; - } - if (other.membersArray.count > 0) { - if (result.membersArray == nil) { - result.membersArray = [[NSMutableArray alloc] initWithArray:other.membersArray]; - } else { - [result.membersArray addObjectsFromArray:other.membersArray]; - } - } - if (other.hasAvatar) { - [self mergeAvatar:other.avatar]; - } - [self mergeUnknownFields:other.unknownFields]; - return self; -} -- (PushMessageContentGroupContextBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input { - return [self mergeFromCodedInputStream:input extensionRegistry:[PBExtensionRegistry emptyRegistry]]; -} -- (PushMessageContentGroupContextBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - PBUnknownFieldSetBuilder* unknownFields = [PBUnknownFieldSet builderWithUnknownFields:self.unknownFields]; - while (YES) { - SInt32 tag = [input readTag]; - switch (tag) { - case 0: - [self setUnknownFields:[unknownFields build]]; - return self; - default: { - if (![self parseUnknownField:input unknownFields:unknownFields extensionRegistry:extensionRegistry tag:tag]) { - [self setUnknownFields:[unknownFields build]]; - return self; - } - break; - } - case 10: { - [self setId:[input readData]]; - break; - } - case 16: { - PushMessageContentGroupContextType value = (PushMessageContentGroupContextType)[input readEnum]; - if (PushMessageContentGroupContextTypeIsValidValue(value)) { - [self setType:value]; - } else { - [unknownFields mergeVarintField:2 value:value]; - } - break; - } - case 26: { - [self setName:[input readString]]; - break; - } - case 34: { - [self addMembers:[input readString]]; - break; - } - case 42: { - PushMessageContentAttachmentPointerBuilder* subBuilder = [PushMessageContentAttachmentPointer builder]; - if (self.hasAvatar) { - [subBuilder mergeFrom:self.avatar]; - } - [input readMessage:subBuilder extensionRegistry:extensionRegistry]; - [self setAvatar:[subBuilder buildPartial]]; - break; - } - } - } -} -- (BOOL) hasId { - return result.hasId; -} -- (NSData*) id { - return result.id; -} -- (PushMessageContentGroupContextBuilder*) setId:(NSData*) value { - result.hasId = YES; - result.id = value; - return self; -} -- (PushMessageContentGroupContextBuilder*) clearId { - result.hasId = NO; - result.id = [NSData data]; - return self; -} -- (BOOL) hasType { - return result.hasType; -} -- (PushMessageContentGroupContextType) type { - return result.type; -} -- (PushMessageContentGroupContextBuilder*) setType:(PushMessageContentGroupContextType) value { - result.hasType = YES; - result.type = value; - return self; -} -- (PushMessageContentGroupContextBuilder*) clearType { - result.hasType = NO; - result.type = PushMessageContentGroupContextTypeUnknown; - return self; -} -- (BOOL) hasName { - return result.hasName; -} -- (NSString*) name { - return result.name; -} -- (PushMessageContentGroupContextBuilder*) setName:(NSString*) value { - result.hasName = YES; - result.name = value; - return self; -} -- (PushMessageContentGroupContextBuilder*) clearName { - result.hasName = NO; - result.name = @""; - return self; -} -- (NSMutableArray *)members { - return result.membersArray; -} -- (NSString*)membersAtIndex:(NSUInteger)index { - return [result membersAtIndex:index]; -} -- (PushMessageContentGroupContextBuilder *)addMembers:(NSString*)value { - if (result.membersArray == nil) { - result.membersArray = [[NSMutableArray alloc]init]; - } - [result.membersArray addObject:value]; - return self; -} -- (PushMessageContentGroupContextBuilder *)setMembersArray:(NSArray *)array { - result.membersArray = [[NSMutableArray alloc] initWithArray:array]; - return self; -} -- (PushMessageContentGroupContextBuilder *)clearMembers { - result.membersArray = nil; - return self; -} -- (BOOL) hasAvatar { - return result.hasAvatar; -} -- (PushMessageContentAttachmentPointer*) avatar { - return result.avatar; -} -- (PushMessageContentGroupContextBuilder*) setAvatar:(PushMessageContentAttachmentPointer*) value { - result.hasAvatar = YES; - result.avatar = value; - return self; -} -- (PushMessageContentGroupContextBuilder*) setAvatarBuilder:(PushMessageContentAttachmentPointerBuilder*) builderForValue { - return [self setAvatar:[builderForValue build]]; -} -- (PushMessageContentGroupContextBuilder*) mergeAvatar:(PushMessageContentAttachmentPointer*) value { - if (result.hasAvatar && - result.avatar != [PushMessageContentAttachmentPointer defaultInstance]) { - result.avatar = - [[[PushMessageContentAttachmentPointer builderWithPrototype:result.avatar] mergeFrom:value] buildPartial]; - } else { - result.avatar = value; - } - result.hasAvatar = YES; - return self; -} -- (PushMessageContentGroupContextBuilder*) clearAvatar { - result.hasAvatar = NO; - result.avatar = [PushMessageContentAttachmentPointer defaultInstance]; - return self; -} -@end - -@interface PushMessageContentBuilder() -@property (strong) PushMessageContent* result; -@end - -@implementation PushMessageContentBuilder -@synthesize result; -- (id) init { - if ((self = [super init])) { - self.result = [[PushMessageContent alloc] init]; - } - return self; -} -- (PBGeneratedMessage*) internalGetResult { - return result; -} -- (PushMessageContentBuilder*) clear { - self.result = [[PushMessageContent alloc] init]; - return self; -} -- (PushMessageContentBuilder*) clone { - return [PushMessageContent builderWithPrototype:result]; -} -- (PushMessageContent*) defaultInstance { - return [PushMessageContent defaultInstance]; -} -- (PushMessageContent*) build { - [self checkInitialized]; - return [self buildPartial]; -} -- (PushMessageContent*) buildPartial { - PushMessageContent* returnMe = result; - self.result = nil; - return returnMe; -} -- (PushMessageContentBuilder*) mergeFrom:(PushMessageContent*) other { - if (other == [PushMessageContent defaultInstance]) { - return self; - } - if (other.hasBody) { - [self setBody:other.body]; - } - if (other.attachmentsArray.count > 0) { - if (result.attachmentsArray == nil) { - result.attachmentsArray = [[NSMutableArray alloc] initWithArray:other.attachmentsArray]; - } else { - [result.attachmentsArray addObjectsFromArray:other.attachmentsArray]; - } - } - if (other.hasGroup) { - [self mergeGroup:other.group]; - } - if (other.hasFlags) { - [self setFlags:other.flags]; - } - [self mergeUnknownFields:other.unknownFields]; - return self; -} -- (PushMessageContentBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input { - return [self mergeFromCodedInputStream:input extensionRegistry:[PBExtensionRegistry emptyRegistry]]; -} -- (PushMessageContentBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - PBUnknownFieldSetBuilder* unknownFields = [PBUnknownFieldSet builderWithUnknownFields:self.unknownFields]; - while (YES) { - SInt32 tag = [input readTag]; - switch (tag) { - case 0: - [self setUnknownFields:[unknownFields build]]; - return self; - default: { - if (![self parseUnknownField:input unknownFields:unknownFields extensionRegistry:extensionRegistry tag:tag]) { - [self setUnknownFields:[unknownFields build]]; - return self; - } - break; - } - case 10: { - [self setBody:[input readString]]; - break; - } - case 18: { - PushMessageContentAttachmentPointerBuilder* subBuilder = [PushMessageContentAttachmentPointer builder]; - [input readMessage:subBuilder extensionRegistry:extensionRegistry]; - [self addAttachments:[subBuilder buildPartial]]; - break; - } - case 26: { - PushMessageContentGroupContextBuilder* subBuilder = [PushMessageContentGroupContext builder]; - if (self.hasGroup) { - [subBuilder mergeFrom:self.group]; - } - [input readMessage:subBuilder extensionRegistry:extensionRegistry]; - [self setGroup:[subBuilder buildPartial]]; - break; - } - case 32: { - [self setFlags:[input readUInt32]]; - break; - } - } - } -} -- (BOOL) hasBody { - return result.hasBody; -} -- (NSString*) body { - return result.body; -} -- (PushMessageContentBuilder*) setBody:(NSString*) value { - result.hasBody = YES; - result.body = value; - return self; -} -- (PushMessageContentBuilder*) clearBody { - result.hasBody = NO; - result.body = @""; - return self; -} -- (NSMutableArray *)attachments { - return result.attachmentsArray; -} -- (PushMessageContentAttachmentPointer*)attachmentsAtIndex:(NSUInteger)index { - return [result attachmentsAtIndex:index]; -} -- (PushMessageContentBuilder *)addAttachments:(PushMessageContentAttachmentPointer*)value { - if (result.attachmentsArray == nil) { - result.attachmentsArray = [[NSMutableArray alloc]init]; - } - [result.attachmentsArray addObject:value]; - return self; -} -- (PushMessageContentBuilder *)setAttachmentsArray:(NSArray *)array { - result.attachmentsArray = [[NSMutableArray alloc]initWithArray:array]; - return self; -} -- (PushMessageContentBuilder *)clearAttachments { - result.attachmentsArray = nil; - return self; -} -- (BOOL) hasGroup { - return result.hasGroup; -} -- (PushMessageContentGroupContext*) group { - return result.group; -} -- (PushMessageContentBuilder*) setGroup:(PushMessageContentGroupContext*) value { - result.hasGroup = YES; - result.group = value; - return self; -} -- (PushMessageContentBuilder*) setGroupBuilder:(PushMessageContentGroupContextBuilder*) builderForValue { - return [self setGroup:[builderForValue build]]; -} -- (PushMessageContentBuilder*) mergeGroup:(PushMessageContentGroupContext*) value { - if (result.hasGroup && - result.group != [PushMessageContentGroupContext defaultInstance]) { - result.group = - [[[PushMessageContentGroupContext builderWithPrototype:result.group] mergeFrom:value] buildPartial]; - } else { - result.group = value; - } - result.hasGroup = YES; - return self; -} -- (PushMessageContentBuilder*) clearGroup { - result.hasGroup = NO; - result.group = [PushMessageContentGroupContext defaultInstance]; - return self; -} -- (BOOL) hasFlags { - return result.hasFlags; -} -- (UInt32) flags { - return result.flags; -} -- (PushMessageContentBuilder*) setFlags:(UInt32) value { - result.hasFlags = YES; - result.flags = value; - return self; -} -- (PushMessageContentBuilder*) clearFlags { - result.hasFlags = NO; - result.flags = 0; - return self; -} -@end - - -// @@protoc_insertion_point(global_scope) diff --git a/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeyErrorMessage.h b/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeyErrorMessage.h deleted file mode 100644 index 4cbfac1b8..000000000 --- a/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeyErrorMessage.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// TSInvalidIdentityKeyErrorMessage.h -// Signal -// -// Created by Frederic Jacobs on 15/02/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import "TSErrorMessage.h" - -@interface TSInvalidIdentityKeyErrorMessage : TSErrorMessage - -- (void)acceptNewIdentityKey; -- (NSString*)newIdentityKey; - -@end diff --git a/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeyErrorMessage.m b/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeyErrorMessage.m deleted file mode 100644 index ded20b1f1..000000000 --- a/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeyErrorMessage.m +++ /dev/null @@ -1,21 +0,0 @@ -// -// TSInvalidIdentityKeyErrorMessage.m -// Signal -// -// Created by Frederic Jacobs on 15/02/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import "TSInvalidIdentityKeyErrorMessage.h" - -@implementation TSInvalidIdentityKeyErrorMessage - -- (void)acceptNewIdentityKey{ - NSAssert(NO, @"Method needs to be implemented in subclasses of TSInvalidIdentityKeyErrorMessage."); -} -- (NSString*)newIdentityKey{ - NSAssert(NO, @"Method needs to be implemented in subclasses of TSInvalidIdentityKeyErrorMessage."); - return nil; -} - -@end diff --git a/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeyReceivingErrorMessage.h b/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeyReceivingErrorMessage.h deleted file mode 100644 index b54b5c216..000000000 --- a/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeyReceivingErrorMessage.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// TSInvalidIdentityKeyErrorMessage.h -// Signal -// -// Created by Frederic Jacobs on 31/12/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSInvalidIdentityKeyErrorMessage.h" - -@interface TSInvalidIdentityKeyReceivingErrorMessage : TSInvalidIdentityKeyErrorMessage - -+ (instancetype)untrustedKeyWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction; - -@end diff --git a/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeyReceivingErrorMessage.m b/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeyReceivingErrorMessage.m deleted file mode 100644 index d02453b86..000000000 --- a/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeyReceivingErrorMessage.m +++ /dev/null @@ -1,99 +0,0 @@ -// -// TSInvalidIdentityKeyErrorMessage.m -// Signal -// -// Created by Frederic Jacobs on 31/12/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import -#import - -#import "TSInvalidIdentityKeyReceivingErrorMessage.h" -#import "TSErrorMessage_privateConstructor.h" -#import "TSDatabaseView.h" -#import "TSStorageManager.h" -#import "TSStorageManager+IdentityKeyStore.h" -#import -#import -#import "TSMessagesManager.h" -#import "TSFingerprintGenerator.h" - -@implementation TSInvalidIdentityKeyReceivingErrorMessage - -- (instancetype)initForUnknownIdentityKeyWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread incomingPushSignal:(NSData*)signal{ - self = [self initWithTimestamp:timestamp inThread:thread failedMessageType:TSErrorMessageWrongTrustedIdentityKey]; - - if (self) { - self.pushSignal = signal; - } - - return self; -} - -+ (instancetype)untrustedKeyWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction{ - TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:preKeyMessage.source transaction:transaction]; - TSInvalidIdentityKeyReceivingErrorMessage *errorMessage = [[self alloc] initForUnknownIdentityKeyWithTimestamp:preKeyMessage.timestamp inThread:contactThread incomingPushSignal:preKeyMessage.data]; - return errorMessage; -} - -- (void)acceptNewIdentityKey{ - if (self.errorType != TSErrorMessageWrongTrustedIdentityKey || !self.pushSignal) { - return; - } - - TSStorageManager *storage = [TSStorageManager sharedManager]; - IncomingPushMessageSignal *signal = [IncomingPushMessageSignal parseFromData:self.pushSignal]; - PreKeyWhisperMessage *message = [[PreKeyWhisperMessage alloc] initWithData:signal.message]; - NSData *newKey = [message.identityKey removeKeyType]; - - [storage saveRemoteIdentity:newKey recipientId:signal.source]; - - [[TSMessagesManager sharedManager] handleMessageSignal:signal]; - - __block NSMutableSet *messagesToDecrypt = [NSMutableSet set]; - - [[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [[transaction ext:TSMessageDatabaseViewExtensionName]enumerateKeysAndObjectsInGroup:self.uniqueThreadId withOptions:NSEnumerationReverse usingBlock:^(NSString *collection, NSString *key, id object, NSUInteger index, BOOL *stop) { - TSInteraction *interaction = (TSInteraction*)object; - - DDLogVerbose(@"Interaction type: %@", interaction.description); - - if ([interaction isKindOfClass:[TSInvalidIdentityKeyErrorMessage class]]) { - TSInvalidIdentityKeyErrorMessage *invalidKeyMessage = (TSInvalidIdentityKeyReceivingErrorMessage*)interaction; - IncomingPushMessageSignal *invalidMessageSignal = [IncomingPushMessageSignal parseFromData:invalidKeyMessage.pushSignal]; - PreKeyWhisperMessage *pkwm = [[PreKeyWhisperMessage alloc] initWithData:invalidMessageSignal.message]; - NSData *newKeyCandidate = [pkwm.identityKey removeKeyType]; - - if ([newKeyCandidate isEqualToData:newKey]) { - [messagesToDecrypt addObject:invalidKeyMessage]; - } - } - }]; - }]; - - - for (TSInvalidIdentityKeyReceivingErrorMessage *errorMessage in messagesToDecrypt) { - - [[TSMessagesManager sharedManager] handleMessageSignal:[IncomingPushMessageSignal parseFromData:errorMessage.pushSignal]]; - - [[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [errorMessage removeWithTransaction:transaction]; - }]; - } - -} - -- (NSString *)newIdentityKey{ - if (!self.pushSignal) { - return @""; - } - - IncomingPushMessageSignal *signal = [IncomingPushMessageSignal parseFromData:self.pushSignal]; - PreKeyWhisperMessage *message = [[PreKeyWhisperMessage alloc] initWithData:signal.message]; - NSData *identityKey = [message.identityKey removeKeyType]; - - return [TSFingerprintGenerator getFingerprintForDisplay:identityKey]; -} - -@end diff --git a/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.h b/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.h deleted file mode 100644 index 004adf78e..000000000 --- a/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// TSInvalidIdentityKeySendingErrorMessage.h -// Signal -// -// Created by Frederic Jacobs on 15/02/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import "TSInvalidIdentityKeyErrorMessage.h" - -@class PreKeyBundle; - -@interface TSInvalidIdentityKeySendingErrorMessage : TSInvalidIdentityKeyErrorMessage - -#define TSInvalidPreKeyBundleKey @"TSInvalidPreKeyBundleKey" -#define TSInvalidRecipientKey @"TSInvalidRecipientKey" - -+ (instancetype)untrustedKeyWithOutgoingMessage:(TSOutgoingMessage*)outgoingMessage - inThread:(TSThread*)thread - forRecipient:(NSString*)recipientId - preKeyBundle:(PreKeyBundle*)preKeyBundle - withTransaction:(YapDatabaseReadWriteTransaction*)transaction; - -- (NSString*)recipientId; - -@end diff --git a/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.m b/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.m deleted file mode 100644 index 12669a455..000000000 --- a/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.m +++ /dev/null @@ -1,85 +0,0 @@ -// -// TSInvalidIdentityKeySendingErrorMessage.m -// Signal -// -// Created by Frederic Jacobs on 15/02/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import "TSOutgoingMessage.h" - -#import - -#import "PreKeyBundle+jsonDict.h" -#import "TSInvalidIdentityKeySendingErrorMessage.h" -#import "TSFingerprintGenerator.h" -#import "TSErrorMessage_privateConstructor.h" -#import "TSStorageManager+IdentityKeyStore.h" -#import "TSMessagesManager+sendMessages.h" - -@interface TSInvalidIdentityKeySendingErrorMessage() - -@property (nonatomic, readonly) PreKeyBundle *preKeyBundle; -@property (nonatomic, readonly) NSString *recipientId; -@property (nonatomic, readonly) NSString *messageId; - -@end - -@implementation TSInvalidIdentityKeySendingErrorMessage - -- (instancetype)initWithOutgoingMessage:(TSOutgoingMessage*)message - inThread:(TSThread*)thread - forRecipient:(NSString*)recipientId - preKeyBundle:(PreKeyBundle*)preKeyBundle - transaction:(YapDatabaseReadWriteTransaction*)transaction -{ - self = [super initWithTimestamp:message.timestamp inThread:thread failedMessageType:TSErrorMessageWrongTrustedIdentityKey]; - - if (self) { - _messageId = message.uniqueId; - _preKeyBundle = preKeyBundle; - _recipientId = recipientId; - } - - return self; -} - -+ (instancetype)untrustedKeyWithOutgoingMessage:(TSOutgoingMessage*)outgoingMessage - inThread:(TSThread*)thread - forRecipient:(NSString*)recipientId - preKeyBundle:(PreKeyBundle*)preKeyBundle - withTransaction:(YapDatabaseReadWriteTransaction*)transaction -{ - TSInvalidIdentityKeySendingErrorMessage *message = [[self alloc] initWithOutgoingMessage:outgoingMessage inThread:thread forRecipient:recipientId preKeyBundle:preKeyBundle transaction:transaction]; - return message; -} - -- (void)acceptNewIdentityKey { - [[TSStorageManager sharedManager] saveRemoteIdentity:[self newKey] recipientId:_recipientId]; - - __block TSOutgoingMessage *message; - __block TSThread *thread; - - [[TSStorageManager sharedManager].newDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - thread = [TSContactThread fetchObjectWithUniqueID:self.uniqueThreadId transaction:transaction]; - message = [TSOutgoingMessage fetchObjectWithUniqueID:_messageId transaction:transaction]; - - [self removeWithTransaction:transaction]; - }]; - - if (message) { - [[TSMessagesManager sharedManager] sendMessage:message inThread:thread success:nil failure:nil]; - } -} - -- (NSString*)newIdentityKey { - NSData *identityKey = [self newKey]; - - return [TSFingerprintGenerator getFingerprintForDisplay:identityKey]; -} - -- (NSData*)newKey { - return [self.preKeyBundle.identityKey removeKeyType]; -} - -@end diff --git a/Signal/src/textsecure/Messages/TSAttachment.h b/Signal/src/textsecure/Messages/TSAttachment.h deleted file mode 100644 index 078b62920..000000000 --- a/Signal/src/textsecure/Messages/TSAttachment.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// TSAttachment.h -// TextSecureKit -// -// Created by Frederic Jacobs on 12/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import -#import "TSYapDatabaseObject.h" - -@interface TSAttachment : TSYapDatabaseObject - -- (NSNumber*)identifier; - -@property (nonatomic, readonly) NSData *encryptionKey; -@property (nonatomic, readonly) NSString *contentType; - -- (instancetype)initWithIdentifier:(NSString*)identifier - encryptionKey:(NSData*)encryptionKey - contentType:(NSString*)contentType; - - -@end diff --git a/Signal/src/textsecure/Messages/TSAttachment.m b/Signal/src/textsecure/Messages/TSAttachment.m deleted file mode 100644 index 16d47055f..000000000 --- a/Signal/src/textsecure/Messages/TSAttachment.m +++ /dev/null @@ -1,52 +0,0 @@ - -// -// TSAttachement.m -// TextSecureKit -// -// Created by Frederic Jacobs on 12/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSAttachment.h" -#import "MIMETypeUtil.h" - -@implementation TSAttachment - -- (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]; -} - -- (NSString*)description { - NSString *attachmentString = NSLocalizedString(@"ATTACHMENT", nil); - - if ([MIMETypeUtil isImage:self.contentType]) { - return [NSString stringWithFormat:@"📷 %@", attachmentString]; - } else if ([MIMETypeUtil isVideo:self.contentType]) { - return [NSString stringWithFormat:@"📽 %@", attachmentString]; - } else if ([MIMETypeUtil isAudio:self.contentType]) { - return [NSString stringWithFormat:@"📻 %@", attachmentString]; - } - - return attachmentString; -} - -@end diff --git a/Signal/src/textsecure/Messages/TSCall.h b/Signal/src/textsecure/Messages/TSCall.h deleted file mode 100644 index 9352bfcdf..000000000 --- a/Signal/src/textsecure/Messages/TSCall.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// TSCall.h -// TextSecureKit -// -// Created by Frederic Jacobs on 12/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import - -#import "TSInteraction.h" -#import "Contact.h" - -#import "RecentCall.h" - -@interface TSCall : TSInteraction - -@property (nonatomic, readonly)RPRecentCallType callType; - -- (instancetype)initWithTimestamp:(uint64_t)timeStamp - withCallNumber:(NSString*)contactNumber - callType:(RPRecentCallType)callType - inThread:(TSContactThread*)thread; - -@end diff --git a/Signal/src/textsecure/Messages/TSCall.m b/Signal/src/textsecure/Messages/TSCall.m deleted file mode 100644 index 1204c0928..000000000 --- a/Signal/src/textsecure/Messages/TSCall.m +++ /dev/null @@ -1,38 +0,0 @@ -// -// TSCall.m -// TextSecureKit -// -// Created by Frederic Jacobs on 12/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSCall.h" - -@implementation TSCall - -- (instancetype)initWithTimestamp:(uint64_t)timeStamp - withCallNumber:(NSString*)contactNumber - callType:(RPRecentCallType)callType - inThread:(TSContactThread*)thread -{ - self = [super initWithTimestamp:timeStamp inThread:thread]; - - if (self) { - _callType = callType; - } - - return self; -} - -- (NSString*)description{ - switch (_callType) { - case RPRecentCallTypeIncoming: - return NSLocalizedString(@"INCOMING_CALL", @""); - case RPRecentCallTypeOutgoing: - return NSLocalizedString(@"OUTGOING_CALL", @""); - case RPRecentCallTypeMissed: - return NSLocalizedString(@"MISSED_CALL", @""); - } -} - -@end diff --git a/Signal/src/textsecure/Messages/TSErrorMessage.h b/Signal/src/textsecure/Messages/TSErrorMessage.h deleted file mode 100644 index a29de82a5..000000000 --- a/Signal/src/textsecure/Messages/TSErrorMessage.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// TSErrorMessage.h -// TextSecureKit -// -// Created by Frederic Jacobs on 12/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSMessage.h" -#import "IncomingPushMessageSignal.pb.h" - -@interface TSErrorMessage : TSMessage - -typedef NS_ENUM(int32_t, TSErrorMessageType){ - TSErrorMessageNoSession, - TSErrorMessageWrongTrustedIdentityKey, - TSErrorMessageInvalidKeyException, - TSErrorMessageMissingKeyId, - TSErrorMessageInvalidMessage, - TSErrorMessageDuplicateMessage, - TSErrorMessageInvalidVersion, -}; - -+ (instancetype)corruptedMessageWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction; -+ (instancetype)invalidVersionWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction; -+ (instancetype)missingKeyIdWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction; -+ (instancetype)invalidKeyExceptionWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction; -+ (instancetype)missingSessionWithSignal:(IncomingPushMessageSignal*)preKeyMessage withTransaction:(YapDatabaseReadWriteTransaction*)transaction; - -@property (nonatomic, readonly) TSErrorMessageType errorType; - -@end diff --git a/Signal/src/textsecure/Messages/TSErrorMessage.m b/Signal/src/textsecure/Messages/TSErrorMessage.m deleted file mode 100644 index 3d95603ce..000000000 --- a/Signal/src/textsecure/Messages/TSErrorMessage.m +++ /dev/null @@ -1,76 +0,0 @@ -// -// TSErrorMessage.m -// TextSecureKit -// -// Created by Frederic Jacobs on 12/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSErrorMessage.h" -#import "TSMessagesManager.h" - -#import "TSErrorMessage_privateConstructor.h" - -@implementation TSErrorMessage - -- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread failedMessageType:(TSErrorMessageType)errorMessageType { - self = [super initWithTimestamp:timestamp inThread:thread messageBody:nil attachments:nil]; - - if (self) { - _errorType = errorMessageType; - } - - [[TSMessagesManager sharedManager] notifyUserForError:self inThread:thread]; - - return self; -} - -- (instancetype)initWithSignal:(IncomingPushMessageSignal*)signal transaction:(YapDatabaseReadWriteTransaction*)transaction failedMessageType:(TSErrorMessageType)errorMessageType{ - TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:signal.source transaction:transaction]; - - return [self initWithTimestamp:signal.timestamp inThread:contactThread failedMessageType:errorMessageType]; -} - -- (NSString*)description{ - switch (_errorType) { - case TSErrorMessageNoSession: - return NSLocalizedString(@"ERROR_MESSAGE_NO_SESSION", @""); - case TSErrorMessageMissingKeyId: - return NSLocalizedString(@"ERROR_MESSAGE_MISSING_KEY", @""); - case TSErrorMessageInvalidMessage: - return NSLocalizedString(@"ERROR_MESSAGE_INVALID_MESSAGE", @""); - case TSErrorMessageInvalidVersion: - return NSLocalizedString(@"ERROR_MESSAGE_INVALID_VERSION", @""); - case TSErrorMessageDuplicateMessage: - return NSLocalizedString(@"ERROR_MESSAGE_DUPLICATE_MESSAGE", @""); - case TSErrorMessageInvalidKeyException: - return NSLocalizedString(@"ERROR_MESSAGE_INVALID_KEY_EXCEPTION", @""); - case TSErrorMessageWrongTrustedIdentityKey: - return NSLocalizedString(@"ERROR_MESSAGE_WRONG_TRUSTED_IDENTITY_KEY", @""); - default: - return NSLocalizedString(@"ERROR_MESSAGE_UNKNOWN_ERROR", @""); - break; - } -} - -+ (instancetype)corruptedMessageWithSignal:(IncomingPushMessageSignal *)signal withTransaction:(YapDatabaseReadWriteTransaction *)transaction{ - return [[self alloc] initWithSignal:signal transaction:transaction failedMessageType:TSErrorMessageInvalidMessage]; -} - -+ (instancetype)invalidVersionWithSignal:(IncomingPushMessageSignal*)signal withTransaction:(YapDatabaseReadWriteTransaction*)transaction{ - return [[self alloc] initWithSignal:signal transaction:transaction failedMessageType:TSErrorMessageInvalidVersion]; -} - -+ (instancetype)missingKeyIdWithSignal:(IncomingPushMessageSignal*)signal withTransaction:(YapDatabaseReadWriteTransaction*)transaction{ - return [[self alloc] initWithSignal:signal transaction:transaction failedMessageType:TSErrorMessageMissingKeyId]; -} - -+ (instancetype)invalidKeyExceptionWithSignal:(IncomingPushMessageSignal*)signal withTransaction:(YapDatabaseReadWriteTransaction*)transaction{ - return [[self alloc] initWithSignal:signal transaction:transaction failedMessageType:TSErrorMessageInvalidKeyException]; -} - -+ (instancetype)missingSessionWithSignal:(IncomingPushMessageSignal*)signal withTransaction:(YapDatabaseReadWriteTransaction*)transaction{ - return [[self alloc] initWithSignal:signal transaction:transaction failedMessageType:TSErrorMessageNoSession]; -} - -@end diff --git a/Signal/src/textsecure/Messages/TSErrorMessage_privateConstructor.h b/Signal/src/textsecure/Messages/TSErrorMessage_privateConstructor.h deleted file mode 100644 index f7a02519c..000000000 --- a/Signal/src/textsecure/Messages/TSErrorMessage_privateConstructor.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// TSErrorMessage_privateConstructor.h -// Signal -// -// Created by Frederic Jacobs on 31/12/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSErrorMessage.h" - -@interface TSErrorMessage () - -- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread failedMessageType:(TSErrorMessageType)errorMessageType NS_DESIGNATED_INITIALIZER; - -@property NSData *pushSignal; - -@property NSDictionary *pendingOutgoingMessage; - -#define TSPendingOutgoingMessageKey @"TSPendingOutgoingMessageKey" -#define TSPendingOutgoingMessageRecipientKey @"TSPendingOutgoingMessageRecipientKey" - -@end diff --git a/Signal/src/textsecure/Messages/TSIncomingMessage.h b/Signal/src/textsecure/Messages/TSIncomingMessage.h deleted file mode 100644 index 9ceaf33af..000000000 --- a/Signal/src/textsecure/Messages/TSIncomingMessage.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// TSIncomingMessage.h -// TextSecureKit -// -// Created by Frederic Jacobs on 15/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSMessage.h" - -@interface TSIncomingMessage : TSMessage - -/** - * Initiates an incoming message - * - * @param timestamp timestamp of the message in milliseconds since epoch - * @param thread thread to which the message belongs - * @param body body of the message - * @param attachments attachments of the message - * - * @return initiated incoming message - */ - -- (instancetype)initWithTimestamp:(uint64_t)timestamp - inThread:(TSContactThread*)thread - messageBody:(NSString*)body - attachments:(NSArray*)attachments; - -/** - * Initiates an incoming group message - * - * @param timestamp timestamp of the message in milliseconds since epoch - * @param thread thread to which the message belongs - * @param authorId author identifier of the user in the group that sent the message - * @param body body of the message - * @param attachments attachments of the message - * - * @return initiated incoming group message - */ - -- (instancetype)initWithTimestamp:(uint64_t)timestamp - inThread:(TSGroupThread*)thread - authorId:(NSString*)authorId - messageBody:(NSString*)body - attachments:(NSArray*)attachments; - -@property (nonatomic, readonly) NSString *authorId; -@property (nonatomic, getter = wasRead) BOOL read; -@property (nonatomic, readonly) NSDate *receivedAt; - -@end diff --git a/Signal/src/textsecure/Messages/TSIncomingMessage.m b/Signal/src/textsecure/Messages/TSIncomingMessage.m deleted file mode 100644 index 1d4012dec..000000000 --- a/Signal/src/textsecure/Messages/TSIncomingMessage.m +++ /dev/null @@ -1,46 +0,0 @@ -// -// TSIncomingMessage.m -// TextSecureKit -// -// Created by Frederic Jacobs on 15/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSIncomingMessage.h" - -@implementation TSIncomingMessage - -- (instancetype)initWithTimestamp:(uint64_t)timestamp - inThread:(TSGroupThread*)thread - authorId:(NSString*)authorId - messageBody:(NSString*)body - attachments:(NSArray *)attachments -{ - self = [super initWithTimestamp:timestamp inThread:thread messageBody:body attachments:attachments]; - - if (self) { - _authorId = authorId; - _read = NO; - _receivedAt = [NSDate date]; - } - - return self; -} - -- (instancetype)initWithTimestamp:(uint64_t)timestamp - inThread:(TSContactThread *)thread - messageBody:(NSString *)body - attachments:(NSArray *)attachments -{ - self = [super initWithTimestamp:timestamp inThread:thread messageBody:body attachments:attachments]; - - if (self) { - _authorId = nil; - _read = NO; - _receivedAt = [NSDate date]; - } - - return self; -} - -@end diff --git a/Signal/src/textsecure/Messages/TSInfoMessage.h b/Signal/src/textsecure/Messages/TSInfoMessage.h deleted file mode 100644 index 4af9608b0..000000000 --- a/Signal/src/textsecure/Messages/TSInfoMessage.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// TSInfoMessage.h -// TextSecureKit -// -// Created by Frederic Jacobs on 15/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSMessage.h" - -@interface TSInfoMessage : TSMessage - -typedef NS_ENUM(NSInteger, TSInfoMessageType){ - TSInfoMessageTypeSessionDidEnd, - TSInfoMessageUserNotRegistered, - TSInfoMessageTypeUnsupportedMessage, - TSInfoMessageTypeGroupUpdate, - TSInfoMessageTypeGroupQuit -}; - -+ (instancetype)userNotRegisteredMessageInThread:(TSThread*)thread transaction:(YapDatabaseReadWriteTransaction*)transaction; - -@property TSInfoMessageType messageType; -@property NSString* customMessage; - -- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)contact messageType:(TSInfoMessageType)infoMessage; -- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread messageType:(TSInfoMessageType)infoMessage customMessage:(NSString*) customMessage; - -@end diff --git a/Signal/src/textsecure/Messages/TSInfoMessage.m b/Signal/src/textsecure/Messages/TSInfoMessage.m deleted file mode 100644 index fbae95eae..000000000 --- a/Signal/src/textsecure/Messages/TSInfoMessage.m +++ /dev/null @@ -1,56 +0,0 @@ -// -// TSInfoMessage.m -// TextSecureKit -// -// Created by Frederic Jacobs on 15/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSInfoMessage.h" -#import "NSDate+millisecondTimeStamp.h" - -@implementation TSInfoMessage - -- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread messageType:(TSInfoMessageType)infoMessage{ - self = [super initWithTimestamp:timestamp inThread:thread messageBody:nil attachments:nil]; - - if (self) { - _messageType = infoMessage; - } - - return self; -} - -- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSThread *)thread messageType:(TSInfoMessageType)infoMessage customMessage:(NSString*)customMessage { - self = [self initWithTimestamp:timestamp inThread:thread messageType:infoMessage]; - if (self) { - _customMessage = customMessage; - } - return self; -} - -+ (instancetype)userNotRegisteredMessageInThread:(TSThread*)thread transaction:(YapDatabaseReadWriteTransaction*)transaction{ - return [[self alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:thread messageType:TSInfoMessageUserNotRegistered]; - -} - -- (NSString *)description{ - switch (_messageType) { - case TSInfoMessageTypeSessionDidEnd: - return NSLocalizedString(@"SECURE_SESSION_RESET", nil); - case TSInfoMessageTypeUnsupportedMessage: - return NSLocalizedString(@"UNSUPPORTED_ATTACHMENT", nil); - case TSInfoMessageUserNotRegistered: - return NSLocalizedString(@"CONTACT_DETAIL_COMM_TYPE_INSECURE", nil); - case TSInfoMessageTypeGroupQuit: - return NSLocalizedString(@"GROUP_YOU_LEFT", nil); - case TSInfoMessageTypeGroupUpdate: - return _customMessage != nil ? _customMessage : NSLocalizedString(@"GROUP_UPDATED", nil); - default: - break; - } - - return @"Unknown Info Message Type"; -} - -@end diff --git a/Signal/src/textsecure/Messages/TSInteraction.h b/Signal/src/textsecure/Messages/TSInteraction.h deleted file mode 100644 index 3b44fa366..000000000 --- a/Signal/src/textsecure/Messages/TSInteraction.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// TSInteraction.h -// TextSecureKit -// -// Created by Frederic Jacobs on 12/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import -#import - -#import "TSYapDatabaseObject.h" - -#import "TSContactThread.h" -#import "TSGroupThread.h" - -extern const struct TSMessageRelationships { - __unsafe_unretained NSString *threadUniqueId; -} TSMessageRelationships; - -extern const struct TSMessageEdges { - __unsafe_unretained NSString *thread; -} TSMessageEdges; - -@interface TSInteraction : TSYapDatabaseObject - -- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSThread*)thread; - -@property (nonatomic, readonly) NSString *uniqueThreadId; -@property (nonatomic, readonly) uint64_t timestamp; - -- (NSDate*)date; -- (NSString*)description; - -#pragma mark Utility Method - -+ (NSString*)stringFromTimeStamp:(uint64_t)timestamp; -+ (uint64_t)timeStampFromString:(NSString*)string; - -+ (instancetype)interactionForTimestamp:(uint64_t)timestamp withTransaction:(YapDatabaseReadWriteTransaction*)transaction; - - -@end diff --git a/Signal/src/textsecure/Messages/TSInteraction.m b/Signal/src/textsecure/Messages/TSInteraction.m deleted file mode 100644 index 435ca5626..000000000 --- a/Signal/src/textsecure/Messages/TSInteraction.m +++ /dev/null @@ -1,116 +0,0 @@ -// -// TSInteraction.m -// TextSecureKit -// -// Created by Frederic Jacobs on 12/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSInteraction.h" - -#import "TSDatabaseSecondaryIndexes.h" -#import "TSStorageManager+messageIDs.h" - - -const struct TSMessageRelationships TSMessageRelationships = { - .threadUniqueId = @"threadUniqueId", -}; - -const struct TSMessageEdges TSMessageEdges = { - .thread = @"thread", -}; - -@implementation TSInteraction - -- (instancetype)initWithTimestamp:(uint64_t)timestamp inThread:(TSThread*)thread { - self = [super initWithUniqueId:nil]; - - if (self) { - _timestamp = timestamp; - _uniqueThreadId = thread.uniqueId; - } - - return self; -} - -+ (instancetype)interactionForTimestamp:(uint64_t)timestamp withTransaction:(YapDatabaseReadWriteTransaction *)transaction{ - __block int counter = 0; - __block TSInteraction *interaction; - - [TSDatabaseSecondaryIndexes enumerateMessagesWithTimestamp:timestamp withBlock:^(NSString *collection, NSString *key, BOOL *stop) { - - if (counter != 0) { - DDLogWarn(@"The database contains two colliding timestamps at: %lld.", timestamp); - return; - } - - interaction = [TSInteraction fetchObjectWithUniqueID:key transaction:transaction]; - - counter ++; - } usingTransaction:transaction]; - - return interaction; -} - - -#pragma mark YapDatabaseRelationshipNode - -- (NSArray *)yapDatabaseRelationshipEdges -{ - NSArray *edges = nil; - if (self.uniqueThreadId) { - YapDatabaseRelationshipEdge *threadEdge = [YapDatabaseRelationshipEdge edgeWithName:TSMessageEdges.thread - destinationKey:self.uniqueThreadId - collection:[TSThread collection] - nodeDeleteRules:YDB_DeleteSourceIfDestinationDeleted]; - edges = @[threadEdge]; - } - - return edges; -} - -+ (NSString*)collection{ - return @"TSInteraction"; -} - -#pragma mark Date operations - -- (uint64_t)millisecondsTimestamp{ - return self.timestamp; -} - -- (NSDate*)date{ - uint64_t seconds = self.timestamp/1000; - return [NSDate dateWithTimeIntervalSince1970:seconds]; -} - -+ (NSString*)stringFromTimeStamp:(uint64_t)timestamp{ - return [[NSNumber numberWithUnsignedLongLong:timestamp] stringValue]; -} - -+ (uint64_t)timeStampFromString:(NSString*)string{ - NSNumberFormatter * f = [[NSNumberFormatter alloc] init]; - [f setNumberStyle:NSNumberFormatterNoStyle]; - NSNumber * myNumber = [f numberFromString:string]; - return [myNumber unsignedLongLongValue]; -} - -- (NSString*)description{ - return @"Interaction description"; -} - -- (void)saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction{ - if (!self.uniqueId) { - self.uniqueId = [TSStorageManager getAndIncrementMessageIdWithTransaction:transaction]; - } - - [super saveWithTransaction:transaction]; - - TSThread *fetchedThread = [TSThread fetchObjectWithUniqueID:self.uniqueThreadId - transaction:transaction]; - - - [fetchedThread updateWithLastMessage:self transaction:transaction]; -} - -@end diff --git a/Signal/src/textsecure/Messages/TSMessage.h b/Signal/src/textsecure/Messages/TSMessage.h deleted file mode 100644 index 375359e93..000000000 --- a/Signal/src/textsecure/Messages/TSMessage.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// TSMessage.h -// TextSecureKit -// -// Created by Frederic Jacobs on 12/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSInteraction.h" -#import - -/** - * Abstract message class. Is instantiated by either - */ - -typedef NS_ENUM(NSInteger, TSGroupMetaMessage){ - TSGroupMessageNone, - TSGroupMessageNew, - TSGroupMessageUpdate, - TSGroupMessageDeliver, - TSGroupMessageQuit -}; -@interface TSMessage : TSInteraction - -@property (nonatomic, readonly) NSMutableArray *attachments; -@property (nonatomic) NSString *body; -@property (nonatomic) TSGroupMetaMessage groupMetaMessage; - -- (instancetype)initWithTimestamp:(uint64_t)timestamp - inThread:(TSThread*)thread - messageBody:(NSString*)body - attachments:(NSArray*)attachments; - -- (void)addattachments:(NSArray*)attachments; -- (void)addattachment:(NSString*)attachment; -- (BOOL)hasAttachments; - -@end diff --git a/Signal/src/textsecure/Messages/TSMessage.m b/Signal/src/textsecure/Messages/TSMessage.m deleted file mode 100644 index 4c65a07e5..000000000 --- a/Signal/src/textsecure/Messages/TSMessage.m +++ /dev/null @@ -1,81 +0,0 @@ -// -// TSMessage.m -// TextSecureKit -// -// Created by Frederic Jacobs on 12/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSMessage.h" - -NSString * const TSAttachementsRelationshipEdgeName = @"TSAttachmentEdge"; - -@implementation TSMessage - -- (void)addattachments:(NSArray*)attachments { - for (NSString *identifier in attachments) { - [self addattachment:identifier]; - } -} - -- (void)addattachment:(NSString*)attachment { - if (!_attachments) { - _attachments = [NSMutableArray array]; - } - - [self.attachments addObject:attachment]; -} - -- (NSArray *)yapDatabaseRelationshipEdges { - NSMutableArray *edges = [[super yapDatabaseRelationshipEdges] mutableCopy]; - - if ([self hasAttachments]) { - for (NSString *attachmentId in self.attachments) { - YapDatabaseRelationshipEdge *fileEdge = [[YapDatabaseRelationshipEdge alloc] initWithName:TSAttachementsRelationshipEdgeName - destinationKey:attachmentId - collection:[TSAttachment collection] - nodeDeleteRules:YDB_DeleteDestinationIfAllSourcesDeleted]; - [edges addObject:fileEdge]; - } - } - return edges; -} - -- (instancetype)initWithTimestamp:(uint64_t)timestamp - inThread:(TSThread*)thread - messageBody:(NSString*)body - attachments:(NSArray*)attachments -{ - self = [super initWithTimestamp:timestamp inThread:thread]; - - if (self) { - _body = body; - _attachments = [attachments mutableCopy]; - } - return self; -} - -- (BOOL)hasAttachments{ - return self.attachments?(self.attachments.count>0):false; -} - -- (NSString *)description{ - if(self.attachments > 0){ - NSString *attachmentId = self.attachments[0]; - TSAttachment *attachment = [TSAttachment fetchObjectWithUniqueID:attachmentId]; - return attachment.description; - } else { - return self.body; - } -} - -- (void)removeWithTransaction:(YapDatabaseReadWriteTransaction *)transaction{ - for (NSString *attachmentId in _attachments){ - TSAttachment *attachment = [TSAttachment fetchObjectWithUniqueID:attachmentId transaction:transaction]; - [attachment removeWithTransaction:transaction]; - } - - [super removeWithTransaction:transaction]; -} - -@end diff --git a/Signal/src/textsecure/Messages/TSMessagesManager+attachments.h b/Signal/src/textsecure/Messages/TSMessagesManager+attachments.h deleted file mode 100644 index 96755b415..000000000 --- a/Signal/src/textsecure/Messages/TSMessagesManager+attachments.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// TSMessagesManager+attachments.h -// Signal -// -// Created by Frederic Jacobs on 17/12/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSMessagesManager.h" - -@class TSAttachment; -@class TSAttachmentPointer; - -@interface TSMessagesManager (attachments) - -- (void)handleReceivedMediaMessage:(IncomingPushMessageSignal*)message withContent:(PushMessageContent*)content; - -- (void)sendAttachment:(NSData*)attachmentData - contentType:(NSString*)contentType - inMessage:(TSOutgoingMessage*)outgoingMessage - thread:(TSThread*)thread; - -- (void)retrieveAttachment:(TSAttachmentPointer*)attachment messageId:(NSString*)messageId; - -@end diff --git a/Signal/src/textsecure/Messages/TSMessagesManager+attachments.m b/Signal/src/textsecure/Messages/TSMessagesManager+attachments.m deleted file mode 100644 index 429e1859d..000000000 --- a/Signal/src/textsecure/Messages/TSMessagesManager+attachments.m +++ /dev/null @@ -1,285 +0,0 @@ -// -// TSMessagesManager+attachments.m -// Signal -// -// Created by Frederic Jacobs on 17/12/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "NSDate+millisecondTimeStamp.h" -#import - -#import "Cryptography.h" - -#import "TSAttachmentPointer.h" -#import "TSInfoMessage.h" -#import "TSMessagesManager+attachments.h" -#import "TSMessagesManager+sendMessages.h" -#import "TSNetworkManager.h" -#import "MIMETypeUtil.h" - -@interface TSMessagesManager () - -dispatch_queue_t attachmentsQueue(void); - -@end - -dispatch_queue_t attachmentsQueue() { - static dispatch_once_t queueCreationGuard; - static dispatch_queue_t queue; - dispatch_once(&queueCreationGuard, ^{ - queue = dispatch_queue_create("org.whispersystems.signal.attachments", NULL); - }); - return queue; -} - -@implementation TSMessagesManager (attachments) - -- (void)handleReceivedMediaMessage:(IncomingPushMessageSignal*)message withContent:(PushMessageContent*)content { - NSArray *attachmentsToRetrieve = (content.group != nil && (content.group.type == PushMessageContentGroupContextTypeUpdate)) ? [NSArray arrayWithObject:content.group.avatar] : content.attachments; - - NSMutableArray *retrievedAttachments = [NSMutableArray array]; - __block BOOL shouldProcessMessage = YES; - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - for (PushMessageContentAttachmentPointer *pointer in attachmentsToRetrieve) { - TSAttachmentPointer *attachmentPointer = (content.group != nil && (content.group.type == PushMessageContentGroupContextTypeUpdate)) ? [[TSAttachmentPointer alloc] initWithIdentifier:pointer.id key:pointer.key contentType:pointer.contentType relay:message.relay avatarOfGroupId:content.group.id] : [[TSAttachmentPointer alloc] initWithIdentifier:pointer.id key:pointer.key contentType:pointer.contentType relay:message.relay]; - - if ([MIMETypeUtil isSupportedMIMEType:attachmentPointer.contentType]) { - [attachmentPointer saveWithTransaction:transaction]; - [retrievedAttachments addObject:attachmentPointer.uniqueId]; - shouldProcessMessage = YES; - } - else { - TSThread *thread = [TSContactThread getOrCreateThreadWithContactId:message.source transaction:transaction]; - TSInfoMessage *infoMessage = [[TSInfoMessage alloc] initWithTimestamp:message.timestamp - inThread:thread - messageType:TSInfoMessageTypeUnsupportedMessage]; - [infoMessage saveWithTransaction:transaction]; - shouldProcessMessage = NO; - } - } - }]; - - if (shouldProcessMessage) { - [self handleReceivedMessage:message withContent:content attachments:retrievedAttachments completionBlock:^(NSString *messageIdentifier) { - for (NSString *pointerId in retrievedAttachments) { - dispatch_async(attachmentsQueue(), ^{ - __block TSAttachmentPointer *pointer; - - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - pointer = [TSAttachmentPointer fetchObjectWithUniqueID:pointerId transaction:transaction]; - }]; - - [self retrieveAttachment:pointer messageId:messageIdentifier]; - }); - } - }]; - } -} - -- (void)sendAttachment:(NSData*)attachmentData contentType:(NSString*)contentType inMessage:(TSOutgoingMessage*)outgoingMessage 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 = [(NSNumber*)[responseDict objectForKey:@"id"] stringValue]; - NSString *location = [responseDict objectForKey:@"location"]; - - TSAttachmentEncryptionResult *result = - [Cryptography encryptAttachment:attachmentData contentType:contentType identifier:attachementId]; - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - result.pointer.isDownloaded = NO; - [result.pointer saveWithTransaction:transaction]; - }]; - outgoingMessage.body = nil; - [outgoingMessage.attachments addObject:attachementId]; - if(outgoingMessage.groupMetaMessage!=TSGroupMessageNew&&outgoingMessage.groupMetaMessage!=TSGroupMessageUpdate) { - [outgoingMessage setMessageState:TSOutgoingMessageStateAttemptingOut]; - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [outgoingMessage saveWithTransaction:transaction]; - }]; - } - BOOL success = [self uploadDataWithProgress:result.body location:location attachmentID:attachementId]; - if (success) { - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - result.pointer.isDownloaded = YES; - [result.pointer saveWithTransaction:transaction]; - }]; - [self sendMessage:outgoingMessage inThread:thread success:nil failure:nil]; - } 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)sendAttachment:(NSData*)attachmentData contentType:(NSString*)contentType thread:(TSThread*)thread { - TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:thread messageBody:nil attachments:[[NSMutableArray alloc] init]]; - [self sendAttachment:attachmentData contentType:contentType inMessage:message thread:thread]; -} - -- (void)retrieveAttachment:(TSAttachmentPointer*)attachment messageId:(NSString*)messageId { - - [self setAttachment:attachment isDownloadingInMessage:messageId]; - - TSAttachmentRequest *attachmentRequest = [[TSAttachmentRequest alloc] initWithId:[attachment identifier] - relay:attachment.relay]; - - [[TSNetworkManager sharedManager] queueAuthenticatedRequest:attachmentRequest success:^(NSURLSessionDataTask *task, id responseObject) { - if ([responseObject isKindOfClass:[NSDictionary class]]) { - dispatch_async(attachmentsQueue(), ^{ - NSString *location = [(NSDictionary*)responseObject objectForKey:@"location"]; - - NSData *data = [self downloadFromLocation:location pointer:attachment messageId:messageId]; - if (data) { - [self decryptedAndSaveAttachment:attachment data:data messageId:messageId]; - } - }); - } - } failure:^(NSURLSessionDataTask *task, NSError *error) { - DDLogError(@"Failed retrieval of attachment with error: %@", error.description); - [self setFailedAttachment:attachment inMessage:messageId]; - }]; -} - -- (void)setAttachment:(TSAttachmentPointer*)pointer isDownloadingInMessage:(NSString*)messageId { - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [pointer setDownloading:YES]; - [pointer saveWithTransaction:transaction]; - TSMessage *message = [TSMessage fetchObjectWithUniqueID:messageId transaction:transaction]; - [message saveWithTransaction:transaction]; - }]; -} - -- (void)setFailedAttachment:(TSAttachmentPointer*)pointer inMessage:(NSString*)messageId { - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [pointer setDownloading:NO]; - [pointer setFailed:YES]; - [pointer saveWithTransaction:transaction]; - TSMessage *message = [TSMessage fetchObjectWithUniqueID:messageId transaction:transaction]; - [message saveWithTransaction:transaction]; - }]; -} - -- (void)decryptedAndSaveAttachment:(TSAttachmentPointer*)attachment data:(NSData*)cipherText messageId:(NSString*)messageId { - 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]; - if([attachment.avatarOfGroupId length]!=0) { - TSGroupModel *emptyModelToFillOutId = [[TSGroupModel alloc] initWithTitle:nil memberIds:nil image:nil groupId:attachment.avatarOfGroupId associatedAttachmentId:attachment.uniqueId]; // TODO refactor the TSGroupThread to just take in an ID (as it is all that it uses). Should not take in more than it uses - TSGroupThread* gThread = [TSGroupThread getOrCreateThreadWithGroupModel:emptyModelToFillOutId transaction:transaction]; - gThread.groupModel.groupImage=[stream image]; - [gThread saveWithTransaction:transaction]; - } - else { - // Causing message to be reloaded in view. - TSMessage *message = [TSMessage fetchObjectWithUniqueID:messageId transaction:transaction]; - [message saveWithTransaction:transaction]; - } - }]; - } -} - -- (NSData*)downloadFromLocation:(NSString*)location pointer:(TSAttachmentPointer*)pointer messageId:(NSString*)messageId{ - __block NSData *data; - - AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; - manager.requestSerializer = [AFHTTPRequestSerializer serializer]; - [manager.requestSerializer setValue:@"application/octet-stream" forHTTPHeaderField:@"Content-Type"]; - manager.responseSerializer = [AFHTTPResponseSerializer serializer]; - manager.completionQueue = dispatch_get_main_queue(); - - 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 retrieve attachment with error: %@", error.description); - if (pointer && messageId) { - [self setFailedAttachment:pointer inMessage:messageId]; - } - dispatch_semaphore_signal(sema); - }]; - - dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); - - return data; -} - -- (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; - - 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; -} - -- (BOOL)uploadDataWithProgress:(NSData*)cipherText location:(NSString*)location attachmentID:(NSString*)attachmentID { - AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; - manager.responseSerializer = [AFHTTPResponseSerializer serializer]; - dispatch_semaphore_t sema = dispatch_semaphore_create(0); - __block BOOL success = NO; - - 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 setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) { - double percentDone = (double)totalBytesWritten / (double)totalBytesExpectedToWrite; - NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; - [notificationCenter postNotificationName:@"attachmentUploadProgress" object:nil userInfo:@{ @"progress": @(percentDone), @"attachmentID": attachmentID }]; - }]; - - [httpOperation start]; - - dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); - - return success; -} - - -@end diff --git a/Signal/src/textsecure/Messages/TSMessagesManager+sendMessages.h b/Signal/src/textsecure/Messages/TSMessagesManager+sendMessages.h deleted file mode 100644 index 5baa23fb8..000000000 --- a/Signal/src/textsecure/Messages/TSMessagesManager+sendMessages.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// TSMessagesManager+sendMessages.h -// TextSecureKit -// -// Created by Frederic Jacobs on 17/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSMessagesManager.h" - -@interface TSMessagesManager (sendMessages) - -typedef void(^successSendingCompletionBlock)(); -typedef void(^failedSendingCompletionBlock)(); - -- (void)sendMessage:(TSOutgoingMessage*)message inThread:(TSThread*)thread - success:(successSendingCompletionBlock)successCompletionBlock - failure:(failedSendingCompletionBlock)failedCompletionBlock; - -@end diff --git a/Signal/src/textsecure/Messages/TSMessagesManager+sendMessages.m b/Signal/src/textsecure/Messages/TSMessagesManager+sendMessages.m deleted file mode 100644 index d23fe6dda..000000000 --- a/Signal/src/textsecure/Messages/TSMessagesManager+sendMessages.m +++ /dev/null @@ -1,540 +0,0 @@ -// -// TSMessagesManager+sendMessages.m -// TextSecureKit -// -// Created by Frederic Jacobs on 17/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSMessagesManager+sendMessages.h" - -#import -#import -#import -#import - -#import "Environment.h" -#import "ContactsManager+updater.h" -#import "PreferencesUtil.h" -#import "NSData+messagePadding.h" -#import "TSStorageManager.h" - -#import "PreKeyBundle+jsonDict.h" -#import "SignalKeyingStorage.h" - -#import "TSNetworkManager.h" -#import "TSServerMessage.h" - -#import "TSInfoMessage.h" -#import "CollapsingFutures.h" - -#define RETRY_ATTEMPTS 3 - -#define InvalidDeviceException @"InvalidDeviceException" - -@interface TSMessagesManager () -dispatch_queue_t sendingQueue(void); -@end - -typedef void (^messagesQueue)(NSArray *messages); - -@implementation TSMessagesManager (sendMessages) - -dispatch_queue_t sendingQueue() { - static dispatch_once_t queueCreationGuard; - static dispatch_queue_t queue; - dispatch_once(&queueCreationGuard, ^{ - queue = dispatch_queue_create("org.whispersystems.signal.sendQueue", NULL); - }); - return queue; -} - -- (void)getRecipients:(NSArray *)identifiers - success:(void (^)(NSArray*))success - failure:(void (^)(NSError *error))failure -{ - NSMutableArray *recipients = [NSMutableArray array]; - for(NSString *recipientId in identifiers) { - __block SignalRecipient *recipient; - [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction * _Nonnull transaction) { - recipient = [SignalRecipient recipientWithTextSecureIdentifier:recipientId withTransaction:transaction]; - }]; - - if (!recipient){ - [[self contactManager] synchronousLookup:recipientId success:^(SignalRecipient * newRecipient) { - [recipients addObject:newRecipient]; - } failure:^(NSError *error) { - failure(error); - return; - }]; - } - } - - success(recipients); - - return; -} - -- (ContactsManager*)contactManager { - return [Environment getCurrent].contactsManager; -} - -- (void)sendMessage:(TSOutgoingMessage*)message - inThread:(TSThread*)thread - success:(successSendingCompletionBlock)successCompletionBlock - failure:(failedSendingCompletionBlock)failedCompletionBlock -{ - [Environment.preferences setHasSentAMessage:YES]; - dispatch_async(sendingQueue(), ^{ - if ([thread isKindOfClass:[TSGroupThread class]]) { - TSGroupThread* groupThread = (TSGroupThread*)thread; - [self saveGroupMessage:message inThread:thread]; - [self getRecipients:groupThread.groupModel.groupMemberIds success:^(NSArray *recipients) { - [self groupSend:recipients Message:message inThread:thread success:successCompletionBlock failure:failedCompletionBlock]; - } failure:^(NSError *error) { - DDLogError(@"Failure to retreive group recipient."); - [self saveMessage:message withState:TSOutgoingMessageStateUnsent]; - }]; - - } else if([thread isKindOfClass:[TSContactThread class]]){ - TSContactThread *contactThread = (TSContactThread*)thread; - - [self saveMessage:message withState:TSOutgoingMessageStateAttemptingOut]; - - if(![contactThread.contactIdentifier isEqualToString:[SignalKeyingStorage.localNumber toE164]]) { - __block SignalRecipient *recipient; - [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - //recipient = [SignalRecipient recipientWithTextSecureIdentifier:contactThread.contactIdentifier - // withTransaction:transaction]; - }]; - - if (!recipient) { - [[self contactManager] synchronousLookup:contactThread.contactIdentifier - success:^(SignalRecipient *recip) { - recipient = recip; - } failure:^(NSError *error) { - if (error.code == NOTFOUND_ERROR) { - [self unregisteredRecipient:recipient - message:message - inThread:thread]; - return; - } else{ - [self saveMessage:message withState:TSOutgoingMessageStateUnsent]; - return; - } - }]; - } - - if (recipient) { - [self sendMessage:message - toRecipient:recipient - inThread:thread - withAttemps:RETRY_ATTEMPTS - success:successCompletionBlock - failure:failedCompletionBlock]; - } - - } else { - // Special situation: if we are sending to ourselves in a single thread, we treat this as an incoming message - [self handleMessageSent:message]; - [[TSMessagesManager sharedManager] handleSendToMyself:message]; - } - } - }); -} - -/// For group sends, we're using chained futures to make the code more readable. - -- (TOCFuture*)sendMessageFuture:(TSOutgoingMessage*)message - recipient:(SignalRecipient*)recipient - inThread:(TSThread*)thread { - TOCFutureSource *futureSource = [[TOCFutureSource alloc] init]; - - [self sendMessage:message toRecipient:recipient inThread:thread withAttemps:RETRY_ATTEMPTS success:^{ - [futureSource trySetResult:@1]; - } failure:^{ - [futureSource trySetFailure:@0]; - }]; - - return futureSource.future; -} - -- (void)groupSend:(NSArray*)recipients - Message:(TSOutgoingMessage*)message - inThread:(TSThread*)thread - success:(successSendingCompletionBlock)successBlock - failure:(failedSendingCompletionBlock)failureBlock { - - NSMutableArray *futures = [NSMutableArray array]; - - for(SignalRecipient *rec in recipients){ - // we don't need to send the message to ourselves, but otherwise we send - if( ![[rec uniqueId] isEqualToString:[SignalKeyingStorage.localNumber toE164]]){ - [futures addObject:[self sendMessageFuture:message recipient:rec inThread:thread]]; - } - } - - TOCFuture *completionFuture = futures.toc_thenAll; - - [completionFuture thenDo:^(id value) { - BLOCK_SAFE_RUN(successBlock); - }]; - - [completionFuture catchDo:^(id failure) { - BLOCK_SAFE_RUN(failureBlock); - }]; -} - -- (void)unregisteredRecipient:(SignalRecipient*)recipient - message:(TSOutgoingMessage*)message - inThread:(TSThread*)thread{ - [self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [recipient removeWithTransaction:transaction]; - [[TSInfoMessage userNotRegisteredMessageInThread:thread transaction:transaction] saveWithTransaction:transaction]; - }]; - - [self saveMessage:message withState:TSOutgoingMessageStateUnsent]; -} - - - -- (void)sendMessage:(TSOutgoingMessage*)message - toRecipient:(SignalRecipient*)recipient - inThread:(TSThread*)thread - withAttemps:(int)remainingAttempts - success:(successSendingCompletionBlock)successBlock - failure:(failedSendingCompletionBlock)failureBlock -{ - - if (remainingAttempts > 0) { - remainingAttempts -= 1; - - [self outgoingMessages:message toRecipient:recipient inThread:thread completion:^(NSArray *messages) { - TSSubmitMessageRequest *request = [[TSSubmitMessageRequest alloc] initWithRecipient:recipient.uniqueId - messages:messages - relay:recipient.relay - timeStamp:message.timestamp]; - - [[TSNetworkManager sharedManager] queueAuthenticatedRequest:request success:^(NSURLSessionDataTask *task, id responseObject) { - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [recipient saveWithTransaction:transaction]; - }]; - [self handleMessageSent:message]; - BLOCK_SAFE_RUN(successBlock); - } failure:^(NSURLSessionDataTask *task, NSError *error) { - NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response; - long statuscode = response.statusCode; - NSData *responseData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey]; - - switch (statuscode) { - case 404:{ - [self unregisteredRecipient:recipient - message:message - inThread:thread]; - BLOCK_SAFE_RUN(failureBlock); - break; - } - case 409:{ - // Mismatched devices - DDLogWarn(@"Mismatch Devices."); - - NSError *e; - NSDictionary *serializedResponse = [NSJSONSerialization JSONObjectWithData:responseData - options:0 - error:&e]; - - if (e) { - DDLogError(@"Failed to serialize response of mismatched devices: %@", e.description); - } else { - [self handleMismatchedDevices:serializedResponse - recipient:recipient]; - } - - dispatch_async(sendingQueue(), ^{ - [self sendMessage:message - toRecipient:recipient - inThread:thread - withAttemps:remainingAttempts - success:successBlock - failure:failureBlock]; - }); - - break; - } - case 410:{ - // staledevices - DDLogWarn(@"Stale devices"); - - if (!responseData) { - DDLogWarn(@"Stale devices but server didn't specify devices in response."); - return; - } - - [self handleStaleDevicesWithResponse:responseData recipientId:recipient.uniqueId]; - - dispatch_async(sendingQueue(), ^{ - [self sendMessage:message - toRecipient:recipient - inThread:thread - withAttemps:remainingAttempts - success:successBlock - failure:failureBlock]; - }); - - break; - } - default: - [self sendMessage:message - toRecipient:recipient - inThread:thread - withAttemps:remainingAttempts - success:successBlock - failure:failureBlock]; - break; - } - }]; - }]; - } else{ - [self saveMessage:message withState:TSOutgoingMessageStateUnsent]; - BLOCK_SAFE_RUN(failureBlock); - } -} - -- (void)handleMismatchedDevices:(NSDictionary*)dictionary recipient:(SignalRecipient*)recipient { - NSArray *extraDevices = [dictionary objectForKey:@"extraDevices"]; - NSArray *missingDevices = [dictionary objectForKey:@"missingDevices"]; - - if (extraDevices && [extraDevices count] > 0) { - for (NSNumber *extraDeviceId in extraDevices) { - [[TSStorageManager sharedManager] deleteSessionForContact:recipient.uniqueId deviceId:[extraDeviceId intValue]]; - } - - [recipient removeDevices:[NSSet setWithArray:extraDevices]]; - } - - if (missingDevices && [missingDevices count] > 0) { - [recipient addDevices:[NSSet setWithArray:missingDevices]]; - } - - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [recipient saveWithTransaction:transaction]; - }]; -} - -- (void)handleMessageSent:(TSOutgoingMessage*)message { - [self saveMessage:message withState:TSOutgoingMessageStateSent]; -} - -- (void)outgoingMessages:(TSOutgoingMessage*)message toRecipient:(SignalRecipient*)recipient inThread:(TSThread*)thread completion:(messagesQueue)sendMessages{ - NSMutableArray *messagesArray = [NSMutableArray arrayWithCapacity:recipient.devices.count]; - TSStorageManager *storage = [TSStorageManager sharedManager]; - NSData *plainText = [self plainTextForMessage:message inThread:thread]; - - for (NSNumber *deviceNumber in recipient.devices) { - @try { - NSDictionary *messageDict = [self encryptedMessageWithPlaintext:plainText toRecipient:recipient.uniqueId deviceId:deviceNumber keyingStorage:storage]; - if (messageDict) { - [messagesArray addObject:messageDict]; - } else{ - @throw [NSException exceptionWithName:InvalidMessageException reason:@"Failed to encrypt message" userInfo:nil]; - } - } - @catch (NSException *exception) { - if ([exception.name isEqualToString:InvalidDeviceException]){ - [recipient removeDevices:[NSSet setWithObject:deviceNumber]]; - } else { - [self processException:exception outgoingMessage:message inThread:thread]; - return; - } - } - } - - sendMessages(messagesArray); -} - -- (NSDictionary*)encryptedMessageWithPlaintext:(NSData*)plainText toRecipient:(NSString*)identifier deviceId:(NSNumber*)deviceNumber keyingStorage:(TSStorageManager*)storage{ - - if (![storage containsSession:identifier deviceId:[deviceNumber intValue]]) { - __block dispatch_semaphore_t sema = dispatch_semaphore_create(0); - __block PreKeyBundle *bundle; - - [[TSNetworkManager sharedManager] queueAuthenticatedRequest:[[TSRecipientPrekeyRequest alloc] initWithRecipient:identifier deviceId:[deviceNumber stringValue]] success:^(NSURLSessionDataTask *task, id responseObject) { - bundle = [PreKeyBundle preKeyBundleFromDictionary:responseObject forDeviceNumber:deviceNumber]; - dispatch_semaphore_signal(sema); - } failure:^(NSURLSessionDataTask *task, NSError *error) { - DDLogError(@"Server replied on PreKeyBundle request with error: %@", error); - NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response; - if (response.statusCode == 404) { - @throw [NSException exceptionWithName:InvalidDeviceException reason:@"Device not registered" userInfo:nil]; - } - dispatch_semaphore_signal(sema); - }]; - dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); - - if (!bundle) { - @throw [NSException exceptionWithName:InvalidVersionException reason:@"Can't get a prekey bundle from the server with required information" userInfo:nil]; - } else{ - SessionBuilder *builder = [[SessionBuilder alloc] initWithSessionStore:storage - preKeyStore:storage - signedPreKeyStore:storage - identityKeyStore:storage - recipientId:identifier - deviceId:[deviceNumber intValue]]; - @try { - [builder processPrekeyBundle:bundle]; - } - @catch (NSException *exception) { - if ([exception.name isEqualToString:UntrustedIdentityKeyException]) { - @throw [NSException exceptionWithName:UntrustedIdentityKeyException reason:nil userInfo:@{TSInvalidPreKeyBundleKey:bundle, TSInvalidRecipientKey:identifier}]; - } - @throw exception; - } - } - } - - SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:storage - preKeyStore:storage - signedPreKeyStore:storage - identityKeyStore:storage - recipientId:identifier - deviceId:[deviceNumber intValue]]; - - id encryptedMessage = [cipher encryptMessage:[plainText paddedMessageBody]]; - NSData *serializedMessage = encryptedMessage.serialized; - TSWhisperMessageType messageType = [self messageTypeForCipherMessage:encryptedMessage]; - - - TSServerMessage *serverMessage = [[TSServerMessage alloc] initWithType:messageType - destination:identifier - device:[deviceNumber intValue] - body:serializedMessage - registrationId:cipher.remoteRegistrationId]; - - NSError *error; - NSDictionary *jsonDict = [MTLJSONAdapter JSONDictionaryFromModel:serverMessage error:&error]; - - if (error) { - DDLogError(@"Error while making JSON dictionary of message: %@", error.debugDescription); - return nil; - } - - return jsonDict; -} - -- (TSWhisperMessageType)messageTypeForCipherMessage:(id)cipherMessage{ - - if ([cipherMessage isKindOfClass:[PreKeyWhisperMessage class]]) { - return TSPreKeyWhisperMessageType; - } else if ([cipherMessage isKindOfClass:[WhisperMessage class]]){ - return TSEncryptedWhisperMessageType; - } - return TSUnknownMessageType; -} - -- (void)saveMessage:(TSOutgoingMessage*)message withState:(TSOutgoingMessageState)state{ - if(message.groupMetaMessage == TSGroupMessageDeliver || message.groupMetaMessage == TSGroupMessageNone) { - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [message setMessageState:state]; - [message saveWithTransaction:transaction]; - }]; - } -} - -- (void)saveGroupMessage:(TSOutgoingMessage*)message inThread:(TSThread*)thread{ - if(message.groupMetaMessage==TSGroupMessageDeliver) { - [self saveMessage:message withState:message.messageState]; - } - else if(message.groupMetaMessage==TSGroupMessageQuit) { - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - - [[[TSInfoMessage alloc] initWithTimestamp:message.timestamp - inThread:thread - messageType:TSInfoMessageTypeGroupQuit] saveWithTransaction:transaction]; - }]; - } - else { - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - - [[[TSInfoMessage alloc] initWithTimestamp:message.timestamp - inThread:thread - messageType:TSInfoMessageTypeGroupUpdate] saveWithTransaction:transaction]; - }]; - } -} - -- (NSData*)plainTextForMessage:(TSOutgoingMessage*)message inThread:(TSThread*)thread{ - PushMessageContentBuilder *builder = [PushMessageContentBuilder new]; - [builder setBody:message.body]; - BOOL processAttachments = YES; - if([thread isKindOfClass:[TSGroupThread class]]) { - TSGroupThread *gThread = (TSGroupThread*)thread; - PushMessageContentGroupContextBuilder *groupBuilder = [PushMessageContentGroupContextBuilder new]; - - switch (message.groupMetaMessage) { - case TSGroupMessageQuit: - [groupBuilder setType:PushMessageContentGroupContextTypeQuit]; - break; - case TSGroupMessageUpdate: - case TSGroupMessageNew: { - if(gThread.groupModel.groupImage!=nil && [message.attachments count] == 1) { - id dbObject = [TSAttachmentStream fetchObjectWithUniqueID:[message.attachments firstObject]]; - 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]; - [groupBuilder setAvatar:[attachmentbuilder build]]; - processAttachments = NO; - } - } - [groupBuilder setMembersArray:gThread.groupModel.groupMemberIds]; - [groupBuilder setName:gThread.groupModel.groupName]; - [groupBuilder setType:PushMessageContentGroupContextTypeUpdate]; - break; - } - default: - [groupBuilder setType:PushMessageContentGroupContextTypeDeliver]; - break; - } - [groupBuilder setId:gThread.groupModel.groupId]; - [builder setGroup:groupBuilder.build]; - } - if(processAttachments) { - 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]; -} - -- (void)handleStaleDevicesWithResponse:(NSData*)responseData recipientId:(NSString*)identifier { - dispatch_async(sendingQueue(), ^{ - NSDictionary *serialization = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil]; - NSArray *devices = serialization[@"staleDevices"]; - - if (!([devices count] > 0)) { - return; - } - - for (NSUInteger i = 0; i < [devices count]; i++) { - int deviceNumber = [devices[i] intValue]; - [[TSStorageManager sharedManager] deleteSessionForContact:identifier deviceId:deviceNumber]; - } - }); -} - -@end diff --git a/Signal/src/textsecure/Messages/TSMessagesManager.h b/Signal/src/textsecure/Messages/TSMessagesManager.h deleted file mode 100644 index bba82256e..000000000 --- a/Signal/src/textsecure/Messages/TSMessagesManager.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// TSMessagesHandler.h -// TextSecureKit -// -// Created by Frederic Jacobs on 11/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import -#import "IncomingPushMessageSignal.pb.h" -#import "TSIncomingMessage.h" -#import "TSOutgoingMessage.h" -#import "TSInvalidIdentityKeySendingErrorMessage.h" -@class TSCall; - -@interface TSMessagesManager : NSObject - -+ (instancetype)sharedManager; - -@property (readonly) YapDatabaseConnection *dbConnection; - -- (void)handleMessageSignal:(IncomingPushMessageSignal*)messageSignal; - -- (void)processException:(NSException*)exception outgoingMessage:(TSOutgoingMessage*)message inThread:(TSThread*)thread; -- (void)notifyUserForError:(TSErrorMessage*)message inThread:(TSThread*)thread; -- (void)notifyUserForCall:(TSCall*)call inThread:(TSThread*)thread; - -- (void)handleReceivedMessage:(IncomingPushMessageSignal*)message withContent:(PushMessageContent*)content attachments:(NSArray*)attachments; -- (void)handleReceivedMessage:(IncomingPushMessageSignal*)message withContent:(PushMessageContent*)content attachments:(NSArray*)attachments completionBlock:(void (^)(NSString* messageIdentifier))completionBlock ; - -- (void)handleSendToMyself:(TSOutgoingMessage*)outgoingMessage; - -- (NSUInteger)unreadMessagesCount; -- (NSUInteger)unreadMessagesCountExcept:(TSThread*)thread; -- (NSUInteger)unreadMessagesInThread:(TSThread*)thread; - -@end diff --git a/Signal/src/textsecure/Messages/TSMessagesManager.m b/Signal/src/textsecure/Messages/TSMessagesManager.m deleted file mode 100644 index 85ed82cbd..000000000 --- a/Signal/src/textsecure/Messages/TSMessagesManager.m +++ /dev/null @@ -1,524 +0,0 @@ -// -// TSMessagesHandler.m -// TextSecureKit -// -// Created by Frederic Jacobs on 11/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSMessagesManager.h" - -#import -#import -#import - -#import "PushManager.h" - -#import "TSInvalidIdentityKeyReceivingErrorMessage.h" -#import "TSInfoMessage.h" - -#import "TSDatabaseView.h" -#import "TSStorageManager.h" -#import "TSMessagesManager+attachments.h" - -#import "SignalKeyingStorage.h" - -#import "NSData+messagePadding.h" - -#import "Environment.h" -#import "PreferencesUtil.h" -#import "ContactsManager.h" -#import "TSCall.h" - -@interface TSMessagesManager () - -@property SystemSoundID newMessageSound; - -@end - -@implementation TSMessagesManager - -+ (instancetype)sharedManager { - static TSMessagesManager *sharedMyManager = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - sharedMyManager = [[self alloc] init]; - }); - return sharedMyManager; -} - -- (instancetype)init{ - self = [super init]; - - if (self) { - _dbConnection = [TSStorageManager sharedManager].newDatabaseConnection; - NSURL *newMessageSound = [NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"NewMessage" ofType:@"aifc"]]; - AudioServicesCreateSystemSoundID((__bridge CFURLRef)newMessageSound, &_newMessageSound);; - } - - return self; -} - -- (void)handleMessageSignal:(IncomingPushMessageSignal*)messageSignal{ - @try { - switch (messageSignal.type) { - case IncomingPushMessageSignalTypeCiphertext: - [self handleSecureMessage:messageSignal]; - break; - - case IncomingPushMessageSignalTypePrekeyBundle: - [self handlePreKeyBundle:messageSignal]; - break; - - // Other messages are just dismissed for now. - - case IncomingPushMessageSignalTypeKeyExchange: - DDLogWarn(@"Received Key Exchange Message, not supported"); - break; - case IncomingPushMessageSignalTypePlaintext: - DDLogWarn(@"Received a plaintext message"); - break; - case IncomingPushMessageSignalTypeReceipt: - DDLogInfo(@"Received a delivery receipt"); - [self handleDeliveryReceipt:messageSignal]; - break; - case IncomingPushMessageSignalTypeUnknown: - DDLogWarn(@"Received an unknown message type"); - break; - default: - break; - } - } - @catch (NSException *exception) { - DDLogWarn(@"Received an incorrectly formatted protocol buffer: %@", exception.debugDescription); - } -} - -- (void)handleDeliveryReceipt:(IncomingPushMessageSignal*)signal{ - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - TSInteraction *interaction = [TSInteraction interactionForTimestamp:signal.timestamp withTransaction:transaction]; - if ([interaction isKindOfClass:[TSOutgoingMessage class]]) { - TSOutgoingMessage *outgoingMessage = (TSOutgoingMessage*)interaction; - outgoingMessage.messageState = TSOutgoingMessageStateDelivered; - - [outgoingMessage saveWithTransaction:transaction]; - } - }]; -} - -- (void)handleSecureMessage:(IncomingPushMessageSignal*)secureMessage{ - @synchronized(self){ - TSStorageManager *storageManager = [TSStorageManager sharedManager]; - NSString *recipientId = secureMessage.source; - int deviceId = (int) secureMessage.sourceDevice; - - if (![storageManager containsSession:recipientId deviceId:deviceId]) { - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - TSErrorMessage *errorMessage = [TSErrorMessage missingSessionWithSignal:secureMessage - withTransaction:transaction]; - [errorMessage saveWithTransaction:transaction]; - }]; - return; - } - - PushMessageContent *content; - - @try { - - WhisperMessage *message = [[WhisperMessage alloc] initWithData:secureMessage.message]; - - SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:storageManager - preKeyStore:storageManager - signedPreKeyStore:storageManager - identityKeyStore:storageManager - recipientId:recipientId - deviceId:deviceId]; - - NSData *plaintext = [[cipher decrypt:message] removePadding]; - - content = [PushMessageContent parseFromData:plaintext]; - } - @catch (NSException *exception) { - [self processException:exception pushSignal:secureMessage]; - return; - } - - [self handleIncomingMessage:secureMessage withPushContent:content]; - } -} - -- (void)handlePreKeyBundle:(IncomingPushMessageSignal*)preKeyMessage{ - @synchronized(self){ - TSStorageManager *storageManager = [TSStorageManager sharedManager]; - NSString *recipientId = preKeyMessage.source; - int deviceId = (int)preKeyMessage.sourceDevice; - - PushMessageContent *content; - - @try { - PreKeyWhisperMessage *message = [[PreKeyWhisperMessage alloc] initWithData:preKeyMessage.message]; - - SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:storageManager - preKeyStore:storageManager - signedPreKeyStore:storageManager - identityKeyStore:storageManager - recipientId:recipientId - deviceId:deviceId]; - - NSData *plaintext = [[cipher decrypt:message] removePadding]; - - content = [PushMessageContent parseFromData:plaintext]; - } - @catch (NSException *exception) { - [self processException:exception pushSignal:preKeyMessage]; - return; - } - - [self handleIncomingMessage:preKeyMessage withPushContent:content]; - } - -} - -- (void)handleIncomingMessage:(IncomingPushMessageSignal*)incomingMessage withPushContent:(PushMessageContent*)content{ - if(content.hasGroup) { - __block BOOL ignoreMessage = NO; - [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - TSGroupModel *emptyModelToFillOutId = [[TSGroupModel alloc] initWithTitle:nil memberIds:nil image:nil groupId:content.group.id associatedAttachmentId:nil]; // TODO refactor the TSGroupThread to just take in an ID (as it is all that it uses). Should not take in more than it uses - TSGroupThread *gThread = [TSGroupThread threadWithGroupModel:emptyModelToFillOutId transaction:transaction]; - if(gThread==nil && content.group.type != PushMessageContentGroupContextTypeUpdate) { - ignoreMessage = YES; - } - }]; - if(ignoreMessage) { - DDLogDebug(@"Received message from group that I left or don't know about, ignoring"); - return; - } - - } - if ((content.flags & PushMessageContentFlagsEndSession) != 0) { - DDLogVerbose(@"Received end session message..."); - [self handleEndSessionMessage:incomingMessage withContent:content]; - } - else if (content.attachments.count > 0 || (content.hasGroup && content.group.type == PushMessageContentGroupContextTypeUpdate && content.group.hasAvatar)) { - DDLogVerbose(@"Received push media message (attachment) or group with an avatar..."); - [self handleReceivedMediaMessage:incomingMessage withContent:content]; - } - else { - DDLogVerbose(@"Received individual push text message..."); - [self handleReceivedTextMessage:incomingMessage withContent:content]; - } -} - -- (void)handleEndSessionMessage:(IncomingPushMessageSignal*)message withContent:(PushMessageContent*)content{ - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - TSContactThread *thread = [TSContactThread getOrCreateThreadWithContactId:message.source transaction:transaction]; - uint64_t timeStamp = message.timestamp; - - if (thread){ - [[[TSInfoMessage alloc] initWithTimestamp:timeStamp inThread:thread messageType:TSInfoMessageTypeSessionDidEnd] saveWithTransaction:transaction]; - } - }]; - - [[TSStorageManager sharedManager] deleteAllSessionsForContact:message.source]; -} - -- (void)handleReceivedTextMessage:(IncomingPushMessageSignal*)message withContent:(PushMessageContent*)content{ - [self handleReceivedMessage:message withContent:content attachments:content.attachments]; -} - --(void)handleSendToMyself:(TSOutgoingMessage*)outgoingMessage { - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - TSContactThread *cThread = [TSContactThread getOrCreateThreadWithContactId:[SignalKeyingStorage.localNumber toE164] transaction:transaction]; - [cThread saveWithTransaction:transaction]; - TSIncomingMessage *incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:(outgoingMessage.timestamp + 1) inThread:cThread messageBody:outgoingMessage.body attachments:outgoingMessage.attachments]; - [incomingMessage saveWithTransaction:transaction]; - }]; -} - -- (void)handleReceivedMessage:(IncomingPushMessageSignal *)message withContent:(PushMessageContent *)content attachments:(NSArray *)attachments{ - [self handleReceivedMessage:message withContent:content attachments:attachments completionBlock:nil]; -} - -- (void)handleReceivedMessage:(IncomingPushMessageSignal*)message withContent:(PushMessageContent*)content attachments:(NSArray*)attachments completionBlock:(void (^)(NSString* messageIdentifier))completionBlock { - uint64_t timeStamp = message.timestamp; - NSString *body = content.body; - NSData *groupId = content.hasGroup?content.group.id:nil; - - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - TSIncomingMessage *incomingMessage; - TSThread *thread; - if (groupId) { - TSGroupModel *model = [[TSGroupModel alloc] initWithTitle:content.group.name memberIds:[[[NSSet setWithArray:content.group.members] allObjects] mutableCopy] image:nil groupId:content.group.id associatedAttachmentId:nil]; - TSGroupThread *gThread = [TSGroupThread getOrCreateThreadWithGroupModel:model transaction:transaction]; - [gThread saveWithTransaction:transaction]; - if(content.group.type==PushMessageContentGroupContextTypeUpdate) { - if([attachments count]==1) { - NSString* avatarId = [attachments firstObject]; - TSAttachment *avatar = [TSAttachment fetchObjectWithUniqueID:avatarId]; - if ([avatar isKindOfClass:[TSAttachmentStream class]]) { - TSAttachmentStream *stream = (TSAttachmentStream*)avatar; - if ([stream isImage]) { - model.associatedAttachmentId = stream.uniqueId; - model.groupImage = [stream image]; - } - } - } - - NSString* updateGroupInfo = [gThread.groupModel getInfoStringAboutUpdateTo:model]; - gThread.groupModel = model; - [gThread saveWithTransaction:transaction]; - [[[TSInfoMessage alloc] initWithTimestamp:timeStamp inThread:gThread messageType:TSInfoMessageTypeGroupUpdate customMessage:updateGroupInfo] saveWithTransaction:transaction]; - } - else if(content.group.type==PushMessageContentGroupContextTypeQuit) { - NSString *nameString = [[Environment.getCurrent contactsManager] nameStringForPhoneIdentifier:message.source]; - - if (!nameString) { - nameString = message.source; - } - - NSString* updateGroupInfo = [NSString stringWithFormat:NSLocalizedString(@"GROUP_MEMBER_LEFT", @""),nameString]; - NSMutableArray *newGroupMembers = [NSMutableArray arrayWithArray:gThread.groupModel.groupMemberIds]; - [newGroupMembers removeObject:message.source]; - gThread.groupModel.groupMemberIds = newGroupMembers; - - [gThread saveWithTransaction:transaction]; - [[[TSInfoMessage alloc] initWithTimestamp:timeStamp inThread:gThread messageType:TSInfoMessageTypeGroupUpdate customMessage:updateGroupInfo] saveWithTransaction:transaction]; - } else { - incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:timeStamp inThread:gThread authorId:message.source messageBody:body attachments:attachments]; - [incomingMessage saveWithTransaction:transaction]; - } - - thread = gThread; - - } else { - TSContactThread *cThread = [TSContactThread getOrCreateThreadWithContactId:message.source - transaction:transaction - pushSignal:message]; - - incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:timeStamp - inThread:cThread - messageBody:body - attachments:attachments]; - thread = cThread; - - } - - if (thread && incomingMessage) { - if ([attachments count] > 0 && body != nil && ![body isEqualToString:@""]) { // Android allows attachments to be sent with body. - uint64_t textMessageTimestamp = timeStamp+1000; // We want the text to be displayed under the attachment - - if ([thread isGroupThread]) { - TSGroupThread *gThread = (TSGroupThread*)thread; - TSIncomingMessage *textMessage = [[TSIncomingMessage alloc] initWithTimestamp:textMessageTimestamp - inThread:gThread - authorId:message.source - messageBody:body - attachments:nil]; - [textMessage saveWithTransaction:transaction]; - } else{ - TSContactThread *cThread= (TSContactThread*)thread; - TSIncomingMessage *textMessage = [[TSIncomingMessage alloc] initWithTimestamp:textMessageTimestamp - inThread:cThread - messageBody:body - attachments:nil]; - [textMessage saveWithTransaction:transaction]; - } - } - - [incomingMessage saveWithTransaction:transaction]; - } - - if (completionBlock) { - completionBlock(incomingMessage.uniqueId); - } - - NSString *name = [thread name]; - - if (incomingMessage && thread) { - [self notifyUserForIncomingMessage:incomingMessage - from:name - inThread:thread]; - } - }]; -} - -- (void)processException:(NSException*)exception pushSignal:(IncomingPushMessageSignal*)signal{ - DDLogError(@"Got exception: %@ of type: %@", exception.description, exception.name); - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - TSErrorMessage *errorMessage; - - if ([exception.name isEqualToString:NoSessionException]) { - errorMessage = [TSErrorMessage missingSessionWithSignal:signal withTransaction:transaction]; - } else if ([exception.name isEqualToString:InvalidKeyException]){ - errorMessage = [TSErrorMessage invalidKeyExceptionWithSignal:signal withTransaction:transaction]; - } else if ([exception.name isEqualToString:InvalidKeyIdException]){ - errorMessage = [TSErrorMessage invalidKeyExceptionWithSignal:signal withTransaction:transaction]; - } else if ([exception.name isEqualToString:DuplicateMessageException]){ - // Duplicate messages are dismissed - return ; - } else if ([exception.name isEqualToString:InvalidVersionException]){ - errorMessage = [TSErrorMessage invalidVersionWithSignal:signal withTransaction:transaction]; - } else if ([exception.name isEqualToString:UntrustedIdentityKeyException]){ - errorMessage = [TSInvalidIdentityKeyReceivingErrorMessage untrustedKeyWithSignal:signal withTransaction:transaction]; - } else { - errorMessage = [TSErrorMessage corruptedMessageWithSignal:signal withTransaction:transaction]; - } - - [errorMessage saveWithTransaction:transaction]; - }]; -} - -- (void)processException:(NSException*)exception outgoingMessage:(TSOutgoingMessage*)message inThread:(TSThread*)thread { - DDLogWarn(@"Got exception: %@", exception.description); - - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - TSErrorMessage *errorMessage; - - if ([exception.name isEqualToString:UntrustedIdentityKeyException]) { - errorMessage = [TSInvalidIdentityKeySendingErrorMessage untrustedKeyWithOutgoingMessage:message inThread:thread forRecipient:exception.userInfo[TSInvalidRecipientKey] preKeyBundle:exception.userInfo[TSInvalidPreKeyBundleKey] withTransaction:transaction]; - message.messageState = TSOutgoingMessageStateUnsent; - [message saveWithTransaction:transaction]; - } else if (message.groupMetaMessage==TSGroupMessageNone) { - // Only update this with exception if it is not a group message as group messages may except for one group send but not another and the UI doesn't know how to handle that - [message setMessageState:TSOutgoingMessageStateUnsent]; - [message saveWithTransaction:transaction]; - } - - [errorMessage saveWithTransaction:transaction]; - }]; -} - -- (NSUInteger)unreadMessagesCount { - __block NSUInteger numberOfItems; - [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - numberOfItems = [[transaction ext:TSUnreadDatabaseViewExtensionName] numberOfItemsInAllGroups]; - }]; - - return numberOfItems; -} - -- (NSUInteger)unreadMessagesCountExcept:(TSThread*)thread { - __block NSUInteger numberOfItems; - [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - numberOfItems = [[transaction ext:TSUnreadDatabaseViewExtensionName] numberOfItemsInAllGroups]; - numberOfItems = numberOfItems - [[transaction ext:TSUnreadDatabaseViewExtensionName] numberOfItemsInGroup:thread.uniqueId]; - }]; - - return numberOfItems; -} - -- (NSUInteger)unreadMessagesInThread:(TSThread*)thread { - __block NSUInteger numberOfItems; - [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - numberOfItems = [[transaction ext:TSUnreadDatabaseViewExtensionName] numberOfItemsInGroup:thread.uniqueId]; - }]; - return numberOfItems; -} - -- (void)notifyUserForCall:(TSCall*)call inThread:(TSThread*)thread { - if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive){ - // Remove previous notification of call and show missed notification. - UILocalNotification *notif = [[PushManager sharedManager] closeVOIPBackgroundTask]; - TSContactThread *cThread = (TSContactThread*)thread; - - if (call.callType == RPRecentCallTypeMissed) { - if (notif) { - [[UIApplication sharedApplication] cancelLocalNotification:notif]; - } - - UILocalNotification *notification = [[UILocalNotification alloc] init]; - notification.category = Signal_CallBack_Category; - notification.userInfo = @{Signal_Call_UserInfo_Key:cThread.contactIdentifier}; - notification.soundName = @"NewMessage.aifc"; - notification.alertBody = [NSString stringWithFormat:NSLocalizedString(@"MSGVIEW_MISSED_CALL", nil), [thread name]]; - - [[PushManager sharedManager] presentNotification:notification]; - } - } -} - -- (void)notifyUserForError:(TSErrorMessage*)message inThread:(TSThread*)thread { - NSString *messageDescription = message.description; - - if (([UIApplication sharedApplication].applicationState != UIApplicationStateActive) && messageDescription) { - UILocalNotification *notification = [[UILocalNotification alloc] init]; - notification.userInfo = @{Signal_Thread_UserInfo_Key:thread.uniqueId}; - notification.soundName = @"NewMessage.aifc"; - - NSString *alertBodyString = @""; - - NSString *authorName = [thread name]; - switch ([[Environment preferences] notificationPreviewType]) { - case NotificationNamePreview: - case NotificationNameNoPreview: - alertBodyString = [NSString stringWithFormat:@"%@: %@", authorName,messageDescription]; - break; - case NotificationNoNameNoPreview: - alertBodyString = messageDescription; - break; - } - notification.alertBody = alertBodyString; - - [[PushManager sharedManager]presentNotification:notification]; - } else { - if ([Environment.preferences soundInForeground]) { - AudioServicesPlayAlertSound(_newMessageSound); - } - } -} - -- (void)notifyUserForIncomingMessage:(TSIncomingMessage*)message from:(NSString*)name inThread:(TSThread*)thread { - NSString *messageDescription = message.description; - - if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive && messageDescription) { - UILocalNotification *notification = [[UILocalNotification alloc] init]; - notification.soundName = @"NewMessage.aifc"; - - switch ([[Environment preferences] notificationPreviewType]) { - case NotificationNamePreview: - notification.category = Signal_Full_New_Message_Category; - notification.userInfo = @{Signal_Thread_UserInfo_Key:thread.uniqueId, - Signal_Message_UserInfo_Key:message.uniqueId}; - - if ([thread isGroupThread]) { - NSString *sender = [[Environment getCurrent].contactsManager nameStringForPhoneIdentifier:message.authorId]; - if (!sender) { - sender = message.authorId; - } - - NSString *threadName = [NSString stringWithFormat:@"\"%@\"", name]; - notification.alertBody = [NSString stringWithFormat:NSLocalizedString(@"APN_MESSAGE_IN_GROUP_DETAILED", nil), sender, threadName, messageDescription]; - } else { - notification.alertBody = [NSString stringWithFormat:@"%@: %@", name, messageDescription]; - } - break; - case NotificationNameNoPreview:{ - notification.userInfo = @{Signal_Thread_UserInfo_Key:thread.uniqueId}; - if ([thread isGroupThread]) { - notification.alertBody = [NSString stringWithFormat:@"%@ \"%@\"", NSLocalizedString(@"APN_MESSAGE_IN_GROUP",nil), name]; - } else { - notification.alertBody = [NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"APN_MESSAGE_FROM", nil), name]; - } - break; - } - case NotificationNoNameNoPreview: - notification.alertBody = NSLocalizedString(@"APN_Message", nil); - break; - default: - notification.alertBody = NSLocalizedString(@"APN_Message", nil); - break; - } - - [[PushManager sharedManager] presentNotification:notification]; - } else { - if ([Environment.preferences soundInForeground]) { - AudioServicesPlayAlertSound(_newMessageSound); - } - } -} - -- (void)dealloc { - AudioServicesDisposeSystemSoundID(_newMessageSound); -} - -@end diff --git a/Signal/src/textsecure/Messages/TSOutgoingMessage.h b/Signal/src/textsecure/Messages/TSOutgoingMessage.h deleted file mode 100644 index 0ae93498a..000000000 --- a/Signal/src/textsecure/Messages/TSOutgoingMessage.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// TSOutgoingMessage.h -// TextSecureKit -// -// Created by Frederic Jacobs on 15/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSMessage.h" - -@interface TSOutgoingMessage : TSMessage - -typedef NS_ENUM(NSInteger, TSOutgoingMessageState){ - TSOutgoingMessageStateAttemptingOut, - TSOutgoingMessageStateUnsent, - TSOutgoingMessageStateSent, - TSOutgoingMessageStateDelivered -}; - -@property (nonatomic) TSOutgoingMessageState messageState; -@end diff --git a/Signal/src/textsecure/Messages/TSOutgoingMessage.m b/Signal/src/textsecure/Messages/TSOutgoingMessage.m deleted file mode 100644 index f637b888e..000000000 --- a/Signal/src/textsecure/Messages/TSOutgoingMessage.m +++ /dev/null @@ -1,34 +0,0 @@ -// -// TSOutgoingMessage.m -// TextSecureKit -// -// Created by Frederic Jacobs on 15/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSOutgoingMessage.h" - -@implementation TSOutgoingMessage - -- (instancetype)initWithTimestamp:(uint64_t)timestamp - inThread:(TSThread *)thread - messageBody:(NSString *)body - attachments:(NSMutableArray*)attachments -{ - self = [super initWithTimestamp:timestamp inThread:thread - messageBody:body attachments:attachments]; - - if (self) { - _messageState = TSOutgoingMessageStateAttemptingOut; - if( [thread isKindOfClass:[TSGroupThread class]]) { - self.groupMetaMessage = TSGroupMessageDeliver; - } - else { - self.groupMetaMessage = TSGroupMessageNone; - } - } - - return self; -} - -@end diff --git a/Signal/src/textsecure/Messages/TSServerMessage.h b/Signal/src/textsecure/Messages/TSServerMessage.h deleted file mode 100644 index da82d6315..000000000 --- a/Signal/src/textsecure/Messages/TSServerMessage.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// TSServerMessage.h -// TextSecureKit -// -// Created by Frederic Jacobs on 18/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import -#import "TSConstants.h" - -@interface TSServerMessage : MTLModel - -- (instancetype)initWithType:(TSWhisperMessageType)type - destination:(NSString*)destination - device:(int)deviceId - body:(NSData*)body - registrationId:(int)registrationId; - -@end diff --git a/Signal/src/textsecure/Messages/TSServerMessage.m b/Signal/src/textsecure/Messages/TSServerMessage.m deleted file mode 100644 index 146aee766..000000000 --- a/Signal/src/textsecure/Messages/TSServerMessage.m +++ /dev/null @@ -1,49 +0,0 @@ -// -// TSServerMessage.m -// TextSecureKit -// -// Created by Frederic Jacobs on 18/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSConstants.h" -#import "TSServerMessage.h" - -#import "NSData+Base64.h" - -@interface TSServerMessage () - -@property int type; -@property NSString *destination; -@property int destinationDeviceId; -@property int destinationRegistrationId; -@property NSString *body; - -@end - -@implementation TSServerMessage - -+ (NSDictionary *)JSONKeyPathsByPropertyKey{ - return [NSDictionary mtl_identityPropertyMapWithModel:[TSServerMessage class]]; -} - -- (instancetype)initWithType:(TSWhisperMessageType)type - destination:(NSString*)destination - device:(int)deviceId - body:(NSData*)body - registrationId:(int)registrationId -{ - self = [super init]; - - if (self) { - _type = type; - _destination = destination; - _destinationDeviceId = deviceId; - _destinationRegistrationId = registrationId; - _body = [body base64EncodedString]; - } - - return self; -} - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSAllocAttachmentRequest.h b/Signal/src/textsecure/Network/API/Requests/TSAllocAttachmentRequest.h deleted file mode 100644 index 3864ab2af..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSAllocAttachmentRequest.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// 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 diff --git a/Signal/src/textsecure/Network/API/Requests/TSAllocAttachmentRequest.m b/Signal/src/textsecure/Network/API/Requests/TSAllocAttachmentRequest.m deleted file mode 100644 index 78d32d6c4..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSAllocAttachmentRequest.m +++ /dev/null @@ -1,26 +0,0 @@ -// -// 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 diff --git a/Signal/src/textsecure/Network/API/Requests/TSAttachmentRequest.h b/Signal/src/textsecure/Network/API/Requests/TSAttachmentRequest.h deleted file mode 100644 index c6c512470..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSAttachmentRequest.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// TSRequestAttachment.h -// TextSecureiOS -// -// Created by Christine Corbett Moran on 12/1/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import "TSRequest.h" - -@interface TSAttachmentRequest : TSRequest - --(TSRequest*) initWithId:(NSNumber*) attachmentId relay:(NSString*)relay; - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSAttachmentRequest.m b/Signal/src/textsecure/Network/API/Requests/TSAttachmentRequest.m deleted file mode 100644 index be46555c9..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSAttachmentRequest.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// TSRequestAttachment.m -// TextSecureiOS -// -// Created by Christine Corbett Moran on 12/1/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import "TSAttachmentRequest.h" -#import "TSConstants.h" - -@implementation TSAttachmentRequest - --(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 diff --git a/Signal/src/textsecure/Network/API/Requests/TSAvailablePreKeysCountRequest.h b/Signal/src/textsecure/Network/API/Requests/TSAvailablePreKeysCountRequest.h deleted file mode 100644 index 64b2a2857..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSAvailablePreKeysCountRequest.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// TSAvailablePreKeysCountRequest.h -// Signal -// -// Created by Frederic Jacobs on 27/01/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import "TSRequest.h" - -@interface TSAvailablePreKeysCountRequest : TSRequest - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSAvailablePreKeysCountRequest.m b/Signal/src/textsecure/Network/API/Requests/TSAvailablePreKeysCountRequest.m deleted file mode 100644 index e95ae18f6..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSAvailablePreKeysCountRequest.m +++ /dev/null @@ -1,27 +0,0 @@ -// -// TSAvailablePreKeysCountRequest.m -// Signal -// -// Created by Frederic Jacobs on 27/01/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import "TSAvailablePreKeysCountRequest.h" - -#import "TSConstants.h" - -@implementation TSAvailablePreKeysCountRequest - --(instancetype)init { - NSString *path = [NSString stringWithFormat:@"%@", textSecureKeysAPI]; - - self = [super initWithURL:[NSURL URLWithString:path]]; - - if (self) { - [self setHTTPMethod:@"GET"]; - } - - return self; -} - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSContactsIntersectionRequest.h b/Signal/src/textsecure/Network/API/Requests/TSContactsIntersectionRequest.h deleted file mode 100644 index 7a794bc98..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSContactsIntersectionRequest.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// TSContactsIntersection.h -// TextSecureiOS -// -// Created by Frederic Jacobs on 10/12/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import "TSRequest.h" - -@interface TSContactsIntersectionRequest : TSRequest - -- (id)initWithHashesArray:(NSArray*)hashes; - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSContactsIntersectionRequest.m b/Signal/src/textsecure/Network/API/Requests/TSContactsIntersectionRequest.m deleted file mode 100644 index 844d7721a..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSContactsIntersectionRequest.m +++ /dev/null @@ -1,26 +0,0 @@ -// -// TSContactsIntersection.m -// TextSecureiOS -// -// Created by Frederic Jacobs on 10/12/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import "TSConstants.h" - -#import "TSContactsIntersectionRequest.h" - -@implementation TSContactsIntersectionRequest - -- (id)initWithHashesArray:(NSArray*)hashes{ - self = [self initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/%@", textSecureDirectoryAPI, @"tokens"]]]; - - self.HTTPMethod = @"PUT"; - - [self.parameters addEntriesFromDictionary:@{@"contacts": hashes}]; - - return self; - -} - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSCurrentSignedPreKeyRequest.h b/Signal/src/textsecure/Network/API/Requests/TSCurrentSignedPreKeyRequest.h deleted file mode 100644 index 982f3443d..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSCurrentSignedPreKeyRequest.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// TSCurrentSignedPreKeyRequest.h -// Signal -// -// Created by Frederic Jacobs on 27/01/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import "TSRequest.h" - -@interface TSCurrentSignedPreKeyRequest : TSRequest - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSCurrentSignedPreKeyRequest.m b/Signal/src/textsecure/Network/API/Requests/TSCurrentSignedPreKeyRequest.m deleted file mode 100644 index 32e41b58e..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSCurrentSignedPreKeyRequest.m +++ /dev/null @@ -1,22 +0,0 @@ -// -// TSCurrentSignedPreKeyRequest.m -// Signal -// -// Created by Frederic Jacobs on 27/01/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import "TSCurrentSignedPreKeyRequest.h" -#import "TSConstants.h" - -@implementation TSCurrentSignedPreKeyRequest - -- (instancetype)init { - self = [super initWithURL:[NSURL URLWithString:textSecureSignedKeysAPI]]; - - self.HTTPMethod = @"GET"; - - return self; -} - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSRecipientPrekeyRequest.h b/Signal/src/textsecure/Network/API/Requests/TSRecipientPrekeyRequest.h deleted file mode 100644 index 08c49c87f..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSRecipientPrekeyRequest.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// TSGetRecipientPrekey.h -// TextSecureiOS -// -// Created by Christine Corbett Moran on 11/30/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import "TSRequest.h" -@class TSContact; -@interface TSRecipientPrekeyRequest : TSRequest - --(TSRequest*) initWithRecipient:(NSString*)recipientNumber deviceId:(NSString*)deviceId; - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSRecipientPrekeyRequest.m b/Signal/src/textsecure/Network/API/Requests/TSRecipientPrekeyRequest.m deleted file mode 100644 index 89276baa2..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSRecipientPrekeyRequest.m +++ /dev/null @@ -1,25 +0,0 @@ -// -// TSGetRecipientPrekey.m -// TextSecureiOS -// -// Created by Christine Corbett Moran on 11/30/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import "TSConstants.h" -#import "TSRecipientPrekeyRequest.h" - -@implementation TSRecipientPrekeyRequest - --(TSRequest*) initWithRecipient:(NSString*)recipientNumber deviceId:(NSString*)deviceId{ - NSString* recipientInformation = recipientNumber; - - self = [super initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/%@/%@", textSecureKeysAPI, recipientInformation, deviceId]]]; - - self.HTTPMethod = @"GET"; - self.parameters = nil; - - return self; -} - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSRegisterForPushRequest.h b/Signal/src/textsecure/Network/API/Requests/TSRegisterForPushRequest.h deleted file mode 100644 index fa4cca013..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSRegisterForPushRequest.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// TSRegisterForPushRequest.h -// TextSecureiOS -// -// Created by Frederic Jacobs on 10/13/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import "TSRequest.h" - -@interface TSRegisterForPushRequest : TSRequest - -- (id) initWithPushIdentifier:(NSString*)identifier voipIdentifier:(NSString*)voipId; - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSRegisterForPushRequest.m b/Signal/src/textsecure/Network/API/Requests/TSRegisterForPushRequest.m deleted file mode 100644 index 7ecc5a851..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSRegisterForPushRequest.m +++ /dev/null @@ -1,30 +0,0 @@ -// -// TSRegisterForPushRequest.m -// TextSecureiOS -// -// Created by Frederic Jacobs on 10/13/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import "TSConstants.h" - -#import "TSRegisterForPushRequest.h" - -@implementation TSRegisterForPushRequest - -- (id) initWithPushIdentifier:(NSString*)identifier voipIdentifier:(NSString*)voipId -{ - self = [super initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/%@", textSecureAccountsAPI, @"apn"]]]; - - self.HTTPMethod = @"PUT"; - - self.parameters = [@{@"apnRegistrationId":identifier} mutableCopy]; - - if (voipId) { - [self.parameters setObject:voipId forKeyedSubscript:@"voipRegistrationId"]; - } - - return self; -} - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSRegisterPrekeysRequest.h b/Signal/src/textsecure/Network/API/Requests/TSRegisterPrekeysRequest.h deleted file mode 100644 index 1ffbbaa9f..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSRegisterPrekeysRequest.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// TSRegisterPrekeys.h -// TextSecureiOS -// -// Created by Christine Corbett Moran on 10/17/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import "TSRequest.h" -@class TSECKeyPair; -@class SignedPreKeyRecord; -@class PreKeyRecord; - -@interface TSRegisterPrekeysRequest : TSRequest - -- (id)initWithPrekeyArray:(NSArray*)prekeys - identityKey:(NSData*)identityKeyPublic - signedPreKeyRecord:(SignedPreKeyRecord*)signedRecord - preKeyLastResort:(PreKeyRecord*)lastResort; - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSRegisterPrekeysRequest.m b/Signal/src/textsecure/Network/API/Requests/TSRegisterPrekeysRequest.m deleted file mode 100644 index afe88661c..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSRegisterPrekeysRequest.m +++ /dev/null @@ -1,55 +0,0 @@ -// -// TSRegisterPrekeys.m -// TextSecureiOS -// -// Created by Christine Corbett Moran on 10/17/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import "TSConstants.h" -#import "TSRegisterPrekeysRequest.h" - -#import <25519/Curve25519.h> -#import -#import -#import - -@implementation TSRegisterPrekeysRequest - -- (id)initWithPrekeyArray:(NSArray*)prekeys identityKey:(NSData*)identityKeyPublic signedPreKeyRecord:(SignedPreKeyRecord*)signedRecord preKeyLastResort:(PreKeyRecord*)lastResort { - self = [super initWithURL:[NSURL URLWithString:textSecureKeysAPI]]; - self.HTTPMethod = @"PUT"; - - NSString *publicIdentityKey = [[identityKeyPublic prependKeyType] base64EncodedStringWithOptions:0]; - NSMutableArray *serializedPrekeyList = [NSMutableArray array]; - - for (PreKeyRecord *preKey in prekeys) { - [serializedPrekeyList addObject:[self dictionaryFromPreKey:preKey]]; - } - - NSDictionary *serializedKeyRegistrationParameters = @{@"preKeys": serializedPrekeyList, - @"lastResortKey":[self dictionaryFromPreKey:lastResort], - @"signedPreKey":[self dictionaryFromSignedPreKey:signedRecord] , - @"identityKey":publicIdentityKey - }; - - self.parameters = [serializedKeyRegistrationParameters mutableCopy]; - - return self; -} - - -- (NSDictionary*)dictionaryFromPreKey:(PreKeyRecord*)preKey { - return @{@"keyId":[NSNumber numberWithInt:preKey.Id], - @"publicKey":[[preKey.keyPair.publicKey prependKeyType] base64EncodedStringWithOptions:0], - }; -} - -- (NSDictionary*)dictionaryFromSignedPreKey:(SignedPreKeyRecord*)preKey { - return @{@"keyId":[NSNumber numberWithInt:preKey.Id], - @"publicKey":[[preKey.keyPair.publicKey prependKeyType] base64EncodedStringWithOptions:0], - @"signature":[preKey.signature base64EncodedStringWithOptions:0] - }; -} - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSRegisterWithTokenRequest.h b/Signal/src/textsecure/Network/API/Requests/TSRegisterWithTokenRequest.h deleted file mode 100644 index a7227e547..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSRegisterWithTokenRequest.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// TSRegisterWithTokenRequest.h -// TextSecureKit -// -// Created by Frederic Jacobs on 14/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSRequest.h" - -@interface TSRegisterWithTokenRequest : TSRequest - -- (instancetype)initWithVerificationToken:(NSString*)verificationCode signalingKey:(NSString*)signalingKey authKey:(NSString*)authKey number:(NSString*)number; - -@property NSString *numberToValidate; - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSRegisterWithTokenRequest.m b/Signal/src/textsecure/Network/API/Requests/TSRegisterWithTokenRequest.m deleted file mode 100644 index c542f1ff3..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSRegisterWithTokenRequest.m +++ /dev/null @@ -1,36 +0,0 @@ -// -// TSRegisterWithTokenRequest.m -// TextSecureKit -// -// Created by Frederic Jacobs on 14/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSConstants.h" -#import "TSAccountManager.h" -#import "TSAttributes.h" -#import "TSRegisterWithTokenRequest.h" - -@implementation TSRegisterWithTokenRequest - -- (TSRequest*) initWithVerificationToken:(NSString*)verificationCode - signalingKey:(NSString*)signalingKey - authKey:(NSString*)authKey - number:(NSString*)number -{ - self = [super initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/token/%@", textSecureAccountsAPI, verificationCode]]]; - - self.numberToValidate = number; - - NSDictionary *attributes = [TSAttributes attributesWithSignalingKey:signalingKey serverAuthToken:authKey]; - - [self.parameters addEntriesFromDictionary:attributes]; - - [self setHTTPMethod:@"PUT"]; - - return self; - -} - -@end - diff --git a/Signal/src/textsecure/Network/API/Requests/TSRequest.h b/Signal/src/textsecure/Network/API/Requests/TSRequest.h deleted file mode 100644 index 2f9573bfd..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSRequest.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// TSRequest.h -// TextSecureiOS -// -// Created by Frederic Jacobs on 9/27/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import - -@interface TSRequest : NSMutableURLRequest - -@property (nonatomic,retain) NSMutableDictionary *parameters; - -- (void) makeAuthenticatedRequest; - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSRequest.m b/Signal/src/textsecure/Network/API/Requests/TSRequest.m deleted file mode 100644 index ccf26c87e..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSRequest.m +++ /dev/null @@ -1,47 +0,0 @@ -// -// TSRequest.m -// TextSecureiOS -// -// Created by Frederic Jacobs on 9/27/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import "TSRequest.h" - -#import "TSStorageManager+keyingMaterial.h" -#import "TSConstants.h" - -@implementation TSRequest - -- (id)initWithURL:(NSURL *)URL{ - self = [super initWithURL:URL cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:textSecureHTTPTimeOut]; - self.parameters = [NSMutableDictionary dictionary]; - - return self; -} - -- (id)init{ - [NSException raise:NSInternalInconsistencyException - format:@"You must use the initWithURL: method"]; - return nil; -} - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wobjc-designated-initializers" - -- (id)initWithURL:(NSURL *)URL cachePolicy:(NSURLRequestCachePolicy)cachePolicy timeoutInterval:(NSTimeInterval)timeoutInterval{ - [NSException raise:NSInternalInconsistencyException - format:@"You must use the initWithURL method"]; - return nil; -} - -#pragma clang diagnostic pop - -- (void) makeAuthenticatedRequest{ - [self.parameters addEntriesFromDictionary:@{@"Authorization":[TSStorageManager serverAuthToken]}]; -} - -- (BOOL) usingExternalServer { - return NO; -} -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSSubmitMessageRequest.h b/Signal/src/textsecure/Network/API/Requests/TSSubmitMessageRequest.h deleted file mode 100644 index ecbf70695..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSSubmitMessageRequest.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// TSSubmitMessageRequest.h -// TextSecureiOS -// -// Created by Christine Corbett Moran on 11/30/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import "TSRequest.h" -#import "TSConstants.h" - -@interface TSSubmitMessageRequest : TSRequest - --(TSRequest*) initWithRecipient:(NSString*)contactRegisteredID - messages:(NSArray*)messages - relay:(NSString*)relay - timeStamp:(uint64_t)timeStamp; - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSSubmitMessageRequest.m b/Signal/src/textsecure/Network/API/Requests/TSSubmitMessageRequest.m deleted file mode 100644 index ed6dad025..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSSubmitMessageRequest.m +++ /dev/null @@ -1,34 +0,0 @@ -// -// TSSubmitMessageRequest.m -// TextSecureiOS -// -// Created by Christine Corbett Moran on 11/30/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import "TSConstants.h" - -#import "TSSubmitMessageRequest.h" - -@implementation TSSubmitMessageRequest - --(TSRequest*) initWithRecipient:(NSString*)contactRegisteredID - messages:(NSArray*)messages - relay:(NSString*)relay - timeStamp:(uint64_t)timeStamp -{ - self = [super initWithURL:[NSURL URLWithString:[textSecureMessagesAPI stringByAppendingString:contactRegisteredID]]]; - - NSMutableDictionary *allMessages = [@{@"messages":messages, @"timestamp":[NSNumber numberWithUnsignedLongLong:timeStamp]} mutableCopy]; - - if (relay) { - [allMessages setObject:relay forKey:@"relay"]; - } - - [self setHTTPMethod:@"PUT"]; - [self setParameters:allMessages]; - return self; -} - -@end - diff --git a/Signal/src/textsecure/Network/API/Requests/TSUnregisterAccountRequest.h b/Signal/src/textsecure/Network/API/Requests/TSUnregisterAccountRequest.h deleted file mode 100644 index 61f836941..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSUnregisterAccountRequest.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// TSDeregisterAccountRequest.h -// TextSecureiOS -// -// Created by Christine Corbett Moran on 3/16/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSRequest.h" - -@interface TSUnregisterAccountRequest : TSRequest -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSUnregisterAccountRequest.m b/Signal/src/textsecure/Network/API/Requests/TSUnregisterAccountRequest.m deleted file mode 100644 index 396c15557..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSUnregisterAccountRequest.m +++ /dev/null @@ -1,20 +0,0 @@ -// -// TSDeregisterAccountRequest.m -// TextSecureiOS -// -// Created by Christine Corbett Moran on 3/16/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSConstants.h" -#import "TSUnregisterAccountRequest.h" - -@implementation TSUnregisterAccountRequest - - -- (id)init { - self = [super initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/%@", textSecureAccountsAPI, @"apn"]]]; - self.HTTPMethod = @"DELETE"; - return self; -} -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSUpdateAttributesRequest.h b/Signal/src/textsecure/Network/API/Requests/TSUpdateAttributesRequest.h deleted file mode 100644 index 5cbd23aa9..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSUpdateAttributesRequest.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// TSUpdateAttributesRequest.h -// Signal -// -// Created by Frederic Jacobs on 22/08/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import "TSRequest.h" - -@interface TSUpdateAttributesRequest : TSRequest - -- (instancetype)initWithUpdatedAttributes; - -@end diff --git a/Signal/src/textsecure/Network/API/Requests/TSUpdateAttributesRequest.m b/Signal/src/textsecure/Network/API/Requests/TSUpdateAttributesRequest.m deleted file mode 100644 index 0f5ecbfde..000000000 --- a/Signal/src/textsecure/Network/API/Requests/TSUpdateAttributesRequest.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// TSUpdateAttributesRequest.m -// Signal -// -// Created by Frederic Jacobs on 22/08/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import "TSConstants.h" -#import "TSUpdateAttributesRequest.h" -#import "TSAttributes.h" - -@implementation TSUpdateAttributesRequest - -- (instancetype)initWithUpdatedAttributes -{ - NSString *endPoint = [textSecureAccountsAPI stringByAppendingString:textSecureAttributesAPI]; - self = [super initWithURL:[NSURL URLWithString:endPoint]]; - - if (self) { - [self setHTTPMethod:@"PUT"]; - [self.parameters addEntriesFromDictionary:[TSAttributes attributesFromStorage]]; - } - - return self; -} - -@end diff --git a/Signal/src/textsecure/Network/API/TSNetworkManager.h b/Signal/src/textsecure/Network/API/TSNetworkManager.h deleted file mode 100644 index 97bc0e5ad..000000000 --- a/Signal/src/textsecure/Network/API/TSNetworkManager.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// TSNetworkManager.h -// TextSecureiOS -// -// Created by Frederic Jacobs on 9/27/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -/** - * TSNetworkManager imports all TSRequests to prevent massive imports - in classes that call TSNetworkManager - */ -#import "TSAllocAttachmentRequest.h" -#import "TSAttachmentRequest.h" -#import "TSAvailablePreKeysCountRequest.h" -#import "TSContactsIntersectionRequest.h" -#import "TSCurrentSignedPreKeyRequest.h" -#import "TSRecipientPrekeyRequest.h" -#import "TSRegisterForPushRequest.h" -#import "TSRegisterPrekeysRequest.h" -#import "TSRegisterWithTokenRequest.h" -#import "TSSubmitMessageRequest.h" -#import "TSUnregisterAccountRequest.h" -#import "TSUpdateAttributesRequest.h" - - -#import -#import - -@interface TSNetworkManager : NSObject - -+ (id)sharedManager; - -- (void) queueAuthenticatedRequest:(TSRequest*) request success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; - -@end diff --git a/Signal/src/textsecure/Network/API/TSNetworkManager.m b/Signal/src/textsecure/Network/API/TSNetworkManager.m deleted file mode 100644 index 83e331db9..000000000 --- a/Signal/src/textsecure/Network/API/TSNetworkManager.m +++ /dev/null @@ -1,78 +0,0 @@ -// -// TSNetworkManager.m -// TextSecureiOS -// -// Created by Frederic Jacobs on 9/27/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import - -#import "AFSecurityOWSPolicy.h" - -#import "TSAccountManager.h" -#import "TSNetworkManager.h" -#import "TSRegisterWithTokenRequest.h" -#import "TSStorageManager+keyingMaterial.h" - -@interface TSNetworkManager () - -@property AFHTTPSessionManager *operationManager; - -@end - -@implementation TSNetworkManager - -#pragma mark Singleton implementation - -+ (id)sharedManager { - static TSNetworkManager *sharedMyManager = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - sharedMyManager = [[self alloc] init]; - }); - return sharedMyManager; -} - -- (id)init { - if (self = [super init]) { - NSURLSessionConfiguration *sessionConf = NSURLSessionConfiguration.ephemeralSessionConfiguration; - self.operationManager = [[AFHTTPSessionManager alloc] initWithBaseURL:[[NSURL alloc] initWithString:textSecureServerURL] sessionConfiguration:sessionConf]; - self.operationManager.securityPolicy = [AFSecurityOWSPolicy OWS_PinningPolicy]; - } - return self; -} - -#pragma mark Manager Methods - -- (void) queueAuthenticatedRequest:(TSRequest*) request success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure { - if ([request isKindOfClass:[TSRegisterWithTokenRequest class]]){ - // We plant the Authorization parameter ourselves, no need to double add. - self.operationManager.requestSerializer = [AFJSONRequestSerializer serializer]; - [self.operationManager.requestSerializer setAuthorizationHeaderFieldWithUsername:((TSRegisterWithTokenRequest*)request).numberToValidate password:[request.parameters objectForKey:@"AuthKey"]]; - - [request.parameters removeObjectForKey:@"AuthKey"]; - - [self.operationManager PUT:[textSecureServerURL stringByAppendingString:request.URL.absoluteString] parameters:request.parameters success:success failure:failure]; - } - else{ - // For all other equests, we do add an authorization header - self.operationManager.requestSerializer = [AFJSONRequestSerializer serializer]; - self.operationManager.responseSerializer = [AFJSONResponseSerializer serializer]; - - [self.operationManager.requestSerializer setAuthorizationHeaderFieldWithUsername:[TSAccountManager registeredNumber] password:[TSStorageManager serverAuthToken]]; - - 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]; - } else if ([request.HTTPMethod isEqualToString:@"PUT"]){ - [self.operationManager PUT:[textSecureServerURL stringByAppendingString:request.URL.absoluteString] parameters:request.parameters success:success failure:failure]; - } else if ([request.HTTPMethod isEqualToString:@"DELETE"]){ - [self.operationManager DELETE:[textSecureServerURL stringByAppendingString:request.URL.absoluteString] parameters:request.parameters success:success failure:failure]; - } - } -} - - -@end diff --git a/Signal/src/textsecure/Network/WebSockets/SubProtocol.pb.h b/Signal/src/textsecure/Network/WebSockets/SubProtocol.pb.h deleted file mode 100644 index 3978224dc..000000000 --- a/Signal/src/textsecure/Network/WebSockets/SubProtocol.pb.h +++ /dev/null @@ -1,264 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! - -#import - -// @@protoc_insertion_point(imports) - -@class WebSocketMessage; -@class WebSocketMessageBuilder; -@class WebSocketRequestMessage; -@class WebSocketRequestMessageBuilder; -@class WebSocketResponseMessage; -@class WebSocketResponseMessageBuilder; -#ifndef __has_feature - #define __has_feature(x) 0 // Compatibility with non-clang compilers. -#endif // __has_feature - -#ifndef NS_RETURNS_NOT_RETAINED - #if __has_feature(attribute_ns_returns_not_retained) - #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained)) - #else - #define NS_RETURNS_NOT_RETAINED - #endif -#endif - -typedef enum { - WebSocketMessageTypeUnknown = 0, - WebSocketMessageTypeRequest = 1, - WebSocketMessageTypeResponse = 2, -} WebSocketMessageType; - -BOOL WebSocketMessageTypeIsValidValue(WebSocketMessageType value); - - -@interface SubProtocolRoot : NSObject { -} -+ (PBExtensionRegistry*) extensionRegistry; -+ (void) registerAllExtensions:(PBMutableExtensionRegistry*) registry; -@end - -@interface WebSocketRequestMessage : PBGeneratedMessage { -@private - BOOL hasId_:1; - BOOL hasVerb_:1; - BOOL hasPath_:1; - BOOL hasBody_:1; - UInt64 id; - NSString* verb; - NSString* path; - NSData* body; -} -- (BOOL) hasVerb; -- (BOOL) hasPath; -- (BOOL) hasBody; -- (BOOL) hasId; -@property (readonly, strong) NSString* verb; -@property (readonly, strong) NSString* path; -@property (readonly, strong) NSData* body; -@property (readonly) UInt64 id; - -+ (WebSocketRequestMessage*) defaultInstance; -- (WebSocketRequestMessage*) defaultInstance; - -- (BOOL) isInitialized; -- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output; -- (WebSocketRequestMessageBuilder*) builder; -+ (WebSocketRequestMessageBuilder*) builder; -+ (WebSocketRequestMessageBuilder*) builderWithPrototype:(WebSocketRequestMessage*) prototype; -- (WebSocketRequestMessageBuilder*) toBuilder; - -+ (WebSocketRequestMessage*) parseFromData:(NSData*) data; -+ (WebSocketRequestMessage*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -+ (WebSocketRequestMessage*) parseFromInputStream:(NSInputStream*) input; -+ (WebSocketRequestMessage*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -+ (WebSocketRequestMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input; -+ (WebSocketRequestMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -@end - -@interface WebSocketRequestMessageBuilder : PBGeneratedMessageBuilder { -@private - WebSocketRequestMessage* result; -} - -- (WebSocketRequestMessage*) defaultInstance; - -- (WebSocketRequestMessageBuilder*) clear; -- (WebSocketRequestMessageBuilder*) clone; - -- (WebSocketRequestMessage*) build; -- (WebSocketRequestMessage*) buildPartial; - -- (WebSocketRequestMessageBuilder*) mergeFrom:(WebSocketRequestMessage*) other; -- (WebSocketRequestMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input; -- (WebSocketRequestMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; - -- (BOOL) hasVerb; -- (NSString*) verb; -- (WebSocketRequestMessageBuilder*) setVerb:(NSString*) value; -- (WebSocketRequestMessageBuilder*) clearVerb; - -- (BOOL) hasPath; -- (NSString*) path; -- (WebSocketRequestMessageBuilder*) setPath:(NSString*) value; -- (WebSocketRequestMessageBuilder*) clearPath; - -- (BOOL) hasBody; -- (NSData*) body; -- (WebSocketRequestMessageBuilder*) setBody:(NSData*) value; -- (WebSocketRequestMessageBuilder*) clearBody; - -- (BOOL) hasId; -- (UInt64) id; -- (WebSocketRequestMessageBuilder*) setId:(UInt64) value; -- (WebSocketRequestMessageBuilder*) clearId; -@end - -@interface WebSocketResponseMessage : PBGeneratedMessage { -@private - BOOL hasId_:1; - BOOL hasMessage_:1; - BOOL hasBody_:1; - BOOL hasStatus_:1; - UInt64 id; - NSString* message; - NSData* body; - UInt32 status; -} -- (BOOL) hasId; -- (BOOL) hasStatus; -- (BOOL) hasMessage; -- (BOOL) hasBody; -@property (readonly) UInt64 id; -@property (readonly) UInt32 status; -@property (readonly, strong) NSString* message; -@property (readonly, strong) NSData* body; - -+ (WebSocketResponseMessage*) defaultInstance; -- (WebSocketResponseMessage*) defaultInstance; - -- (BOOL) isInitialized; -- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output; -- (WebSocketResponseMessageBuilder*) builder; -+ (WebSocketResponseMessageBuilder*) builder; -+ (WebSocketResponseMessageBuilder*) builderWithPrototype:(WebSocketResponseMessage*) prototype; -- (WebSocketResponseMessageBuilder*) toBuilder; - -+ (WebSocketResponseMessage*) parseFromData:(NSData*) data; -+ (WebSocketResponseMessage*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -+ (WebSocketResponseMessage*) parseFromInputStream:(NSInputStream*) input; -+ (WebSocketResponseMessage*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -+ (WebSocketResponseMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input; -+ (WebSocketResponseMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -@end - -@interface WebSocketResponseMessageBuilder : PBGeneratedMessageBuilder { -@private - WebSocketResponseMessage* result; -} - -- (WebSocketResponseMessage*) defaultInstance; - -- (WebSocketResponseMessageBuilder*) clear; -- (WebSocketResponseMessageBuilder*) clone; - -- (WebSocketResponseMessage*) build; -- (WebSocketResponseMessage*) buildPartial; - -- (WebSocketResponseMessageBuilder*) mergeFrom:(WebSocketResponseMessage*) other; -- (WebSocketResponseMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input; -- (WebSocketResponseMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; - -- (BOOL) hasId; -- (UInt64) id; -- (WebSocketResponseMessageBuilder*) setId:(UInt64) value; -- (WebSocketResponseMessageBuilder*) clearId; - -- (BOOL) hasStatus; -- (UInt32) status; -- (WebSocketResponseMessageBuilder*) setStatus:(UInt32) value; -- (WebSocketResponseMessageBuilder*) clearStatus; - -- (BOOL) hasMessage; -- (NSString*) message; -- (WebSocketResponseMessageBuilder*) setMessage:(NSString*) value; -- (WebSocketResponseMessageBuilder*) clearMessage; - -- (BOOL) hasBody; -- (NSData*) body; -- (WebSocketResponseMessageBuilder*) setBody:(NSData*) value; -- (WebSocketResponseMessageBuilder*) clearBody; -@end - -@interface WebSocketMessage : PBGeneratedMessage { -@private - BOOL hasRequest_:1; - BOOL hasResponse_:1; - BOOL hasType_:1; - WebSocketRequestMessage* request; - WebSocketResponseMessage* response; - WebSocketMessageType type; -} -- (BOOL) hasType; -- (BOOL) hasRequest; -- (BOOL) hasResponse; -@property (readonly) WebSocketMessageType type; -@property (readonly, strong) WebSocketRequestMessage* request; -@property (readonly, strong) WebSocketResponseMessage* response; - -+ (WebSocketMessage*) defaultInstance; -- (WebSocketMessage*) defaultInstance; - -- (BOOL) isInitialized; -- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output; -- (WebSocketMessageBuilder*) builder; -+ (WebSocketMessageBuilder*) builder; -+ (WebSocketMessageBuilder*) builderWithPrototype:(WebSocketMessage*) prototype; -- (WebSocketMessageBuilder*) toBuilder; - -+ (WebSocketMessage*) parseFromData:(NSData*) data; -+ (WebSocketMessage*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -+ (WebSocketMessage*) parseFromInputStream:(NSInputStream*) input; -+ (WebSocketMessage*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -+ (WebSocketMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input; -+ (WebSocketMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; -@end - -@interface WebSocketMessageBuilder : PBGeneratedMessageBuilder { -@private - WebSocketMessage* result; -} - -- (WebSocketMessage*) defaultInstance; - -- (WebSocketMessageBuilder*) clear; -- (WebSocketMessageBuilder*) clone; - -- (WebSocketMessage*) build; -- (WebSocketMessage*) buildPartial; - -- (WebSocketMessageBuilder*) mergeFrom:(WebSocketMessage*) other; -- (WebSocketMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input; -- (WebSocketMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry; - -- (BOOL) hasType; -- (WebSocketMessageType) type; -- (WebSocketMessageBuilder*) setType:(WebSocketMessageType) value; -- (WebSocketMessageBuilder*) clearType; - -- (BOOL) hasRequest; -- (WebSocketRequestMessage*) request; -- (WebSocketMessageBuilder*) setRequest:(WebSocketRequestMessage*) value; -- (WebSocketMessageBuilder*) setRequestBuilder:(WebSocketRequestMessageBuilder*) builderForValue; -- (WebSocketMessageBuilder*) mergeRequest:(WebSocketRequestMessage*) value; -- (WebSocketMessageBuilder*) clearRequest; - -- (BOOL) hasResponse; -- (WebSocketResponseMessage*) response; -- (WebSocketMessageBuilder*) setResponse:(WebSocketResponseMessage*) value; -- (WebSocketMessageBuilder*) setResponseBuilder:(WebSocketResponseMessageBuilder*) builderForValue; -- (WebSocketMessageBuilder*) mergeResponse:(WebSocketResponseMessage*) value; -- (WebSocketMessageBuilder*) clearResponse; -@end - - -// @@protoc_insertion_point(global_scope) diff --git a/Signal/src/textsecure/Network/WebSockets/SubProtocol.pb.m b/Signal/src/textsecure/Network/WebSockets/SubProtocol.pb.m deleted file mode 100644 index c5d15a9e0..000000000 --- a/Signal/src/textsecure/Network/WebSockets/SubProtocol.pb.m +++ /dev/null @@ -1,1051 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! - -#import "SubProtocol.pb.h" -// @@protoc_insertion_point(imports) - -@implementation SubProtocolRoot -static PBExtensionRegistry* extensionRegistry = nil; -+ (PBExtensionRegistry*) extensionRegistry { - return extensionRegistry; -} - -+ (void) initialize { - if (self == [SubProtocolRoot class]) { - PBMutableExtensionRegistry* registry = [PBMutableExtensionRegistry registry]; - [self registerAllExtensions:registry]; - extensionRegistry = registry; - } -} -+ (void) registerAllExtensions:(PBMutableExtensionRegistry*) registry { -} -@end - -@interface WebSocketRequestMessage () -@property (strong) NSString* verb; -@property (strong) NSString* path; -@property (strong) NSData* body; -@property UInt64 id; -@end - -@implementation WebSocketRequestMessage - -- (BOOL) hasVerb { - return !!hasVerb_; -} -- (void) setHasVerb:(BOOL) value_ { - hasVerb_ = !!value_; -} -@synthesize verb; -- (BOOL) hasPath { - return !!hasPath_; -} -- (void) setHasPath:(BOOL) value_ { - hasPath_ = !!value_; -} -@synthesize path; -- (BOOL) hasBody { - return !!hasBody_; -} -- (void) setHasBody:(BOOL) value_ { - hasBody_ = !!value_; -} -@synthesize body; -- (BOOL) hasId { - return !!hasId_; -} -- (void) setHasId:(BOOL) value_ { - hasId_ = !!value_; -} -@synthesize id; -- (id) init { - if ((self = [super init])) { - self.verb = @""; - self.path = @""; - self.body = [NSData data]; - self.id = 0L; - } - return self; -} -static WebSocketRequestMessage* defaultWebSocketRequestMessageInstance = nil; -+ (void) initialize { - if (self == [WebSocketRequestMessage class]) { - defaultWebSocketRequestMessageInstance = [[WebSocketRequestMessage alloc] init]; - } -} -+ (WebSocketRequestMessage*) defaultInstance { - return defaultWebSocketRequestMessageInstance; -} -- (WebSocketRequestMessage*) defaultInstance { - return defaultWebSocketRequestMessageInstance; -} -- (BOOL) isInitialized { - return YES; -} -- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output { - if (self.hasVerb) { - [output writeString:1 value:self.verb]; - } - if (self.hasPath) { - [output writeString:2 value:self.path]; - } - if (self.hasBody) { - [output writeData:3 value:self.body]; - } - if (self.hasId) { - [output writeUInt64:4 value:self.id]; - } - [self.unknownFields writeToCodedOutputStream:output]; -} -- (SInt32) serializedSize { - __block SInt32 size_ = memoizedSerializedSize; - if (size_ != -1) { - return size_; - } - - size_ = 0; - if (self.hasVerb) { - size_ += computeStringSize(1, self.verb); - } - if (self.hasPath) { - size_ += computeStringSize(2, self.path); - } - if (self.hasBody) { - size_ += computeDataSize(3, self.body); - } - if (self.hasId) { - size_ += computeUInt64Size(4, self.id); - } - size_ += self.unknownFields.serializedSize; - memoizedSerializedSize = size_; - return size_; -} -+ (WebSocketRequestMessage*) parseFromData:(NSData*) data { - return (WebSocketRequestMessage*)[[[WebSocketRequestMessage builder] mergeFromData:data] build]; -} -+ (WebSocketRequestMessage*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (WebSocketRequestMessage*)[[[WebSocketRequestMessage builder] mergeFromData:data extensionRegistry:extensionRegistry] build]; -} -+ (WebSocketRequestMessage*) parseFromInputStream:(NSInputStream*) input { - return (WebSocketRequestMessage*)[[[WebSocketRequestMessage builder] mergeFromInputStream:input] build]; -} -+ (WebSocketRequestMessage*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (WebSocketRequestMessage*)[[[WebSocketRequestMessage builder] mergeFromInputStream:input extensionRegistry:extensionRegistry] build]; -} -+ (WebSocketRequestMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input { - return (WebSocketRequestMessage*)[[[WebSocketRequestMessage builder] mergeFromCodedInputStream:input] build]; -} -+ (WebSocketRequestMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (WebSocketRequestMessage*)[[[WebSocketRequestMessage builder] mergeFromCodedInputStream:input extensionRegistry:extensionRegistry] build]; -} -+ (WebSocketRequestMessageBuilder*) builder { - return [[WebSocketRequestMessageBuilder alloc] init]; -} -+ (WebSocketRequestMessageBuilder*) builderWithPrototype:(WebSocketRequestMessage*) prototype { - return [[WebSocketRequestMessage builder] mergeFrom:prototype]; -} -- (WebSocketRequestMessageBuilder*) builder { - return [WebSocketRequestMessage builder]; -} -- (WebSocketRequestMessageBuilder*) toBuilder { - return [WebSocketRequestMessage builderWithPrototype:self]; -} -- (void) writeDescriptionTo:(NSMutableString*) output withIndent:(NSString*) indent { - if (self.hasVerb) { - [output appendFormat:@"%@%@: %@\n", indent, @"verb", self.verb]; - } - if (self.hasPath) { - [output appendFormat:@"%@%@: %@\n", indent, @"path", self.path]; - } - if (self.hasBody) { - [output appendFormat:@"%@%@: %@\n", indent, @"body", self.body]; - } - if (self.hasId) { - [output appendFormat:@"%@%@: %@\n", indent, @"id", [NSNumber numberWithLongLong:self.id]]; - } - [self.unknownFields writeDescriptionTo:output withIndent:indent]; -} -- (BOOL) isEqual:(id)other { - if (other == self) { - return YES; - } - if (![other isKindOfClass:[WebSocketRequestMessage class]]) { - return NO; - } - WebSocketRequestMessage *otherMessage = other; - return - self.hasVerb == otherMessage.hasVerb && - (!self.hasVerb || [self.verb isEqual:otherMessage.verb]) && - self.hasPath == otherMessage.hasPath && - (!self.hasPath || [self.path isEqual:otherMessage.path]) && - self.hasBody == otherMessage.hasBody && - (!self.hasBody || [self.body isEqual:otherMessage.body]) && - self.hasId == otherMessage.hasId && - (!self.hasId || self.id == otherMessage.id) && - (self.unknownFields == otherMessage.unknownFields || (self.unknownFields != nil && [self.unknownFields isEqual:otherMessage.unknownFields])); -} -- (NSUInteger) hash { - __block NSUInteger hashCode = 7; - if (self.hasVerb) { - hashCode = hashCode * 31 + [self.verb hash]; - } - if (self.hasPath) { - hashCode = hashCode * 31 + [self.path hash]; - } - if (self.hasBody) { - hashCode = hashCode * 31 + [self.body hash]; - } - if (self.hasId) { - hashCode = hashCode * 31 + [[NSNumber numberWithLongLong:self.id] hash]; - } - hashCode = hashCode * 31 + [self.unknownFields hash]; - return hashCode; -} -@end - -@interface WebSocketRequestMessageBuilder() -@property (strong) WebSocketRequestMessage* result; -@end - -@implementation WebSocketRequestMessageBuilder -@synthesize result; -- (id) init { - if ((self = [super init])) { - self.result = [[WebSocketRequestMessage alloc] init]; - } - return self; -} -- (PBGeneratedMessage*) internalGetResult { - return result; -} -- (WebSocketRequestMessageBuilder*) clear { - self.result = [[WebSocketRequestMessage alloc] init]; - return self; -} -- (WebSocketRequestMessageBuilder*) clone { - return [WebSocketRequestMessage builderWithPrototype:result]; -} -- (WebSocketRequestMessage*) defaultInstance { - return [WebSocketRequestMessage defaultInstance]; -} -- (WebSocketRequestMessage*) build { - [self checkInitialized]; - return [self buildPartial]; -} -- (WebSocketRequestMessage*) buildPartial { - WebSocketRequestMessage* returnMe = result; - self.result = nil; - return returnMe; -} -- (WebSocketRequestMessageBuilder*) mergeFrom:(WebSocketRequestMessage*) other { - if (other == [WebSocketRequestMessage defaultInstance]) { - return self; - } - if (other.hasVerb) { - [self setVerb:other.verb]; - } - if (other.hasPath) { - [self setPath:other.path]; - } - if (other.hasBody) { - [self setBody:other.body]; - } - if (other.hasId) { - [self setId:other.id]; - } - [self mergeUnknownFields:other.unknownFields]; - return self; -} -- (WebSocketRequestMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input { - return [self mergeFromCodedInputStream:input extensionRegistry:[PBExtensionRegistry emptyRegistry]]; -} -- (WebSocketRequestMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - PBUnknownFieldSetBuilder* unknownFields = [PBUnknownFieldSet builderWithUnknownFields:self.unknownFields]; - while (YES) { - SInt32 tag = [input readTag]; - switch (tag) { - case 0: - [self setUnknownFields:[unknownFields build]]; - return self; - default: { - if (![self parseUnknownField:input unknownFields:unknownFields extensionRegistry:extensionRegistry tag:tag]) { - [self setUnknownFields:[unknownFields build]]; - return self; - } - break; - } - case 10: { - [self setVerb:[input readString]]; - break; - } - case 18: { - [self setPath:[input readString]]; - break; - } - case 26: { - [self setBody:[input readData]]; - break; - } - case 32: { - [self setId:[input readUInt64]]; - break; - } - } - } -} -- (BOOL) hasVerb { - return result.hasVerb; -} -- (NSString*) verb { - return result.verb; -} -- (WebSocketRequestMessageBuilder*) setVerb:(NSString*) value { - result.hasVerb = YES; - result.verb = value; - return self; -} -- (WebSocketRequestMessageBuilder*) clearVerb { - result.hasVerb = NO; - result.verb = @""; - return self; -} -- (BOOL) hasPath { - return result.hasPath; -} -- (NSString*) path { - return result.path; -} -- (WebSocketRequestMessageBuilder*) setPath:(NSString*) value { - result.hasPath = YES; - result.path = value; - return self; -} -- (WebSocketRequestMessageBuilder*) clearPath { - result.hasPath = NO; - result.path = @""; - return self; -} -- (BOOL) hasBody { - return result.hasBody; -} -- (NSData*) body { - return result.body; -} -- (WebSocketRequestMessageBuilder*) setBody:(NSData*) value { - result.hasBody = YES; - result.body = value; - return self; -} -- (WebSocketRequestMessageBuilder*) clearBody { - result.hasBody = NO; - result.body = [NSData data]; - return self; -} -- (BOOL) hasId { - return result.hasId; -} -- (UInt64) id { - return result.id; -} -- (WebSocketRequestMessageBuilder*) setId:(UInt64) value { - result.hasId = YES; - result.id = value; - return self; -} -- (WebSocketRequestMessageBuilder*) clearId { - result.hasId = NO; - result.id = 0L; - return self; -} -@end - -@interface WebSocketResponseMessage () -@property UInt64 id; -@property UInt32 status; -@property (strong) NSString* message; -@property (strong) NSData* body; -@end - -@implementation WebSocketResponseMessage - -- (BOOL) hasId { - return !!hasId_; -} -- (void) setHasId:(BOOL) value_ { - hasId_ = !!value_; -} -@synthesize id; -- (BOOL) hasStatus { - return !!hasStatus_; -} -- (void) setHasStatus:(BOOL) value_ { - hasStatus_ = !!value_; -} -@synthesize status; -- (BOOL) hasMessage { - return !!hasMessage_; -} -- (void) setHasMessage:(BOOL) value_ { - hasMessage_ = !!value_; -} -@synthesize message; -- (BOOL) hasBody { - return !!hasBody_; -} -- (void) setHasBody:(BOOL) value_ { - hasBody_ = !!value_; -} -@synthesize body; -- (id) init { - if ((self = [super init])) { - self.id = 0L; - self.status = 0; - self.message = @""; - self.body = [NSData data]; - } - return self; -} -static WebSocketResponseMessage* defaultWebSocketResponseMessageInstance = nil; -+ (void) initialize { - if (self == [WebSocketResponseMessage class]) { - defaultWebSocketResponseMessageInstance = [[WebSocketResponseMessage alloc] init]; - } -} -+ (WebSocketResponseMessage*) defaultInstance { - return defaultWebSocketResponseMessageInstance; -} -- (WebSocketResponseMessage*) defaultInstance { - return defaultWebSocketResponseMessageInstance; -} -- (BOOL) isInitialized { - return YES; -} -- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output { - if (self.hasId) { - [output writeUInt64:1 value:self.id]; - } - if (self.hasStatus) { - [output writeUInt32:2 value:self.status]; - } - if (self.hasMessage) { - [output writeString:3 value:self.message]; - } - if (self.hasBody) { - [output writeData:4 value:self.body]; - } - [self.unknownFields writeToCodedOutputStream:output]; -} -- (SInt32) serializedSize { - __block SInt32 size_ = memoizedSerializedSize; - if (size_ != -1) { - return size_; - } - - size_ = 0; - if (self.hasId) { - size_ += computeUInt64Size(1, self.id); - } - if (self.hasStatus) { - size_ += computeUInt32Size(2, self.status); - } - if (self.hasMessage) { - size_ += computeStringSize(3, self.message); - } - if (self.hasBody) { - size_ += computeDataSize(4, self.body); - } - size_ += self.unknownFields.serializedSize; - memoizedSerializedSize = size_; - return size_; -} -+ (WebSocketResponseMessage*) parseFromData:(NSData*) data { - return (WebSocketResponseMessage*)[[[WebSocketResponseMessage builder] mergeFromData:data] build]; -} -+ (WebSocketResponseMessage*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (WebSocketResponseMessage*)[[[WebSocketResponseMessage builder] mergeFromData:data extensionRegistry:extensionRegistry] build]; -} -+ (WebSocketResponseMessage*) parseFromInputStream:(NSInputStream*) input { - return (WebSocketResponseMessage*)[[[WebSocketResponseMessage builder] mergeFromInputStream:input] build]; -} -+ (WebSocketResponseMessage*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (WebSocketResponseMessage*)[[[WebSocketResponseMessage builder] mergeFromInputStream:input extensionRegistry:extensionRegistry] build]; -} -+ (WebSocketResponseMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input { - return (WebSocketResponseMessage*)[[[WebSocketResponseMessage builder] mergeFromCodedInputStream:input] build]; -} -+ (WebSocketResponseMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (WebSocketResponseMessage*)[[[WebSocketResponseMessage builder] mergeFromCodedInputStream:input extensionRegistry:extensionRegistry] build]; -} -+ (WebSocketResponseMessageBuilder*) builder { - return [[WebSocketResponseMessageBuilder alloc] init]; -} -+ (WebSocketResponseMessageBuilder*) builderWithPrototype:(WebSocketResponseMessage*) prototype { - return [[WebSocketResponseMessage builder] mergeFrom:prototype]; -} -- (WebSocketResponseMessageBuilder*) builder { - return [WebSocketResponseMessage builder]; -} -- (WebSocketResponseMessageBuilder*) toBuilder { - return [WebSocketResponseMessage builderWithPrototype:self]; -} -- (void) writeDescriptionTo:(NSMutableString*) output withIndent:(NSString*) indent { - if (self.hasId) { - [output appendFormat:@"%@%@: %@\n", indent, @"id", [NSNumber numberWithLongLong:self.id]]; - } - if (self.hasStatus) { - [output appendFormat:@"%@%@: %@\n", indent, @"status", [NSNumber numberWithInteger:self.status]]; - } - if (self.hasMessage) { - [output appendFormat:@"%@%@: %@\n", indent, @"message", self.message]; - } - if (self.hasBody) { - [output appendFormat:@"%@%@: %@\n", indent, @"body", self.body]; - } - [self.unknownFields writeDescriptionTo:output withIndent:indent]; -} -- (BOOL) isEqual:(id)other { - if (other == self) { - return YES; - } - if (![other isKindOfClass:[WebSocketResponseMessage class]]) { - return NO; - } - WebSocketResponseMessage *otherMessage = other; - return - self.hasId == otherMessage.hasId && - (!self.hasId || self.id == otherMessage.id) && - self.hasStatus == otherMessage.hasStatus && - (!self.hasStatus || self.status == otherMessage.status) && - self.hasMessage == otherMessage.hasMessage && - (!self.hasMessage || [self.message isEqual:otherMessage.message]) && - self.hasBody == otherMessage.hasBody && - (!self.hasBody || [self.body isEqual:otherMessage.body]) && - (self.unknownFields == otherMessage.unknownFields || (self.unknownFields != nil && [self.unknownFields isEqual:otherMessage.unknownFields])); -} -- (NSUInteger) hash { - __block NSUInteger hashCode = 7; - if (self.hasId) { - hashCode = hashCode * 31 + [[NSNumber numberWithLongLong:self.id] hash]; - } - if (self.hasStatus) { - hashCode = hashCode * 31 + [[NSNumber numberWithInteger:self.status] hash]; - } - if (self.hasMessage) { - hashCode = hashCode * 31 + [self.message hash]; - } - if (self.hasBody) { - hashCode = hashCode * 31 + [self.body hash]; - } - hashCode = hashCode * 31 + [self.unknownFields hash]; - return hashCode; -} -@end - -@interface WebSocketResponseMessageBuilder() -@property (strong) WebSocketResponseMessage* result; -@end - -@implementation WebSocketResponseMessageBuilder -@synthesize result; -- (id) init { - if ((self = [super init])) { - self.result = [[WebSocketResponseMessage alloc] init]; - } - return self; -} -- (PBGeneratedMessage*) internalGetResult { - return result; -} -- (WebSocketResponseMessageBuilder*) clear { - self.result = [[WebSocketResponseMessage alloc] init]; - return self; -} -- (WebSocketResponseMessageBuilder*) clone { - return [WebSocketResponseMessage builderWithPrototype:result]; -} -- (WebSocketResponseMessage*) defaultInstance { - return [WebSocketResponseMessage defaultInstance]; -} -- (WebSocketResponseMessage*) build { - [self checkInitialized]; - return [self buildPartial]; -} -- (WebSocketResponseMessage*) buildPartial { - WebSocketResponseMessage* returnMe = result; - self.result = nil; - return returnMe; -} -- (WebSocketResponseMessageBuilder*) mergeFrom:(WebSocketResponseMessage*) other { - if (other == [WebSocketResponseMessage defaultInstance]) { - return self; - } - if (other.hasId) { - [self setId:other.id]; - } - if (other.hasStatus) { - [self setStatus:other.status]; - } - if (other.hasMessage) { - [self setMessage:other.message]; - } - if (other.hasBody) { - [self setBody:other.body]; - } - [self mergeUnknownFields:other.unknownFields]; - return self; -} -- (WebSocketResponseMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input { - return [self mergeFromCodedInputStream:input extensionRegistry:[PBExtensionRegistry emptyRegistry]]; -} -- (WebSocketResponseMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - PBUnknownFieldSetBuilder* unknownFields = [PBUnknownFieldSet builderWithUnknownFields:self.unknownFields]; - while (YES) { - SInt32 tag = [input readTag]; - switch (tag) { - case 0: - [self setUnknownFields:[unknownFields build]]; - return self; - default: { - if (![self parseUnknownField:input unknownFields:unknownFields extensionRegistry:extensionRegistry tag:tag]) { - [self setUnknownFields:[unknownFields build]]; - return self; - } - break; - } - case 8: { - [self setId:[input readUInt64]]; - break; - } - case 16: { - [self setStatus:[input readUInt32]]; - break; - } - case 26: { - [self setMessage:[input readString]]; - break; - } - case 34: { - [self setBody:[input readData]]; - break; - } - } - } -} -- (BOOL) hasId { - return result.hasId; -} -- (UInt64) id { - return result.id; -} -- (WebSocketResponseMessageBuilder*) setId:(UInt64) value { - result.hasId = YES; - result.id = value; - return self; -} -- (WebSocketResponseMessageBuilder*) clearId { - result.hasId = NO; - result.id = 0L; - return self; -} -- (BOOL) hasStatus { - return result.hasStatus; -} -- (UInt32) status { - return result.status; -} -- (WebSocketResponseMessageBuilder*) setStatus:(UInt32) value { - result.hasStatus = YES; - result.status = value; - return self; -} -- (WebSocketResponseMessageBuilder*) clearStatus { - result.hasStatus = NO; - result.status = 0; - return self; -} -- (BOOL) hasMessage { - return result.hasMessage; -} -- (NSString*) message { - return result.message; -} -- (WebSocketResponseMessageBuilder*) setMessage:(NSString*) value { - result.hasMessage = YES; - result.message = value; - return self; -} -- (WebSocketResponseMessageBuilder*) clearMessage { - result.hasMessage = NO; - result.message = @""; - return self; -} -- (BOOL) hasBody { - return result.hasBody; -} -- (NSData*) body { - return result.body; -} -- (WebSocketResponseMessageBuilder*) setBody:(NSData*) value { - result.hasBody = YES; - result.body = value; - return self; -} -- (WebSocketResponseMessageBuilder*) clearBody { - result.hasBody = NO; - result.body = [NSData data]; - return self; -} -@end - -@interface WebSocketMessage () -@property WebSocketMessageType type; -@property (strong) WebSocketRequestMessage* request; -@property (strong) WebSocketResponseMessage* response; -@end - -@implementation WebSocketMessage - -- (BOOL) hasType { - return !!hasType_; -} -- (void) setHasType:(BOOL) value_ { - hasType_ = !!value_; -} -@synthesize type; -- (BOOL) hasRequest { - return !!hasRequest_; -} -- (void) setHasRequest:(BOOL) value_ { - hasRequest_ = !!value_; -} -@synthesize request; -- (BOOL) hasResponse { - return !!hasResponse_; -} -- (void) setHasResponse:(BOOL) value_ { - hasResponse_ = !!value_; -} -@synthesize response; -- (id) init { - if ((self = [super init])) { - self.type = WebSocketMessageTypeUnknown; - self.request = [WebSocketRequestMessage defaultInstance]; - self.response = [WebSocketResponseMessage defaultInstance]; - } - return self; -} -static WebSocketMessage* defaultWebSocketMessageInstance = nil; -+ (void) initialize { - if (self == [WebSocketMessage class]) { - defaultWebSocketMessageInstance = [[WebSocketMessage alloc] init]; - } -} -+ (WebSocketMessage*) defaultInstance { - return defaultWebSocketMessageInstance; -} -- (WebSocketMessage*) defaultInstance { - return defaultWebSocketMessageInstance; -} -- (BOOL) isInitialized { - return YES; -} -- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output { - if (self.hasType) { - [output writeEnum:1 value:self.type]; - } - if (self.hasRequest) { - [output writeMessage:2 value:self.request]; - } - if (self.hasResponse) { - [output writeMessage:3 value:self.response]; - } - [self.unknownFields writeToCodedOutputStream:output]; -} -- (SInt32) serializedSize { - __block SInt32 size_ = memoizedSerializedSize; - if (size_ != -1) { - return size_; - } - - size_ = 0; - if (self.hasType) { - size_ += computeEnumSize(1, self.type); - } - if (self.hasRequest) { - size_ += computeMessageSize(2, self.request); - } - if (self.hasResponse) { - size_ += computeMessageSize(3, self.response); - } - size_ += self.unknownFields.serializedSize; - memoizedSerializedSize = size_; - return size_; -} -+ (WebSocketMessage*) parseFromData:(NSData*) data { - return (WebSocketMessage*)[[[WebSocketMessage builder] mergeFromData:data] build]; -} -+ (WebSocketMessage*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (WebSocketMessage*)[[[WebSocketMessage builder] mergeFromData:data extensionRegistry:extensionRegistry] build]; -} -+ (WebSocketMessage*) parseFromInputStream:(NSInputStream*) input { - return (WebSocketMessage*)[[[WebSocketMessage builder] mergeFromInputStream:input] build]; -} -+ (WebSocketMessage*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (WebSocketMessage*)[[[WebSocketMessage builder] mergeFromInputStream:input extensionRegistry:extensionRegistry] build]; -} -+ (WebSocketMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input { - return (WebSocketMessage*)[[[WebSocketMessage builder] mergeFromCodedInputStream:input] build]; -} -+ (WebSocketMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - return (WebSocketMessage*)[[[WebSocketMessage builder] mergeFromCodedInputStream:input extensionRegistry:extensionRegistry] build]; -} -+ (WebSocketMessageBuilder*) builder { - return [[WebSocketMessageBuilder alloc] init]; -} -+ (WebSocketMessageBuilder*) builderWithPrototype:(WebSocketMessage*) prototype { - return [[WebSocketMessage builder] mergeFrom:prototype]; -} -- (WebSocketMessageBuilder*) builder { - return [WebSocketMessage builder]; -} -- (WebSocketMessageBuilder*) toBuilder { - return [WebSocketMessage builderWithPrototype:self]; -} -- (void) writeDescriptionTo:(NSMutableString*) output withIndent:(NSString*) indent { - if (self.hasType) { - [output appendFormat:@"%@%@: %d\n", indent, @"type", self.type]; - } - if (self.hasRequest) { - [output appendFormat:@"%@%@ {\n", indent, @"request"]; - [self.request writeDescriptionTo:output - withIndent:[NSString stringWithFormat:@"%@ ", indent]]; - [output appendFormat:@"%@}\n", indent]; - } - if (self.hasResponse) { - [output appendFormat:@"%@%@ {\n", indent, @"response"]; - [self.response writeDescriptionTo:output - withIndent:[NSString stringWithFormat:@"%@ ", indent]]; - [output appendFormat:@"%@}\n", indent]; - } - [self.unknownFields writeDescriptionTo:output withIndent:indent]; -} -- (BOOL) isEqual:(id)other { - if (other == self) { - return YES; - } - if (![other isKindOfClass:[WebSocketMessage class]]) { - return NO; - } - WebSocketMessage *otherMessage = other; - return - self.hasType == otherMessage.hasType && - (!self.hasType || self.type == otherMessage.type) && - self.hasRequest == otherMessage.hasRequest && - (!self.hasRequest || [self.request isEqual:otherMessage.request]) && - self.hasResponse == otherMessage.hasResponse && - (!self.hasResponse || [self.response isEqual:otherMessage.response]) && - (self.unknownFields == otherMessage.unknownFields || (self.unknownFields != nil && [self.unknownFields isEqual:otherMessage.unknownFields])); -} -- (NSUInteger) hash { - __block NSUInteger hashCode = 7; - if (self.hasType) { - hashCode = hashCode * 31 + self.type; - } - if (self.hasRequest) { - hashCode = hashCode * 31 + [self.request hash]; - } - if (self.hasResponse) { - hashCode = hashCode * 31 + [self.response hash]; - } - hashCode = hashCode * 31 + [self.unknownFields hash]; - return hashCode; -} -@end - -BOOL WebSocketMessageTypeIsValidValue(WebSocketMessageType value) { - switch (value) { - case WebSocketMessageTypeUnknown: - case WebSocketMessageTypeRequest: - case WebSocketMessageTypeResponse: - return YES; - default: - return NO; - } -} -@interface WebSocketMessageBuilder() -@property (strong) WebSocketMessage* result; -@end - -@implementation WebSocketMessageBuilder -@synthesize result; -- (id) init { - if ((self = [super init])) { - self.result = [[WebSocketMessage alloc] init]; - } - return self; -} -- (PBGeneratedMessage*) internalGetResult { - return result; -} -- (WebSocketMessageBuilder*) clear { - self.result = [[WebSocketMessage alloc] init]; - return self; -} -- (WebSocketMessageBuilder*) clone { - return [WebSocketMessage builderWithPrototype:result]; -} -- (WebSocketMessage*) defaultInstance { - return [WebSocketMessage defaultInstance]; -} -- (WebSocketMessage*) build { - [self checkInitialized]; - return [self buildPartial]; -} -- (WebSocketMessage*) buildPartial { - WebSocketMessage* returnMe = result; - self.result = nil; - return returnMe; -} -- (WebSocketMessageBuilder*) mergeFrom:(WebSocketMessage*) other { - if (other == [WebSocketMessage defaultInstance]) { - return self; - } - if (other.hasType) { - [self setType:other.type]; - } - if (other.hasRequest) { - [self mergeRequest:other.request]; - } - if (other.hasResponse) { - [self mergeResponse:other.response]; - } - [self mergeUnknownFields:other.unknownFields]; - return self; -} -- (WebSocketMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input { - return [self mergeFromCodedInputStream:input extensionRegistry:[PBExtensionRegistry emptyRegistry]]; -} -- (WebSocketMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry { - PBUnknownFieldSetBuilder* unknownFields = [PBUnknownFieldSet builderWithUnknownFields:self.unknownFields]; - while (YES) { - SInt32 tag = [input readTag]; - switch (tag) { - case 0: - [self setUnknownFields:[unknownFields build]]; - return self; - default: { - if (![self parseUnknownField:input unknownFields:unknownFields extensionRegistry:extensionRegistry tag:tag]) { - [self setUnknownFields:[unknownFields build]]; - return self; - } - break; - } - case 8: { - WebSocketMessageType value = (WebSocketMessageType)[input readEnum]; - if (WebSocketMessageTypeIsValidValue(value)) { - [self setType:value]; - } else { - [unknownFields mergeVarintField:1 value:value]; - } - break; - } - case 18: { - WebSocketRequestMessageBuilder* subBuilder = [WebSocketRequestMessage builder]; - if (self.hasRequest) { - [subBuilder mergeFrom:self.request]; - } - [input readMessage:subBuilder extensionRegistry:extensionRegistry]; - [self setRequest:[subBuilder buildPartial]]; - break; - } - case 26: { - WebSocketResponseMessageBuilder* subBuilder = [WebSocketResponseMessage builder]; - if (self.hasResponse) { - [subBuilder mergeFrom:self.response]; - } - [input readMessage:subBuilder extensionRegistry:extensionRegistry]; - [self setResponse:[subBuilder buildPartial]]; - break; - } - } - } -} -- (BOOL) hasType { - return result.hasType; -} -- (WebSocketMessageType) type { - return result.type; -} -- (WebSocketMessageBuilder*) setType:(WebSocketMessageType) value { - result.hasType = YES; - result.type = value; - return self; -} -- (WebSocketMessageBuilder*) clearType { - result.hasType = NO; - result.type = WebSocketMessageTypeUnknown; - return self; -} -- (BOOL) hasRequest { - return result.hasRequest; -} -- (WebSocketRequestMessage*) request { - return result.request; -} -- (WebSocketMessageBuilder*) setRequest:(WebSocketRequestMessage*) value { - result.hasRequest = YES; - result.request = value; - return self; -} -- (WebSocketMessageBuilder*) setRequestBuilder:(WebSocketRequestMessageBuilder*) builderForValue { - return [self setRequest:[builderForValue build]]; -} -- (WebSocketMessageBuilder*) mergeRequest:(WebSocketRequestMessage*) value { - if (result.hasRequest && - result.request != [WebSocketRequestMessage defaultInstance]) { - result.request = - [[[WebSocketRequestMessage builderWithPrototype:result.request] mergeFrom:value] buildPartial]; - } else { - result.request = value; - } - result.hasRequest = YES; - return self; -} -- (WebSocketMessageBuilder*) clearRequest { - result.hasRequest = NO; - result.request = [WebSocketRequestMessage defaultInstance]; - return self; -} -- (BOOL) hasResponse { - return result.hasResponse; -} -- (WebSocketResponseMessage*) response { - return result.response; -} -- (WebSocketMessageBuilder*) setResponse:(WebSocketResponseMessage*) value { - result.hasResponse = YES; - result.response = value; - return self; -} -- (WebSocketMessageBuilder*) setResponseBuilder:(WebSocketResponseMessageBuilder*) builderForValue { - return [self setResponse:[builderForValue build]]; -} -- (WebSocketMessageBuilder*) mergeResponse:(WebSocketResponseMessage*) value { - if (result.hasResponse && - result.response != [WebSocketResponseMessage defaultInstance]) { - result.response = - [[[WebSocketResponseMessage builderWithPrototype:result.response] mergeFrom:value] buildPartial]; - } else { - result.response = value; - } - result.hasResponse = YES; - return self; -} -- (WebSocketMessageBuilder*) clearResponse { - result.hasResponse = NO; - result.response = [WebSocketResponseMessage defaultInstance]; - return self; -} -@end - - -// @@protoc_insertion_point(global_scope) diff --git a/Signal/src/textsecure/Network/WebSockets/SubProtocol.proto b/Signal/src/textsecure/Network/WebSockets/SubProtocol.proto deleted file mode 100644 index 0fc5ce75d..000000000 --- a/Signal/src/textsecure/Network/WebSockets/SubProtocol.proto +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (C) 2014 Open WhisperSystems - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package textsecure; - -option java_package = "org.whispersystems.websocket.messages.protobuf"; - -message WebSocketRequestMessage { - optional string verb = 1; - optional string path = 2; - optional bytes body = 3; - optional uint64 id = 4; -} - -message WebSocketResponseMessage { - optional uint64 id = 1; - optional uint32 status = 2; - optional string message = 3; - optional bytes body = 4; -} - -message WebSocketMessage { - enum Type { - UNKNOWN = 0; - REQUEST = 1; - RESPONSE = 2; - } - - optional Type type = 1; - optional WebSocketRequestMessage request = 2; - optional WebSocketResponseMessage response = 3; -} \ No newline at end of file diff --git a/Signal/src/textsecure/Network/WebSockets/TSSocketManager.h b/Signal/src/textsecure/Network/WebSockets/TSSocketManager.h deleted file mode 100644 index 70868f58b..000000000 --- a/Signal/src/textsecure/Network/WebSockets/TSSocketManager.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// TSSocketManager.h -// TextSecureiOS -// -// Created by Frederic Jacobs on 17/05/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import -#import - -typedef enum : NSUInteger { - kSocketStatusOpen, - kSocketStatusClosed, - kSocketStatusConnecting, -} SocketStatus; - -static void *kSocketStatusObservationContext = &kSocketStatusObservationContext; - -extern NSString * const SocketOpenedNotification; -extern NSString * const SocketClosedNotification; -extern NSString * const SocketConnectingNotification; - -@interface TSSocketManager : NSObject - -+ (void)becomeActiveFromForeground; -+ (void)becomeActiveFromBackgroundExpectMessage:(BOOL)expected; - -+ (void)resignActivity; -+ (void)sendNotification; - -@end diff --git a/Signal/src/textsecure/Network/WebSockets/TSSocketManager.m b/Signal/src/textsecure/Network/WebSockets/TSSocketManager.m deleted file mode 100644 index c5ad4f585..000000000 --- a/Signal/src/textsecure/Network/WebSockets/TSSocketManager.m +++ /dev/null @@ -1,367 +0,0 @@ -// -// TSSocketManager.m -// TextSecureiOS -// -// Created by Frederic Jacobs on 17/05/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "SubProtocol.pb.h" - -#import "TSConstants.h" -#import "TSAccountManager.h" -#import "TSMessagesManager.h" -#import "TSSocketManager.h" -#import "TSStorageManager+keyingMaterial.h" - -#import "Cryptography.h" -#import "AFSecurityOWSPolicy.h" - -#define kWebSocketHeartBeat 30 -#define kWebSocketReconnectTry 5 -#define kBackgroundConnectTimer 25 -#define kBackgroundConnectKeepAlive 15 - -NSString * const SocketOpenedNotification = @"SocketOpenedNotification"; -NSString * const SocketClosedNotification = @"SocketClosedNotification"; -NSString * const SocketConnectingNotification = @"SocketConnectingNotification"; - -@interface TSSocketManager () -@property (nonatomic, retain) NSTimer *pingTimer; -@property (nonatomic, retain) NSTimer *reconnectTimer; - - -@property (nonatomic, retain) SRWebSocket *websocket; -@property (nonatomic) SocketStatus status; - -@property (nonatomic) UIBackgroundTaskIdentifier fetchingTaskIdentifier; - -@property BOOL didConnectBg; -@property BOOL didRetreiveMessageBg; -@property BOOL shouldDownloadMessage; - -@property (nonatomic, retain) NSTimer *backgroundKeepAliveTimer; -@property (nonatomic, retain) NSTimer *backgroundConnectTimer; - -@end - -@implementation TSSocketManager - -- (instancetype)init{ - self = [super init]; - - if (self) { - self.websocket = nil; - [self addObserver:self - forKeyPath:@"status" - options:0 - context:kSocketStatusObservationContext]; - } - - return self; -} - -+ (instancetype)sharedManager { - static TSSocketManager *sharedMyManager = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - sharedMyManager = [[self alloc] init]; - sharedMyManager.fetchingTaskIdentifier = UIBackgroundTaskInvalid; - sharedMyManager.didConnectBg = NO; - sharedMyManager.shouldDownloadMessage = NO; - sharedMyManager.didRetreiveMessageBg = NO; - }); - return sharedMyManager; -} - -#pragma mark - Manage Socket - -+ (void)becomeActive { - TSSocketManager *sharedInstance = [self sharedManager]; - SRWebSocket *socket = [sharedInstance websocket]; - - if (socket) { - switch ([socket readyState]) { - case SR_OPEN: - DDLogVerbose(@"WebSocket already open on connection request"); - sharedInstance.status = kSocketStatusOpen; - return; - case SR_CONNECTING: - DDLogVerbose(@"WebSocket is already connecting"); - sharedInstance.status = kSocketStatusConnecting; - return; - default: - [socket close]; - sharedInstance.status = kSocketStatusClosed; - socket.delegate = nil; - socket = nil; - break; - } - } - - NSString* webSocketConnect = [textSecureWebSocketAPI stringByAppendingString:[[self sharedManager] webSocketAuthenticationString]]; - NSURL* webSocketConnectURL = [NSURL URLWithString:webSocketConnect]; - NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:webSocketConnectURL]; - request.securityPolicy = [AFSecurityOWSPolicy OWS_PinningPolicy]; - - socket = [[SRWebSocket alloc] initWithURLRequest:request]; - socket.delegate = [self sharedManager]; - - [[self sharedManager] setWebsocket:socket]; - [socket open]; -} - -+ (void)resignActivity{ - SRWebSocket *socket = [[self sharedManager] websocket]; - [socket close]; -} - -#pragma mark - Delegate methods - -- (void)webSocketDidOpen:(SRWebSocket *)webSocket { - self.pingTimer = [NSTimer timerWithTimeInterval:kWebSocketHeartBeat - target:self - selector:@selector(webSocketHeartBeat) - userInfo:nil - repeats:YES]; - - // Additionally, we want the ping timer to work in the background too. - [[NSRunLoop mainRunLoop] addTimer:self.pingTimer - forMode:NSDefaultRunLoopMode]; - - self.status = kSocketStatusOpen; - [self.reconnectTimer invalidate]; - self.reconnectTimer = nil; - self.didConnectBg = YES; -} - -- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error { - DDLogError(@"Error connecting to socket %@", error); - - [self.pingTimer invalidate]; - self.status = kSocketStatusClosed; - [self scheduleRetry]; -} - -- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(NSData*)data { - WebSocketMessage *wsMessage = [WebSocketMessage parseFromData:data]; - self.didRetreiveMessageBg = YES; - - if (wsMessage.type == WebSocketMessageTypeRequest) { - [self processWebSocketRequestMessage:wsMessage.request]; - } else if (wsMessage.type == WebSocketMessageTypeResponse){ - [self processWebSocketResponseMessage:wsMessage.response]; - } else{ - DDLogWarn(@"Got a WebSocketMessage of unknown type"); - } -} - -- (void)processWebSocketRequestMessage:(WebSocketRequestMessage*)message { - DDLogInfo(@"Got message with verb: %@ and path: %@", message.verb, message.path); - - [self sendWebSocketMessageAcknowledgement:message]; - [self keepAliveBackground]; - - if ([message.path isEqualToString:@"/api/v1/message"] && [message.verb isEqualToString:@"PUT"]){ - NSData *decryptedPayload = [Cryptography decryptAppleMessagePayload:message.body - withSignalingKey:TSStorageManager.signalingKey]; - - if (!decryptedPayload) { - DDLogWarn(@"Failed to decrypt incoming payload or bad HMAC"); - return; - } - - IncomingPushMessageSignal *messageSignal = [IncomingPushMessageSignal parseFromData:decryptedPayload]; - - [[TSMessagesManager sharedManager] handleMessageSignal:messageSignal]; - } else{ - DDLogWarn(@"Unsupported WebSocket Request"); - } -} - -- (void)keepAliveBackground { - [self.backgroundConnectTimer invalidate]; - - if (self.fetchingTaskIdentifier) { - [self.backgroundKeepAliveTimer invalidate]; - - self.backgroundKeepAliveTimer = [NSTimer timerWithTimeInterval:kBackgroundConnectKeepAlive - target:self - selector:@selector(backgroundTimeExpired) - userInfo:nil - repeats:NO]; - // Additionally, we want the reconnect timer to work in the background too. - [[NSRunLoop mainRunLoop] addTimer:self.backgroundKeepAliveTimer - forMode:NSDefaultRunLoopMode]; - - } -} - -- (void)processWebSocketResponseMessage:(WebSocketResponseMessage*)message { - DDLogWarn(@"Client should not receive WebSocket Respond messages"); -} - -- (void)sendWebSocketMessageAcknowledgement:(WebSocketRequestMessage*)request { - WebSocketResponseMessageBuilder *response = [WebSocketResponseMessage builder]; - [response setStatus:200]; - [response setMessage:@"OK"]; - [response setId:request.id]; - - WebSocketMessageBuilder *message = [WebSocketMessage builder]; - [message setResponse:response.build]; - [message setType:WebSocketMessageTypeResponse]; - - @try { - [self.websocket send:message.build.data]; - } - @catch (NSException *exception) { - DDLogWarn(@"Caught exception while trying to write on the socket %@", exception.debugDescription); - } -} - -- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean { - [self.pingTimer invalidate]; - self.status = kSocketStatusClosed; - - if (!wasClean && [UIApplication sharedApplication].applicationState == UIApplicationStateActive) { - [self scheduleRetry]; - } -} - -- (void)webSocketHeartBeat { - @try { - [self.websocket sendPing:nil]; - } - @catch (NSException *exception) { - DDLogWarn(@"Caught exception while trying to write on the socket %@", exception.debugDescription); - } -} - -- (NSString*)webSocketAuthenticationString { - return [NSString stringWithFormat:@"?login=%@&password=%@", - [[TSAccountManager registeredNumber] stringByReplacingOccurrencesOfString:@"+" - withString:@"%2B"],[TSStorageManager serverAuthToken]]; -} - -- (void)scheduleRetry { - if (![self.reconnectTimer isValid]) { - self.reconnectTimer = [NSTimer timerWithTimeInterval:kWebSocketReconnectTry - target:[self class] - selector:@selector(becomeActive) - userInfo:nil - repeats:YES]; - // Additionally, we want the reconnect timer to work in the background too. - [[NSRunLoop mainRunLoop] addTimer:self.reconnectTimer - forMode:NSDefaultRunLoopMode]; - } else { - DDLogWarn(@"Not scheduling retry, valid timer"); - } -} - -#pragma mark - Background Connect - -+ (void)becomeActiveFromForeground { - TSSocketManager *sharedInstance = [self sharedManager]; - - if (sharedInstance.fetchingTaskIdentifier != UIBackgroundTaskInvalid) { - [sharedInstance closeBackgroundTask]; - } - - [self becomeActive]; -} - -+ (void)becomeActiveFromBackgroundExpectMessage:(BOOL)expected { - TSSocketManager *sharedInstance = [TSSocketManager sharedManager]; - - if (sharedInstance.fetchingTaskIdentifier == UIBackgroundTaskInvalid) { - sharedInstance.backgroundConnectTimer = [NSTimer timerWithTimeInterval:kBackgroundConnectTimer - target:sharedInstance - selector:@selector(backgroundConnectTimerExpired) - userInfo:nil - repeats:NO]; - NSRunLoop *loop = [NSRunLoop mainRunLoop]; - [loop addTimer:[TSSocketManager sharedManager].backgroundConnectTimer - forMode:NSDefaultRunLoopMode]; - - [sharedInstance.backgroundKeepAliveTimer invalidate]; - sharedInstance.didConnectBg = NO; - sharedInstance.didRetreiveMessageBg = NO; - sharedInstance.shouldDownloadMessage = expected; - sharedInstance.fetchingTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ - [TSSocketManager resignActivity]; - [[TSSocketManager sharedManager] closeBackgroundTask]; - }]; - - [self becomeActive]; - } else { - DDLogWarn(@"Got called to become active in the background but there was already a background task running."); - } -} - -- (void)backgroundConnectTimerExpired { - [self backgroundTimeExpired]; -} - -- (void)backgroundTimeExpired { - [[self class] resignActivity]; - [self closeBackgroundTask]; -} - -- (void)closeBackgroundTask { - [self.backgroundKeepAliveTimer invalidate]; - [self.backgroundConnectTimer invalidate]; - -/* - If VOIP Push worked, we should just have to check if message was retreived and if not, alert the user. - But we have to rely on the server for the fallback in failed cases since background push is unreliable. - https://devforums.apple.com/message/1135227 - - if ((self.shouldDownloadMessage && !self.didRetreiveMessageBg) || !self.didConnectBg) { - [self backgroundConnectTimedOut]; - } - - */ - - [[UIApplication sharedApplication] endBackgroundTask:self.fetchingTaskIdentifier]; - self.fetchingTaskIdentifier = UIBackgroundTaskInvalid; -} - -- (void)backgroundConnectTimedOut { - UILocalNotification *notification = [[UILocalNotification alloc] init]; - notification.alertBody = NSLocalizedString(@"APN_FETCHED_FAILED", nil); - notification.soundName = @"NewMessage.aifc"; - [[UIApplication sharedApplication] presentLocalNotificationNow:notification]; -} - -#pragma mark UI Delegates - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - if (context == kSocketStatusObservationContext) - { - [self notifyStatusChange]; - } else { - [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; - } -} - -- (void)notifyStatusChange { - switch (self.status) { - case kSocketStatusOpen: - [[NSNotificationCenter defaultCenter] postNotificationName:SocketOpenedNotification object:self]; - break; - case kSocketStatusClosed: - [[NSNotificationCenter defaultCenter] postNotificationName:SocketClosedNotification object:self]; - break; - case kSocketStatusConnecting: - [[NSNotificationCenter defaultCenter] postNotificationName:SocketConnectingNotification object:self]; - break; - default: - break; - } -} - -+ (void)sendNotification { - [[self sharedManager] notifyStatusChange]; -} - -@end diff --git a/Signal/src/textsecure/Security/SecurityUtils.h b/Signal/src/textsecure/Security/SecurityUtils.h deleted file mode 100644 index 7eb91c9b9..000000000 --- a/Signal/src/textsecure/Security/SecurityUtils.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// SecurityUtils.h -// TextSecureKit -// -// Created by Frederic Jacobs on 28/10/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import - -@interface SecurityUtils : NSObject - -+ (NSData*)generateRandomBytes:(int)numberBytes; - -@end diff --git a/Signal/src/textsecure/Security/SecurityUtils.m b/Signal/src/textsecure/Security/SecurityUtils.m deleted file mode 100644 index 100137e6a..000000000 --- a/Signal/src/textsecure/Security/SecurityUtils.m +++ /dev/null @@ -1,23 +0,0 @@ -// -// SecurityUtils.m -// TextSecureKit -// -// Created by Frederic Jacobs on 28/10/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "SecurityUtils.h" - -@implementation SecurityUtils - -+ (NSData*)generateRandomBytes:(int)numberBytes { - NSMutableData* randomBytes = [NSMutableData dataWithLength:(NSUInteger)numberBytes]; - int err = 0; - err = SecRandomCopyBytes(kSecRandomDefault,(size_t)numberBytes,[randomBytes mutableBytes]); - if(err != noErr) { - @throw [NSException exceptionWithName:@"random problem" reason:@"problem generating the random " userInfo:nil]; - } - return randomBytes; -} - -@end diff --git a/Signal/src/textsecure/Security/TSFingerprintGenerator.h b/Signal/src/textsecure/Security/TSFingerprintGenerator.h deleted file mode 100644 index 714e457ed..000000000 --- a/Signal/src/textsecure/Security/TSFingerprintGenerator.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// TSFingerprintGenerator.h -// Signal -// -// Created by Frederic Jacobs on 10/12/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import - -@interface TSFingerprintGenerator : NSObject - -+ (NSString*)getFingerprintForDisplay:(NSData*)identityKey; - -@end diff --git a/Signal/src/textsecure/Security/TSFingerprintGenerator.m b/Signal/src/textsecure/Security/TSFingerprintGenerator.m deleted file mode 100644 index 9181e203e..000000000 --- a/Signal/src/textsecure/Security/TSFingerprintGenerator.m +++ /dev/null @@ -1,37 +0,0 @@ -// -// TSFingerprintGenerator.m -// Signal -// -// Created by Frederic Jacobs on 10/12/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "NSData+hexString.h" -#import - -#import "TSFingerprintGenerator.h" - -@implementation TSFingerprintGenerator - -+ (NSString*)getFingerprintForDisplay:(NSData*)identityKey { - // idea here is to insert a space every two characters. there is probably a cleverer/more native way to do this. - - identityKey = [identityKey prependKeyType]; - NSString *fingerprint = [identityKey hexadecimalString]; - __block NSString* formattedFingerprint = @""; - - - [fingerprint enumerateSubstringsInRange:NSMakeRange(0, [fingerprint length]) - options:NSStringEnumerationByComposedCharacterSequences - usingBlock: - ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { - if (substringRange.location % 2 != 0 && substringRange.location != [fingerprint length]-1) { - substring = [substring stringByAppendingString:@" "]; - } - formattedFingerprint = [formattedFingerprint stringByAppendingString:substring]; - }]; - return formattedFingerprint; -} - - -@end diff --git a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+IdentityKeyStore.h b/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+IdentityKeyStore.h deleted file mode 100644 index 12b67827a..000000000 --- a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+IdentityKeyStore.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// TSStorageManager+IdentityKeyStore.h -// TextSecureKit -// -// Created by Frederic Jacobs on 06/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager.h" -#import - -@interface TSStorageManager (IdentityKeyStore) - -- (void)generateNewIdentityKey; -- (NSData*)identityKeyForRecipientId:(NSString*)recipientId; -- (void)removeIdentityKeyForRecipient:(NSString*)receipientId; - -@end diff --git a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+IdentityKeyStore.m b/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+IdentityKeyStore.m deleted file mode 100644 index adf4d20b2..000000000 --- a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+IdentityKeyStore.m +++ /dev/null @@ -1,56 +0,0 @@ -// -// TSStorageManager+IdentityKeyStore.m -// TextSecureKit -// -// Created by Frederic Jacobs on 06/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager+IdentityKeyStore.h" -#import "TSAccountManager.h" - -#import <25519/Curve25519.h> - -#define TSStorageManagerIdentityKeyStoreIdentityKey @"TSStorageManagerIdentityKeyStoreIdentityKey" // Key for our identity key -#define TSStorageManagerIdentityKeyStoreCollection @"TSStorageManagerIdentityKeyStoreCollection" -#define TSStorageManagerTrustedKeysCollection @"TSStorageManagerTrustedKeysCollection" - - - -@implementation TSStorageManager (IdentityKeyStore) - -- (void)generateNewIdentityKey { - [self setObject:[Curve25519 generateKeyPair] forKey:TSStorageManagerIdentityKeyStoreIdentityKey - inCollection:TSStorageManagerIdentityKeyStoreCollection]; -} - - -- (NSData*)identityKeyForRecipientId:(NSString*)recipientId{ - return [self dataForKey:recipientId inCollection:TSStorageManagerTrustedKeysCollection]; -} - - -- (ECKeyPair*)identityKeyPair { - return [self keyPairForKey:TSStorageManagerIdentityKeyStoreIdentityKey - inCollection:TSStorageManagerIdentityKeyStoreCollection]; -} - -- (int)localRegistrationId { - return (int)[TSAccountManager getOrGenerateRegistrationId]; -} - -- (void)saveRemoteIdentity:(NSData*)identityKey recipientId:(NSString*)recipientId { - [self setObject:identityKey forKey:recipientId inCollection:TSStorageManagerTrustedKeysCollection]; -} - -- (BOOL)isTrustedIdentityKey:(NSData*)identityKey recipientId:(NSString*)recipientId { - NSData *trusted = [self dataForKey:recipientId inCollection:TSStorageManagerTrustedKeysCollection]; - - return (trusted == nil || [trusted isEqualToData:identityKey]); -} - -- (void)removeIdentityKeyForRecipient:(NSString*)receipientId{ - [self removeObjectForKey:receipientId inCollection:TSStorageManagerTrustedKeysCollection]; -} - -@end diff --git a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+PreKeyStore.h b/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+PreKeyStore.h deleted file mode 100644 index 2ce93e8cf..000000000 --- a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+PreKeyStore.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// TSStorageManager+PreKeyStore.h -// TextSecureKit -// -// Created by Frederic Jacobs on 06/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager.h" -#import - -@interface TSStorageManager (PreKeyStore) - -- (NSArray*)generatePreKeyRecords; -- (PreKeyRecord*)getOrGenerateLastResortKey; -- (void)storePreKeyRecords:(NSArray*)preKeyRecords; - -@end diff --git a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+PreKeyStore.m b/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+PreKeyStore.m deleted file mode 100644 index 2798b5312..000000000 --- a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+PreKeyStore.m +++ /dev/null @@ -1,89 +0,0 @@ -// -// TSStorageManager+PreKeyStore.m -// TextSecureKit -// -// Created by Frederic Jacobs on 06/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager+PreKeyStore.h" -#import -#import "TSStorageManager+keyFromIntLong.h" - -#define TSStorageManagerPreKeyStoreCollection @"TSStorageManagerPreKeyStoreCollection" -#define TSNextPrekeyIdKey @"TSStorageInternalSettingsNextPreKeyId" -#define BATCH_SIZE 100 -#define MAX_VALUE_LASTRESORT 0xFFFFFF - -@implementation TSStorageManager (PreKeyStore) - -- (PreKeyRecord*)getOrGenerateLastResortKey { - if ([self containsPreKey:MAX_VALUE_LASTRESORT]) { - return [self loadPreKey:MAX_VALUE_LASTRESORT]; - } else{ - PreKeyRecord *lastResort = [[PreKeyRecord alloc] initWithId:MAX_VALUE_LASTRESORT keyPair:[Curve25519 generateKeyPair]]; - [self storePreKey:MAX_VALUE_LASTRESORT preKeyRecord:lastResort]; - return lastResort; - } -} - -- (NSArray*)generatePreKeyRecords { - NSMutableArray *preKeyRecords = [NSMutableArray array]; - - @synchronized(self){ - - int preKeyId = [self nextPreKeyId]; - for (int i = 0; i < BATCH_SIZE; i++) { - ECKeyPair *keyPair = [Curve25519 generateKeyPair]; - PreKeyRecord *record = [[PreKeyRecord alloc] initWithId:preKeyId keyPair:keyPair]; - - [preKeyRecords addObject:record]; - preKeyId++; - } - - [self setInt:preKeyId forKey:TSNextPrekeyIdKey inCollection:TSStorageInternalSettingsCollection]; - } - return preKeyRecords; -} - -- (void)storePreKeyRecords:(NSArray*)preKeyRecords { - for (PreKeyRecord *record in preKeyRecords) { - [self setObject:record forKey:[self keyFromInt:record.Id] inCollection:TSStorageManagerPreKeyStoreCollection]; - } -} - -- (PreKeyRecord*)loadPreKey:(int)preKeyId { - PreKeyRecord *preKeyRecord = [self preKeyRecordForKey:[self keyFromInt:preKeyId] inCollection:TSStorageManagerPreKeyStoreCollection]; - - if (!preKeyRecord) { - @throw [NSException exceptionWithName:InvalidKeyIdException reason:@"No key found matching key id" userInfo:@{}]; - } else { - return preKeyRecord; - } -} - -- (void)storePreKey:(int)preKeyId preKeyRecord:(PreKeyRecord*)record { - [self setObject:record forKey:[self keyFromInt:preKeyId] inCollection:TSStorageManagerPreKeyStoreCollection]; -} - -- (BOOL)containsPreKey:(int)preKeyId { - PreKeyRecord *preKeyRecord = [self preKeyRecordForKey:[self keyFromInt:preKeyId] - inCollection:TSStorageManagerPreKeyStoreCollection]; - return (preKeyRecord != nil); -} - -- (void)removePreKey:(int)preKeyId { - [self removeObjectForKey:[self keyFromInt:preKeyId] inCollection:TSStorageManagerPreKeyStoreCollection]; -} - -- (int)nextPreKeyId { - int lastPreKeyId = [self intForKey:TSNextPrekeyIdKey inCollection:TSStorageInternalSettingsCollection]; - - while (lastPreKeyId < 1 || (lastPreKeyId > (MAX_VALUE_LASTRESORT - BATCH_SIZE))) { - lastPreKeyId = rand(); - } - - return lastPreKeyId; -} - -@end diff --git a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SessionStore.h b/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SessionStore.h deleted file mode 100644 index d6a2a8e0c..000000000 --- a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SessionStore.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// TSStorageManager+SessionStore.h -// TextSecureKit -// -// Created by Frederic Jacobs on 06/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager.h" -#import - -@interface TSStorageManager (SessionStore) - -@end diff --git a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SessionStore.m b/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SessionStore.m deleted file mode 100644 index 713d2f6a5..000000000 --- a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SessionStore.m +++ /dev/null @@ -1,90 +0,0 @@ -// -// TSStorageManager+SessionStore.m -// TextSecureKit -// -// Created by Frederic Jacobs on 06/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager+SessionStore.h" - -#define TSStorageManagerSessionStoreCollection @"TSStorageManagerSessionStoreCollection" - -@implementation TSStorageManager (SessionStore) - -- (SessionRecord*)loadSession:(NSString*)contactIdentifier deviceId:(int)deviceId { - NSDictionary *dictionary = [self dictionaryForKey:contactIdentifier - inCollection:TSStorageManagerSessionStoreCollection]; - - SessionRecord *record; - - if (dictionary) { - record = [dictionary objectForKey:[self keyForInt:deviceId]]; - } - - if (!record) { - return [SessionRecord new]; - } - - return record; -} - -- (NSArray*)subDevicesSessions:(NSString*)contactIdentifier { - NSDictionary *dictionary = [self objectForKey:contactIdentifier inCollection:TSStorageManagerSessionStoreCollection]; - - NSMutableArray *subDevicesSessions = [NSMutableArray array]; - - if (dictionary) { - for (NSString *key in [dictionary allKeys]) { - NSNumber *number = @([key doubleValue]); - - [subDevicesSessions addObject:number]; - } - } - - return subDevicesSessions; -} - -- (void)storeSession:(NSString*)contactIdentifier deviceId:(int)deviceId session:(SessionRecord*)session { - NSMutableDictionary *dictionary = [[self dictionaryForKey:contactIdentifier - inCollection:TSStorageManagerSessionStoreCollection] mutableCopy]; - - if (!dictionary) { - dictionary = [NSMutableDictionary dictionary]; - } - - [dictionary setObject:session forKey:[self keyForInt:deviceId]]; - - [self setObject:dictionary forKey:contactIdentifier - inCollection:TSStorageManagerSessionStoreCollection]; -} - -- (BOOL)containsSession:(NSString*)contactIdentifier deviceId:(int)deviceId { - return [self loadSession:contactIdentifier deviceId:deviceId].sessionState.hasSenderChain; -} - -- (void)deleteSessionForContact:(NSString*)contactIdentifier deviceId:(int)deviceId { - NSMutableDictionary *dictionary = [[self dictionaryForKey:contactIdentifier - inCollection:TSStorageManagerSessionStoreCollection] mutableCopy]; - - if (!dictionary) { - dictionary = [NSMutableDictionary dictionary]; - } - - [dictionary removeObjectForKey:[self keyForInt:deviceId]]; - - [self setObject:dictionary forKey:contactIdentifier - inCollection:TSStorageManagerSessionStoreCollection]; -} - -- (void)deleteAllSessionsForContact:(NSString*)contactIdentifier { - [self removeObjectForKey:contactIdentifier - inCollection:TSStorageManagerSessionStoreCollection]; -} - - -- (NSNumber*)keyForInt:(int)number { - return [NSNumber numberWithInt:number]; -} - -@end diff --git a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SignedPreKeyStore.h b/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SignedPreKeyStore.h deleted file mode 100644 index 43c7bb988..000000000 --- a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SignedPreKeyStore.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// TSStorageManager+SignedPreKeyStore.h -// TextSecureKit -// -// Created by Frederic Jacobs on 06/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager.h" -#import - - -#define TSStorageManagerSignedPreKeyStoreCollection @"TSStorageManagerSignedPreKeyStoreCollection" - -@interface TSStorageManager (SignedPreKeyStore) - -- (SignedPreKeyRecord*)generateRandomSignedRecord; - -@end diff --git a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SignedPreKeyStore.m b/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SignedPreKeyStore.m deleted file mode 100644 index affefa644..000000000 --- a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+SignedPreKeyStore.m +++ /dev/null @@ -1,69 +0,0 @@ -// -// TSStorageManager+SignedPreKeyStore.m -// TextSecureKit -// -// Created by Frederic Jacobs on 06/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - - -#import "TSStorageManager+SignedPreKeyStore.h" -#import "TSStorageManager+IdentityKeyStore.h" -#import "TSStorageManager+keyFromIntLong.h" - -#import -#import <25519/Ed25519.h> -#import - -@implementation TSStorageManager (SignedPreKeyStore) - -- (SignedPreKeyRecord*)generateRandomSignedRecord { - ECKeyPair *keyPair = [Curve25519 generateKeyPair]; - return [[SignedPreKeyRecord alloc] initWithId:rand() keyPair:keyPair signature:[Ed25519 sign:keyPair.publicKey.prependKeyType withKeyPair:[self identityKeyPair]] generatedAt:[NSDate date]]; -} - -- (SignedPreKeyRecord*)loadSignedPrekey:(int)signedPreKeyId { - SignedPreKeyRecord *preKeyRecord = [self signedPreKeyRecordForKey:[self keyFromInt:signedPreKeyId] - inCollection:TSStorageManagerSignedPreKeyStoreCollection]; - - if (!preKeyRecord) { - @throw [NSException exceptionWithName:InvalidKeyIdException - reason:@"No key found matching key id" - userInfo:@{}]; - } else { - return preKeyRecord; - } -} - -- (NSArray*)loadSignedPreKeys { - NSMutableArray *signedPreKeyRecords = [NSMutableArray array]; - - YapDatabaseConnection *conn = [self newDatabaseConnection]; - - [conn readWithBlock:^(YapDatabaseReadTransaction *transaction) { - [transaction enumerateRowsInCollection:TSStorageManagerSignedPreKeyStoreCollection - usingBlock:^(NSString *key, id object, id metadata, BOOL *stop) { - [signedPreKeyRecords addObject:object]; - }]; - }]; - - return signedPreKeyRecords; -} - -- (void)storeSignedPreKey:(int)signedPreKeyId signedPreKeyRecord:(SignedPreKeyRecord*)signedPreKeyRecord { - [self setObject:signedPreKeyRecord forKey:[self keyFromInt:signedPreKeyId] - inCollection:TSStorageManagerSignedPreKeyStoreCollection]; -} - -- (BOOL)containsSignedPreKey:(int)signedPreKeyId { - PreKeyRecord *preKeyRecord = [self signedPreKeyRecordForKey:[self keyFromInt:signedPreKeyId] - inCollection:TSStorageManagerSignedPreKeyStoreCollection]; - return (preKeyRecord != nil); -} - -- (void)removeSignedPreKey:(int)signedPrekeyId { - [self removeObjectForKey:[self keyFromInt:signedPrekeyId] - inCollection:TSStorageManagerSignedPreKeyStoreCollection]; -} - -@end diff --git a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+keyFromIntLong.h b/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+keyFromIntLong.h deleted file mode 100644 index 6a44339bc..000000000 --- a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+keyFromIntLong.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// TSStorageManager+keyFromIntLong.h -// TextSecureKit -// -// Created by Frederic Jacobs on 08/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager.h" - -@interface TSStorageManager (keyFromIntLong) - -- (NSString*)keyFromInt:(int)integer; - -@end diff --git a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+keyFromIntLong.m b/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+keyFromIntLong.m deleted file mode 100644 index 6bf2eb5f3..000000000 --- a/Signal/src/textsecure/Storage/AxolotlStore/TSStorageManager+keyFromIntLong.m +++ /dev/null @@ -1,17 +0,0 @@ -// -// TSStorageManager+keyFromIntLong.m -// TextSecureKit -// -// Created by Frederic Jacobs on 08/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager+keyFromIntLong.h" - -@implementation TSStorageManager (keyFromIntLong) - -- (NSString*)keyFromInt:(int)integer { - return [[NSNumber numberWithInteger:integer] stringValue]; -} - -@end diff --git a/Signal/src/textsecure/Storage/TSDatabaseSecondaryIndexes.h b/Signal/src/textsecure/Storage/TSDatabaseSecondaryIndexes.h deleted file mode 100644 index 25c7ec05c..000000000 --- a/Signal/src/textsecure/Storage/TSDatabaseSecondaryIndexes.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// TSDatabaseSecondaryIndexes.h -// Signal -// -// Created by Frederic Jacobs on 26/01/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import - -#import -#import - -@interface TSDatabaseSecondaryIndexes : NSObject - -+ (YapDatabaseSecondaryIndex*)registerTimeStampIndex; - -+ (void)enumerateMessagesWithTimestamp:(uint64_t)timestamp withBlock:(void (^)(NSString *collection, NSString *key, BOOL *stop))block usingTransaction:(YapDatabaseReadWriteTransaction*)transaction; - -@end diff --git a/Signal/src/textsecure/Storage/TSDatabaseSecondaryIndexes.m b/Signal/src/textsecure/Storage/TSDatabaseSecondaryIndexes.m deleted file mode 100644 index 20f5a69f1..000000000 --- a/Signal/src/textsecure/Storage/TSDatabaseSecondaryIndexes.m +++ /dev/null @@ -1,47 +0,0 @@ -// -// TSDatabaseSecondaryIndexes.m -// Signal -// -// Created by Frederic Jacobs on 26/01/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import "TSDatabaseSecondaryIndexes.h" - -#import "TSInteraction.h" - -#define TSTimeStampSQLiteIndex @"messagesTimeStamp" - -@implementation TSDatabaseSecondaryIndexes - -+ (YapDatabaseSecondaryIndex*)registerTimeStampIndex { - YapDatabaseSecondaryIndexSetup *setup = [ [YapDatabaseSecondaryIndexSetup alloc] init]; - [setup addColumn:TSTimeStampSQLiteIndex withType:YapDatabaseSecondaryIndexTypeReal]; - - YapDatabaseSecondaryIndexWithObjectBlock block = ^(NSMutableDictionary *dict, NSString *collection, NSString *key, id object){ - - if ([object isKindOfClass:[TSInteraction class]]) - { - TSInteraction *interaction = (TSInteraction *)object; - - [dict setObject:@(interaction.timestamp) forKey:TSTimeStampSQLiteIndex]; - } - }; - - YapDatabaseSecondaryIndexHandler *handler = [YapDatabaseSecondaryIndexHandler withObjectBlock:block]; - - YapDatabaseSecondaryIndex *secondaryIndex = [[YapDatabaseSecondaryIndex alloc] initWithSetup:setup handler:handler]; - - return secondaryIndex; -} - - -+ (void)enumerateMessagesWithTimestamp:(uint64_t)timestamp - withBlock:(void (^)(NSString *collection, NSString *key, BOOL *stop))block - usingTransaction:(YapDatabaseReadWriteTransaction *)transaction { - - NSString *formattedString = [NSString stringWithFormat:@"WHERE %@ = %lld", TSTimeStampSQLiteIndex,timestamp]; - YapDatabaseQuery *query = [YapDatabaseQuery queryWithFormat:formattedString]; - [[transaction ext:@"idx"] enumerateKeysMatchingQuery:query usingBlock:block]; -} -@end diff --git a/Signal/src/textsecure/Storage/TSDatabaseView.h b/Signal/src/textsecure/Storage/TSDatabaseView.h deleted file mode 100644 index 73871c4d3..000000000 --- a/Signal/src/textsecure/Storage/TSDatabaseView.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// TSDatabaseView.h -// TextSecureKit -// -// Created by Frederic Jacobs on 17/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import -#import - -@interface TSDatabaseView : NSObject - -extern NSString *TSInboxGroup; -extern NSString *TSArchiveGroup; -extern NSString *TSUnreadIncomingMessagesGroup; - -extern NSString *TSThreadDatabaseViewExtensionName; -extern NSString *TSMessageDatabaseViewExtensionName; -extern NSString *TSUnreadDatabaseViewExtensionName; - -+ (BOOL)registerThreadDatabaseView; -+ (BOOL)registerBuddyConversationDatabaseView; -+ (BOOL)registerUnreadDatabaseView; - - -@end diff --git a/Signal/src/textsecure/Storage/TSDatabaseView.m b/Signal/src/textsecure/Storage/TSDatabaseView.m deleted file mode 100644 index e0dd10ce4..000000000 --- a/Signal/src/textsecure/Storage/TSDatabaseView.m +++ /dev/null @@ -1,201 +0,0 @@ -// -// TSDatabaseView.m -// TextSecureKit -// -// Created by Frederic Jacobs on 17/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSDatabaseView.h" - -#import - -#import "TSThread.h" -#import "TSIncomingMessage.h" -#import "TSStorageManager.h" - -NSString *TSInboxGroup = @"TSInboxGroup"; -NSString *TSArchiveGroup = @"TSArchiveGroup"; - -NSString *TSUnreadIncomingMessagesGroup = @"TSUnreadIncomingMessagesGroup"; - -NSString *TSThreadDatabaseViewExtensionName = @"TSThreadDatabaseViewExtensionName"; -NSString *TSMessageDatabaseViewExtensionName = @"TSMessageDatabaseViewExtensionName"; -NSString *TSUnreadDatabaseViewExtensionName = @"TSUnreadDatabaseViewExtensionName"; - -@implementation TSDatabaseView - -+ (BOOL)registerUnreadDatabaseView { - YapDatabaseView *unreadView = [[TSStorageManager sharedManager].database registeredExtension:TSUnreadDatabaseViewExtensionName]; - if (unreadView) { - return YES; - } - - YapDatabaseViewGrouping *viewGrouping = [YapDatabaseViewGrouping withObjectBlock:^NSString *(YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key, id object) { - if ([object isKindOfClass:[TSIncomingMessage class]]){ - TSIncomingMessage *message = (TSIncomingMessage*)object; - if (message.read == NO){ - return message.uniqueThreadId; - } - } - return nil; - }]; - - YapDatabaseViewSorting *viewSorting = [self messagesSorting]; - - YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init]; - options.isPersistent = YES; - options.allowedCollections = [[YapWhitelistBlacklist alloc] initWithWhitelist:[NSSet setWithObject:[TSInteraction collection]]]; - - YapDatabaseView *view = [[YapDatabaseView alloc] initWithGrouping:viewGrouping - sorting:viewSorting - versionTag:@"1" - options:options]; - - return [[TSStorageManager sharedManager].database registerExtension:view withName:TSUnreadDatabaseViewExtensionName]; -} - -+ (BOOL)registerThreadDatabaseView { - YapDatabaseView *threadView = [[TSStorageManager sharedManager].database registeredExtension:TSThreadDatabaseViewExtensionName]; - if (threadView) { - return YES; - } - - YapDatabaseViewGrouping *viewGrouping = [YapDatabaseViewGrouping withObjectBlock:^NSString *(YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key, id object) { - if ([object isKindOfClass:[TSThread class]]){ - TSThread *thread = (TSThread*)object; - if (thread.archivalDate) { - return ([self threadShouldBeInInbox:thread])?TSInboxGroup:TSArchiveGroup; - } - else if(thread.archivalDate) { - return TSArchiveGroup; - } - else { - return TSInboxGroup; - } - } - return nil; - }]; - - YapDatabaseViewSorting *viewSorting = [self threadSorting]; - - YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init]; - options.isPersistent = NO; - options.allowedCollections = [[YapWhitelistBlacklist alloc] initWithWhitelist:[NSSet setWithObject:[TSThread collection]]]; - - YapDatabaseView *databaseView = [[YapDatabaseView alloc] initWithGrouping:viewGrouping - sorting:viewSorting - versionTag:@"1" - options:options]; - - return [[TSStorageManager sharedManager].database registerExtension:databaseView withName:TSThreadDatabaseViewExtensionName]; -} - -+ (BOOL)registerBuddyConversationDatabaseView { - if ([[TSStorageManager sharedManager].database registeredExtension:TSMessageDatabaseViewExtensionName]) { - return YES; - } - - YapDatabaseViewGrouping *viewGrouping = [YapDatabaseViewGrouping withObjectBlock:^NSString *(YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key, id object) { - if ([object isKindOfClass:[TSInteraction class]]){ - return ((TSInteraction *)object).uniqueThreadId; - } - return nil; - }]; - - YapDatabaseViewSorting *viewSorting = [self messagesSorting]; - - YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init]; - options.isPersistent = YES; - options.allowedCollections = [[YapWhitelistBlacklist alloc] initWithWhitelist:[NSSet setWithObject:[TSInteraction collection]]]; - - YapDatabaseView *view = [[YapDatabaseView alloc] initWithGrouping:viewGrouping - sorting:viewSorting - versionTag:@"1" - options:options]; - - return [[TSStorageManager sharedManager].database registerExtension:view withName:TSMessageDatabaseViewExtensionName]; -} - - -/** - * Determines whether a thread belongs to the archive or inbox - * - * @param thread TSThread - * - * @return Inbox if true, Archive if false - */ - -+ (BOOL)threadShouldBeInInbox:(TSThread*)thread { - NSDate *lastMessageDate = thread.lastMessageDate; - NSDate *archivalDate = thread.archivalDate; - if (lastMessageDate&&archivalDate) { // this is what is called - return ([lastMessageDate timeIntervalSinceDate:archivalDate]>0)?YES:NO; // if there hasn't been a new message since the archive date, it's in the archive. an issue is that empty threads are always given with a lastmessage date of the present on every launch - } - else if(archivalDate) { - return NO; - } - - return YES; -} - -+ (YapDatabaseViewSorting*)threadSorting { - return [YapDatabaseViewSorting withObjectBlock:^NSComparisonResult(YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection1, NSString *key1, id object1, NSString *collection2, NSString *key2, id object2) { - if ([group isEqualToString:TSArchiveGroup] || [group isEqualToString:TSInboxGroup]) { - if ([object1 isKindOfClass:[TSThread class]] && [object2 isKindOfClass:[TSThread class]]){ - TSThread *thread1 = (TSThread*)object1; - TSThread *thread2 = (TSThread*)object2; - - return [thread1.lastMessageDate compare:thread2.lastMessageDate]; - } - } - - return NSOrderedSame; - }]; -} - -+ (YapDatabaseViewSorting*)messagesSorting { - return [YapDatabaseViewSorting withObjectBlock:^NSComparisonResult(YapDatabaseReadTransaction *transaction, NSString *group, NSString *collection1, NSString *key1, id object1, NSString *collection2, NSString *key2, id object2) { - if ([object1 isKindOfClass:[TSInteraction class]] && [object2 isKindOfClass:[TSInteraction class]]) { - TSInteraction *message1 = (TSInteraction*)object1; - TSInteraction *message2 = (TSInteraction*)object2; - - NSDate *date1 = [self localTimeReceiveDateForInteraction:message1]; - NSDate *date2 = [self localTimeReceiveDateForInteraction:message2]; - - NSComparisonResult result = [date1 compare:date2]; - - // NSDates are only accurate to the second, we might want finer precision - if (result != NSOrderedSame) { - return result; - } - - if (message1.timestamp > message2.timestamp) { - return NSOrderedDescending; - } else if (message1.timestamp < message2.timestamp){ - return NSOrderedAscending; - } else{ - return NSOrderedSame; - } - } - - return NSOrderedSame; - }]; -} - -+ (NSDate*)localTimeReceiveDateForInteraction:(TSInteraction*)interaction{ - NSDate *interactionDate = interaction.date; - - if ([interaction isKindOfClass:[TSIncomingMessage class]]) { - TSIncomingMessage *message = (TSIncomingMessage*)interaction; - - if (message.receivedAt) { - interactionDate = message.receivedAt; - } - - } - - return interactionDate; -} - -@end diff --git a/Signal/src/textsecure/Storage/TSStorageHeaders.h b/Signal/src/textsecure/Storage/TSStorageHeaders.h deleted file mode 100644 index 3ef754799..000000000 --- a/Signal/src/textsecure/Storage/TSStorageHeaders.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// TSStorageHeaders.h -// Signal -// -// Created by Frederic Jacobs on 22/08/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#ifndef Signal_TSStorageHeaders_h -#define Signal_TSStorageHeaders_h - -#import "TSStorageManager.h" - -#import "TSStorageManager+keyingMaterial.h" -#import "TSStorageManager+messageIDs.h" -#import "TSStorageManager+PreKeyStore.h" -#import "TSStorageManager+SessionStore.h" -#import "TSStorageManager+keyFromIntLong.h" -#import "TSStorageManager+IdentityKeyStore.h" -#import "TSStorageManager+SignedPreKeyStore.h" - -#endif diff --git a/Signal/src/textsecure/Storage/TSStorageKeys.h b/Signal/src/textsecure/Storage/TSStorageKeys.h deleted file mode 100644 index 524423f8c..000000000 --- a/Signal/src/textsecure/Storage/TSStorageKeys.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// TSStorageKeys.h -// TextSecureKit -// -// Created by Frederic Jacobs on 28/10/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#ifndef TextSecureKit_TSStorageKeys_h -#define TextSecureKit_TSStorageKeys_h - -#pragma mark User Account Keys - -#define TSStorageUserAccountCollection @"TSStorageUserAccountCollection" - -#define TSStorageRegisteredNumberKey @"TSStorageRegisteredNumberKey" -#define TSStorageServerAuthToken @"TSStorageServerAuthToken" -#define TSStorageServerSignalingKey @"TSStorageServerSignalingKey" -#define TSStorageLocalRegistrationId @"TSStorageLocalRegistrationId" - -/** - * Preferences exposed to the user - */ - -#pragma mark User Preferences - -#define TSStorageUserPreferencesCollection @"TSStorageUserPreferencesCollection" - - -/** - * Internal settings of the application, not exposed to the user. - */ - -#pragma mark Internal Settings - -#define TSStorageInternalSettingsCollection @"TSStorageInternalSettingsCollection" -#define TSStorageIsRegistered @"TSStorageIsRegistered" -#define TSStorageInternalSettingsVersion @"TSLastLaunchedVersion" - -#endif diff --git a/Signal/src/textsecure/Storage/TSStorageManager+keyingMaterial.h b/Signal/src/textsecure/Storage/TSStorageManager+keyingMaterial.h deleted file mode 100644 index 87143fc62..000000000 --- a/Signal/src/textsecure/Storage/TSStorageManager+keyingMaterial.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// TSStorageManager+keyingMaterial.h -// TextSecureKit -// -// Created by Frederic Jacobs on 06/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager.h" - -@interface TSStorageManager (keyingMaterial) - -#pragma mark Server Credentials - -/** - * The server signaling key that's used to encrypt push payloads - * - * @return signaling key - */ - -+ (NSString*)signalingKey; - -/** - * The server auth token allows the TextSecure client to connect to the server - * - * @return server authentication token - */ - -+ (NSString*)serverAuthToken; - -+ (void)storeServerToken:(NSString*)authToken signalingKey:(NSString*)signalingKey phoneNumber:(NSString*)phoneNumber; - -@end diff --git a/Signal/src/textsecure/Storage/TSStorageManager+keyingMaterial.m b/Signal/src/textsecure/Storage/TSStorageManager+keyingMaterial.m deleted file mode 100644 index 540116634..000000000 --- a/Signal/src/textsecure/Storage/TSStorageManager+keyingMaterial.m +++ /dev/null @@ -1,34 +0,0 @@ -// -// TSStorageManager+keyingMaterial.m -// TextSecureKit -// -// Created by Frederic Jacobs on 06/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager+keyingMaterial.h" - -@implementation TSStorageManager (keyingMaterial) - - -+ (NSString*)signalingKey{ - return [[self sharedManager] stringForKey:TSStorageServerSignalingKey - inCollection:TSStorageUserAccountCollection]; -} - -+ (NSString*)serverAuthToken{ - return [[self sharedManager] stringForKey:TSStorageServerAuthToken - inCollection:TSStorageUserAccountCollection]; -} - -+ (void)storeServerToken:(NSString*)authToken signalingKey:(NSString*)signalingKey phoneNumber:(NSString*)phoneNumber { - YapDatabaseConnection *dbConn = [[self sharedManager] dbConnection]; - - [dbConn readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [transaction setObject:authToken forKey:TSStorageServerAuthToken inCollection:TSStorageUserAccountCollection]; - [transaction setObject:signalingKey forKey:TSStorageServerSignalingKey inCollection:TSStorageUserAccountCollection]; - [transaction setObject:phoneNumber forKey:TSStorageRegisteredNumberKey inCollection:TSStorageUserAccountCollection]; - }]; -} - -@end diff --git a/Signal/src/textsecure/Storage/TSStorageManager+messageIDs.h b/Signal/src/textsecure/Storage/TSStorageManager+messageIDs.h deleted file mode 100644 index 341cb5df7..000000000 --- a/Signal/src/textsecure/Storage/TSStorageManager+messageIDs.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// TSStorageManager+messageIDs.h -// Signal -// -// Created by Frederic Jacobs on 24/01/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager.h" - -@interface TSStorageManager (messageIDs) - -+ (NSString*)getAndIncrementMessageIdWithTransaction:(YapDatabaseReadWriteTransaction*)transaction; - -@end diff --git a/Signal/src/textsecure/Storage/TSStorageManager+messageIDs.m b/Signal/src/textsecure/Storage/TSStorageManager+messageIDs.m deleted file mode 100644 index 7a21f4f2e..000000000 --- a/Signal/src/textsecure/Storage/TSStorageManager+messageIDs.m +++ /dev/null @@ -1,36 +0,0 @@ -// -// TSStorageManager+messageIDs.m -// Signal -// -// Created by Frederic Jacobs on 24/01/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager+messageIDs.h" - -#define TSStorageParametersCollection @"TSStorageParametersCollection" -#define TSMessagesLatestId @"TSMessagesLatestId" - -@implementation TSStorageManager (messageIDs) - -+ (NSString*)getAndIncrementMessageIdWithTransaction:(YapDatabaseReadWriteTransaction*)transaction { - NSString *messageId = [transaction objectForKey:TSMessagesLatestId inCollection:TSStorageParametersCollection]; - if (!messageId) { - messageId = @"0"; - } - - NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; - numberFormatter.numberStyle = NSNumberFormatterDecimalStyle; - NSNumber *myNumber = [numberFormatter numberFromString:messageId]; - - unsigned long long nextMessageId = [myNumber unsignedLongLongValue]; - nextMessageId ++; - - NSString *nextMessageIdString = [[NSNumber numberWithUnsignedLongLong:nextMessageId] stringValue]; - - [transaction setObject:nextMessageIdString forKey:TSMessagesLatestId inCollection:TSStorageParametersCollection]; - - return messageId; -} - -@end diff --git a/Signal/src/textsecure/Storage/TSStorageManager.h b/Signal/src/textsecure/Storage/TSStorageManager.h deleted file mode 100644 index 1df3f667d..000000000 --- a/Signal/src/textsecure/Storage/TSStorageManager.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// TSStorageManager.h -// TextSecureKit -// -// Created by Frederic Jacobs on 27/10/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageKeys.h" - -#import -#import - -@class ECKeyPair; -@class PreKeyRecord; -@class SignedPreKeyRecord; - -extern NSString *const TSUIDatabaseConnectionDidUpdateNotification; - -@interface TSStorageManager : NSObject - -+ (instancetype)sharedManager; -- (void)setupDatabase; -- (void)deleteThreadsAndMessages; -- (BOOL)databasePasswordAccessible; -- (void)wipeSignalStorage; - -- (YapDatabase*)database; -- (YapDatabaseConnection*)newDatabaseConnection; - - - -- (void)setObject:(id)object forKey:(NSString*)key inCollection:(NSString*)collection; -- (void)removeObjectForKey:(NSString*)string inCollection:(NSString *)collection; - - -- (BOOL)boolForKey:(NSString*)key inCollection:(NSString*)collection; -- (int)intForKey:(NSString*)key inCollection:(NSString*)collection; -- (void)setInt:(int)integer forKey:(NSString*)key inCollection:(NSString*)collection; -- (id)objectForKey:(NSString*)key inCollection:(NSString *)collection; -- (NSDictionary*)dictionaryForKey:(NSString*)key inCollection:(NSString *)collection; -- (NSString*)stringForKey:(NSString*)key inCollection:(NSString*)collection; -- (NSData*)dataForKey:(NSString*)key inCollection:(NSString*)collection; -- (ECKeyPair*)keyPairForKey:(NSString*)key inCollection:(NSString*)collection; -- (PreKeyRecord*)preKeyRecordForKey:(NSString*)key inCollection:(NSString*)collection; -- (SignedPreKeyRecord*)signedPreKeyRecordForKey:(NSString*)key inCollection:(NSString*)collection; -- (void)purgeCollection:(NSString*)collection; - -@property (nonatomic, readonly) YapDatabaseConnection *dbConnection; - -@end diff --git a/Signal/src/textsecure/Storage/TSStorageManager.m b/Signal/src/textsecure/Storage/TSStorageManager.m deleted file mode 100644 index b82895ef6..000000000 --- a/Signal/src/textsecure/Storage/TSStorageManager.m +++ /dev/null @@ -1,285 +0,0 @@ -// -// TSStorageManager.m -// TextSecureKit -// -// Created by Frederic Jacobs on 27/10/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager.h" -#import -#import "CryptoTools.h" -#import "DebugLogger.h" -#import "NSData+Base64.h" - -#import "TSThread.h" -#import "TSInteraction.h" - -#import -#import "TSDatabaseView.h" -#import "TSDatabaseSecondaryIndexes.h" - - -NSString *const TSUIDatabaseConnectionDidUpdateNotification = @"TSUIDatabaseConnectionDidUpdateNotification"; - -static const NSString *const databaseName = @"Signal.sqlite"; -static NSString * keychainService = @"TSKeyChainService"; -static NSString * keychainDBPassAccount = @"TSDatabasePass"; - -@interface TSStorageManager () - -@property YapDatabase *database; - -@end - -@implementation TSStorageManager - -+ (instancetype)sharedManager { - static TSStorageManager *sharedMyManager = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - sharedMyManager = [[self alloc] init]; - [sharedMyManager protectSignalFiles]; - }); - return sharedMyManager; -} - -- (instancetype)init { - self = [super init]; - - YapDatabaseOptions *options = [[YapDatabaseOptions alloc] init]; - options.corruptAction = YapDatabaseCorruptAction_Fail; - options.cipherKeyBlock = ^{ - return [self databasePassword]; - }; - - _database = [[YapDatabase alloc] initWithPath:[self dbPath] - serializer:NULL - deserializer:NULL - options:options]; - _dbConnection = self.newDatabaseConnection; - - return self; -} - -- (void)setupDatabase { - [TSDatabaseView registerThreadDatabaseView]; - [TSDatabaseView registerBuddyConversationDatabaseView]; - [TSDatabaseView registerUnreadDatabaseView]; - - [self.database registerExtension:[TSDatabaseSecondaryIndexes registerTimeStampIndex] withName:@"idx"]; - - [self.database registerExtension:[[YapDatabaseRelationship alloc] init] withName:@"TSRelationships"]; -} - - -- (void)protectSignalFiles{ - [self protectFolderAtPath:[TSAttachmentStream attachmentsFolder]]; - [self protectFolderAtPath:[self dbPath]]; - [self protectFolderAtPath:[[self dbPath] stringByAppendingString:@"-shm"]]; - [self protectFolderAtPath:[[self dbPath] stringByAppendingString:@"-wal"]]; - [self protectFolderAtPath:[[DebugLogger sharedInstance] logsDirectory]]; -} - -- (void)protectFolderAtPath:(NSString*)path { - if (![NSFileManager.defaultManager fileExistsAtPath:path]) { - return; - } - - NSError *error; - NSDictionary *fileProtection = @{NSFileProtectionKey:NSFileProtectionCompleteUntilFirstUserAuthentication}; - [[NSFileManager defaultManager] setAttributes:fileProtection ofItemAtPath:path error:&error]; - - NSDictionary *resourcesAttrs = @{NSURLIsExcludedFromBackupKey: @YES}; - - NSURL *ressourceURL = [NSURL fileURLWithPath:path]; - BOOL success = [ressourceURL setResourceValues:resourcesAttrs error:&error]; - - if (error || !success) { - DDLogError(@"Error while removing files from backup: %@", error.description); - SignalAlertView(NSLocalizedString(@"WARNING_STRING", @""), NSLocalizedString(@"DISABLING_BACKUP_FAILED", @"")); - return; - } -} - -- (YapDatabaseConnection *)newDatabaseConnection { - return self.database.newConnection; -} - -- (BOOL)userSetPassword { - return FALSE; -} - -- (BOOL)dbExists { - return [[NSFileManager defaultManager] fileExistsAtPath:[self dbPath]]; -} - -- (NSString*)dbPath { - - NSString *databasePath; - - NSFileManager* fileManager = [NSFileManager defaultManager]; -#if TARGET_OS_IPHONE - NSURL *fileURL = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; - NSString *path = [fileURL path]; - databasePath = [path stringByAppendingFormat:@"/%@", databaseName]; -#elif TARGET_OS_MAC - - NSString* bundleID = [[NSBundle mainBundle] bundleIdentifier]; - NSArray* urlPaths = [fileManager URLsForDirectory:NSApplicationSupportDirectory - inDomains:NSUserDomainMask]; - - NSURL* appDirectory = [[urlPaths objectAtIndex:0] URLByAppendingPathComponent:bundleID isDirectory:YES]; - - if (![fileManager fileExistsAtPath:[appDirectory path]]) { - [fileManager createDirectoryAtURL:appDirectory withIntermediateDirectories:NO attributes:nil error:nil]; - } - - databasePath = [appDirectory.filePathURL.absoluteString stringByAppendingFormat:@"/%@", databaseName]; -#endif - - return databasePath; -} - -- (BOOL)databasePasswordAccessible { - [SSKeychain setAccessibilityType:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly]; - NSError *error; - NSString *dbPassword = [SSKeychain passwordForService:keychainService account:keychainDBPassAccount error:&error]; - - if (dbPassword && !error) { - return YES; - } - - if (error) { - DDLogWarn(@"Database password couldn't be accessed: %@", error.localizedDescription); - } - - return NO; -} - -- (NSData*)databasePassword { - [SSKeychain setAccessibilityType:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly]; - NSString *dbPassword = [SSKeychain passwordForService:keychainService account:keychainDBPassAccount]; - - if (!dbPassword) { - dbPassword = [[CryptoTools generateSecureRandomData:30] base64EncodedString]; - [SSKeychain setPassword:dbPassword forService:keychainService account:keychainDBPassAccount]; - DDLogError(@"Set new password from keychain ..."); - } - - return [dbPassword dataUsingEncoding:NSUTF8StringEncoding]; -} - -#pragma mark convenience methods - -- (void)purgeCollection:(NSString*)collection { - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [transaction removeAllObjectsInCollection:collection]; - }]; -} - -- (void)setObject:(id)object forKey:(NSString*)key inCollection:(NSString*)collection { - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [transaction setObject:object forKey:key inCollection:collection]; - }]; -} - -- (void)removeObjectForKey:(NSString*)string inCollection:(NSString *)collection{ - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [transaction removeObjectForKey:string inCollection:collection]; - }]; -} - -- (id)objectForKey:(NSString*)key inCollection:(NSString *)collection { - __block NSString *object; - - [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - object = [transaction objectForKey:key inCollection:collection]; - }]; - - return object; -} - -- (NSDictionary*)dictionaryForKey:(NSString*)key inCollection:(NSString *)collection { - __block NSDictionary *object; - - [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - object = [transaction objectForKey:key inCollection:collection]; - }]; - - return object; -} - -- (NSString*)stringForKey:(NSString*)key inCollection:(NSString*)collection { - NSString *string = [self objectForKey:key inCollection:collection]; - - return string; -} - -- (BOOL)boolForKey:(NSString*)key inCollection:(NSString*)collection { - NSNumber *boolNum = [self objectForKey:key inCollection:collection]; - - return [boolNum boolValue]; -} - -- (NSData*)dataForKey:(NSString*)key inCollection:(NSString*)collection { - NSData *data = [self objectForKey:key inCollection:collection]; - return data; -} - -- (ECKeyPair*)keyPairForKey:(NSString*)key inCollection:(NSString*)collection { - ECKeyPair *keyPair = [self objectForKey:key inCollection:collection]; - - return keyPair; -} - -- (PreKeyRecord*)preKeyRecordForKey:(NSString*)key inCollection:(NSString*)collection { - PreKeyRecord *preKeyRecord = [self objectForKey:key inCollection:collection]; - - return preKeyRecord; -} - -- (SignedPreKeyRecord*)signedPreKeyRecordForKey:(NSString*)key inCollection:(NSString*)collection { - SignedPreKeyRecord *preKeyRecord = [self objectForKey:key inCollection:collection]; - - return preKeyRecord; -} - -- (int)intForKey:(NSString*)key inCollection:(NSString*)collection { - int integer = [[self objectForKey:key inCollection:collection] intValue]; - - return integer; -} - -- (void)setInt:(int)integer forKey:(NSString*)key inCollection:(NSString*)collection { - [self setObject:[NSNumber numberWithInt:integer] forKey:key inCollection:collection]; -} - -- (void)deleteThreadsAndMessages { - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [transaction removeAllObjectsInCollection:[TSThread collection]]; - [transaction removeAllObjectsInCollection:[SignalRecipient collection]]; - [transaction removeAllObjectsInCollection:[TSInteraction collection]]; - [transaction removeAllObjectsInCollection:[TSAttachment collection]]; - }]; - [TSAttachmentStream deleteAttachments]; -} - -- (void)wipeSignalStorage{ - self.database = nil; - NSError *error; - - [SSKeychain deletePasswordForService:keychainService account:keychainDBPassAccount]; - [[NSFileManager defaultManager] removeItemAtPath:[self dbPath] error:&error]; - - - if (error) { - DDLogError(@"Failed to delete database: %@", error.description); - } - - [TSAttachmentStream deleteAttachments]; - - [[self init] setupDatabase]; -} - -@end diff --git a/Signal/src/textsecure/Storage/TSYapDatabaseObject.h b/Signal/src/textsecure/Storage/TSYapDatabaseObject.h deleted file mode 100644 index 3b048b154..000000000 --- a/Signal/src/textsecure/Storage/TSYapDatabaseObject.h +++ /dev/null @@ -1,74 +0,0 @@ -// -// TSYapDatabaseObject.h -// TextSecureKit -// -// Created by Frederic Jacobs on 16/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import - -#import "YapDatabaseRelationshipNode.h" -#import "YapDatabaseTransaction.h" -#import - -@interface TSYapDatabaseObject : MTLModel - -/** - * Initializes a new database object with a unique identifier - * - * @param uniqueId Key used for the key-value store - * - * @return Initialized object - */ - -- (instancetype)initWithUniqueId:(NSString*)uniqueId; - -/** - * Returns the collection to which the object belongs. - * - * @return Key (string) identifying the collection - */ - -+ (NSString*)collection; - -/** - * Fetches the object with the provided identifier - * - * @param uniqueID Unique identifier of the entry in a collection - * @param transaction Transaction used for fetching the object - * - * @return Returns and instance of the object or nil if non-existent - */ - -+ (instancetype)fetchObjectWithUniqueID:(NSString*)uniqueID transaction:(YapDatabaseReadTransaction*)transaction; - -+ (instancetype) fetchObjectWithUniqueID:(NSString *)uniqueID; - -/** - * Saves the object with a new YapDatabaseConnection - */ - -- (void)save; - -/** - * Saves the object with the provided transaction - * - * @param transaction Database transaction - */ - -- (void)saveWithTransaction:(YapDatabaseReadWriteTransaction*)transaction; - - -/** - * The unique identifier of the stored object - */ - - -@property (nonatomic) NSString *uniqueId; - - -- (void)removeWithTransaction:(YapDatabaseReadWriteTransaction*)transaction; -- (void)remove; - -@end diff --git a/Signal/src/textsecure/Storage/TSYapDatabaseObject.m b/Signal/src/textsecure/Storage/TSYapDatabaseObject.m deleted file mode 100644 index 1a8096bd6..000000000 --- a/Signal/src/textsecure/Storage/TSYapDatabaseObject.m +++ /dev/null @@ -1,72 +0,0 @@ -// -// TSYapDatabaseObject.m -// TextSecureKit -// -// Created by Frederic Jacobs on 16/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSYapDatabaseObject.h" -#import "TSStorageManager.h" - -@implementation TSYapDatabaseObject - -- (id)init{ - if (self = [super init]) - { - _uniqueId = [[NSUUID UUID] UUIDString]; - } - return self; -} - -- (instancetype)initWithUniqueId:(NSString *)aUniqueId{ - if (self = [super init]) { - _uniqueId = aUniqueId; - } - return self; -} - -- (void)saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction{ - [transaction setObject:self forKey:self.uniqueId inCollection:[[self class] collection]]; -} - -- (void)save{ - [[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [self saveWithTransaction:transaction]; - }]; -} - -- (void)removeWithTransaction:(YapDatabaseReadWriteTransaction *)transaction{ - [transaction removeObjectForKey:self.uniqueId inCollection:[[self class] collection]]; -} - - -- (void)remove{ - [[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [self removeWithTransaction:transaction]; - [[transaction ext:@"relationships"] flush]; - }]; -} - - -#pragma mark Class Methods - -+ (NSString *)collection{ - return NSStringFromClass([self class]); -} - -+ (instancetype) fetchObjectWithUniqueID:(NSString *)uniqueID transaction:(YapDatabaseReadTransaction *)transaction { - return [transaction objectForKey:uniqueID inCollection:[self collection]]; -} - -+ (instancetype) fetchObjectWithUniqueID:(NSString *)uniqueID{ - __block id object; - - [[TSStorageManager sharedManager].dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - object = [transaction objectForKey:uniqueID inCollection:[self collection]]; - }]; - - return object; -} - -@end diff --git a/Signal/src/textsecure/TSConstants.h b/Signal/src/textsecure/TSConstants.h deleted file mode 100644 index 7be7f10e4..000000000 --- a/Signal/src/textsecure/TSConstants.h +++ /dev/null @@ -1,64 +0,0 @@ -// -// Constants.h -// TextSecureKit -// -// Created by Frederic Jacobs on 28/10/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import -@class TSNumberVerifier; - -#ifndef TextSecureKit_Constants_h -#define TextSecureKit_Constants_h - -typedef NS_ENUM(NSInteger, TSWhisperMessageType) { - TSUnknownMessageType =0, - TSEncryptedWhisperMessageType = 1, - TSIgnoreOnIOSWhisperMessageType=2, // on droid this is the prekey bundle message irrelevant for us - TSPreKeyWhisperMessageType = 3, - TSUnencryptedWhisperMessageType = 4, -}; - -typedef enum { - kSMSVerification, - kPhoneNumberVerification -} VerificationTransportType; - -#pragma mark Server Address - -#define textSecureHTTPTimeOut 10 - -#define textSecureWebSocketAPI @"wss://textsecure-service.whispersystems.org/v1/websocket/" -#define textSecureServerURL @"https://textsecure-service.whispersystems.org/" - -//#define textSecureWebSocketAPI @"wss://textsecure-service-staging.whispersystems.org/v1/websocket/" -//#define textSecureServerURL @"https://textsecure-service-staging.whispersystems.org/" - -#define textSecureGeneralAPI @"v1" -#define textSecureAccountsAPI @"v1/accounts" - #define textSecureAttributesAPI @"/attributes/" - -#define textSecureMessagesAPI @"v1/messages/" -#define textSecureKeysAPI @"v2/keys" -#define textSecureSignedKeysAPI @"v2/keys/signed" -#define textSecureDirectoryAPI @"v1/directory" -#define textSecureAttachmentsAPI @"v1/attachments" - - -typedef void(^successCompletionBlock)(void); -typedef void(^failedRegistrationRequestBlock)(void); - - -#pragma mark Push RegistrationSpecific Constants -typedef NS_ENUM(NSInteger, TSPushRegistrationError){ - TSPushRegistrationErrorNetwork, - TSPushRegistrationErrorAuthentication, - TSPushRegistrationErrorRequest -}; - -typedef void(^failedPushRegistrationRequestBlock)(TSPushRegistrationError error); - - - -#endif diff --git a/Signal/src/textsecure/Util/Cryptography.h b/Signal/src/textsecure/Util/Cryptography.h deleted file mode 100755 index f8e924312..000000000 --- a/Signal/src/textsecure/Util/Cryptography.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Cryptography.h -// TextSecureiOS -// -// Created by Christine Corbett Moran on 3/26/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import -#import "TSAttachmentEncryptionResult.h" - -@interface Cryptography : NSObject - -typedef NS_ENUM(NSInteger, TSMACType) { - TSHMACSHA1Truncated10Bytes = 1, - TSHMACSHA256Truncated10Bytes = 2, - TSHMACSHA256AttachementType = 3 -}; - -+(NSMutableData*) generateRandomBytes:(NSUInteger)numberBytes; - -#pragma mark SHA and HMAC methods - -+(NSData*) computeSHA256:(NSData *)data truncatedToBytes:(NSUInteger)truncatedBytes; -+(NSString*)truncatedSHA1Base64EncodedWithoutPadding:(NSString*)string; -+(NSString*)computeSHA1DigestForString:(NSString*)input; - -+(NSData*) computeSHA256HMAC:(NSData*)dataToHMAC withHMACKey:(NSData*)HMACKey; -+(NSData*) computeSHA1HMAC:(NSData*)dataToHMAC withHMACKey:(NSData*)HMACKey; -+(NSData*) truncatedSHA1HMAC:(NSData*)dataToHMAC withHMACKey:(NSData*)HMACKey truncation:(NSUInteger)bytes; - -+(NSData*) decryptAppleMessagePayload:(NSData*)payload withSignalingKey:(NSString*)signalingKeyString; - -#pragma mark encrypt and decrypt attachment data -+(NSData*) decryptAttachment:(NSData*)dataToDecrypt withKey:(NSData*)key ; - -+(TSAttachmentEncryptionResult*)encryptAttachment:(NSData*)attachment contentType:(NSString*)contentType identifier:(NSString*)identifier; -@end diff --git a/Signal/src/textsecure/Util/Cryptography.m b/Signal/src/textsecure/Util/Cryptography.m deleted file mode 100755 index d9f719fe5..000000000 --- a/Signal/src/textsecure/Util/Cryptography.m +++ /dev/null @@ -1,288 +0,0 @@ -// -// Cryptography.m -// TextSecureiOS -// -// Created by Christine Corbett Moran on 3/26/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import -#import - -#import "Cryptography.h" -#import "Constraints.h" - -#import "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 - - -#pragma mark random bytes methods -+(NSMutableData*) generateRandomBytes:(NSUInteger)numberBytes { - /* used to generate db master key, and to generate signaling key, both at install */ - NSMutableData* randomBytes = [NSMutableData dataWithLength:numberBytes]; - int err = 0; - err = SecRandomCopyBytes(kSecRandomDefault,numberBytes,[randomBytes mutableBytes]); - if(err != noErr) { - @throw [NSException exceptionWithName:@"random problem" reason:@"problem generating the random " userInfo:nil]; - } - return randomBytes; -} - -#pragma mark SHA1 - -+(NSString*)truncatedSHA1Base64EncodedWithoutPadding:(NSString*)string{ - /* used by TSContactManager to send hashed/truncated contact list to server */ - NSMutableData *hashData = [NSMutableData dataWithLength:20]; - - CC_SHA1([string dataUsingEncoding:NSUTF8StringEncoding].bytes, - (unsigned int)[string dataUsingEncoding:NSUTF8StringEncoding].length, - hashData.mutableBytes); - - NSData *truncatedData = [hashData subdataWithRange:NSMakeRange(0, 10)]; - - return [[truncatedData base64EncodedString] stringByReplacingOccurrencesOfString:@"=" withString:@""]; -} - -+ (NSString*)computeSHA1DigestForString:(NSString*)input { - // Here we are taking in our string hash, placing that inside of a C Char Array, then parsing it through the SHA1 encryption method. - const char *cstr = [input cStringUsingEncoding:NSUTF8StringEncoding]; - NSData *data = [NSData dataWithBytes:cstr length:input.length]; - uint8_t digest[CC_SHA1_DIGEST_LENGTH]; - - CC_SHA1(data.bytes, (unsigned int)data.length, digest); - - NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2]; - - for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) { - [output appendFormat:@"%02x", digest[i]]; - } - - return output; -} - -#pragma mark SHA256 -+(NSData*) computeSHA256:(NSData *)data truncatedToBytes:(NSUInteger)truncatedBytes { - uint8_t digest[CC_SHA256_DIGEST_LENGTH]; - CC_SHA256(data.bytes, (unsigned int)data.length, digest); - return [[NSData dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH] subdataWithRange:NSMakeRange(0, truncatedBytes)]; -} - - -#pragma mark HMAC/SHA256 -+(NSData*) computeSHA256HMAC:(NSData*)dataToHMAC withHMACKey:(NSData*)HMACKey{ - uint8_t ourHmac[CC_SHA256_DIGEST_LENGTH] = {0}; - CCHmac(kCCHmacAlgSHA256, - [HMACKey bytes], - [HMACKey length], - [dataToHMAC bytes], - [dataToHMAC length], - ourHmac); - return [NSData dataWithBytes:ourHmac length:CC_SHA256_DIGEST_LENGTH]; -} - -+(NSData*) computeSHA1HMAC:(NSData*)dataToHMAC withHMACKey:(NSData*)HMACKey{ - uint8_t ourHmac[CC_SHA256_DIGEST_LENGTH] = {0}; - CCHmac(kCCHmacAlgSHA1, - [HMACKey bytes], - [HMACKey length], - [dataToHMAC bytes], - [dataToHMAC length], - ourHmac); - return [NSData dataWithBytes:ourHmac length:CC_SHA256_DIGEST_LENGTH]; -} - - -+(NSData*) truncatedSHA1HMAC:(NSData*)dataToHMAC withHMACKey:(NSData*)HMACKey truncation:(NSUInteger)bytes{ - return [[Cryptography computeSHA1HMAC:dataToHMAC withHMACKey:HMACKey] subdataWithRange:NSMakeRange(0, bytes)]; -} - -+(NSData*) truncatedSHA256HMAC:(NSData*)dataToHMAC withHMACKey:(NSData*)HMACKey truncation:(NSUInteger)bytes{ - return [[Cryptography computeSHA256HMAC:dataToHMAC withHMACKey:HMACKey] subdataWithRange:NSMakeRange(0, bytes)]; -} - - -#pragma mark AES CBC Mode -+(NSData*)encryptCBCMode:(NSData*) dataToEncrypt withKey:(NSData*) key withIV:(NSData*) iv withVersion:(NSData*)version withHMACKey:(NSData*) hmacKey withHMACType:(TSMACType)hmacType computedHMAC:(NSData**)hmac { - /* AES256 CBC encrypt then mac - Returns nil if encryption fails - */ - size_t bufferSize = [dataToEncrypt length] + kCCBlockSizeAES128; - void* buffer = malloc(bufferSize); - - size_t bytesEncrypted = 0; - CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, - [key bytes], [key length], - [iv bytes], - [dataToEncrypt bytes], [dataToEncrypt length], - buffer, bufferSize, - &bytesEncrypted); - - if (cryptStatus == kCCSuccess){ - NSData* encryptedData= [NSData dataWithBytesNoCopy:buffer length:bytesEncrypted]; - //compute hmac of version||encrypted data||iv - NSMutableData *dataToHmac = [NSMutableData data]; - if(version!=nil) { - [dataToHmac appendData:version]; - } - [dataToHmac appendData:iv]; - [dataToHmac appendData:encryptedData]; - - if(hmacType == TSHMACSHA1Truncated10Bytes) { - *hmac = [Cryptography truncatedSHA1HMAC:dataToHmac withHMACKey:hmacKey truncation:10]; - } 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; - } - free(buffer); - return nil; - -} - - - -+(NSData*)decryptCBCMode:(NSData*)dataToDecrypt - key:(NSData*)key - IV:(NSData*)iv - version:(NSData*)version - HMACKey:(NSData*) hmacKey - HMACType:(TSMACType)hmacType - matchingHMAC:(NSData *)hmac -{ - - /* AES256 CBC encrypt then mac - - Returns nil if hmac invalid or decryption fails - */ - //verify hmac of version||encrypted data||iv - NSMutableData *dataToHmac = [NSMutableData data ]; - if(version != nil) { - [dataToHmac appendData:version]; - } - - [dataToHmac appendData:iv]; - [dataToHmac appendData:dataToDecrypt]; - - NSData* ourHmacData; - - if(hmacType == TSHMACSHA1Truncated10Bytes) { - ourHmacData = [Cryptography truncatedSHA1HMAC:dataToHmac withHMACKey:hmacKey truncation:10]; - } 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; - CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, - [key bytes], [key length], - [iv bytes], - [dataToDecrypt bytes], [dataToDecrypt length], - buffer, bufferSize, - &bytesDecrypted); - if (cryptStatus == kCCSuccess) { - return [NSData dataWithBytesNoCopy:buffer length:bytesDecrypted]; - } else{ - DDLogError(@"Failed CBC decryption"); - free(buffer); - } - - return nil; -} - -#pragma mark methods which use AES CBC -+(NSData*)decryptAppleMessagePayload:(NSData*)payload withSignalingKey:(NSString*)signalingKeyString{ - require(payload); - require(signalingKeyString); - - unsigned char version[1]; - unsigned char iv[16]; - NSUInteger ciphertext_length = ([payload length]-10-17)*sizeof(char); - unsigned char *ciphertext = (unsigned char*)malloc(ciphertext_length); - unsigned char mac[10]; - [payload getBytes:version range:NSMakeRange(0, 1)]; - [payload getBytes:iv range:NSMakeRange(1, 16)]; - [payload getBytes:ciphertext range:NSMakeRange(17, [payload length]-10-17)]; - [payload getBytes:mac range:NSMakeRange([payload length]-10, 10)]; - - NSData* signalingKey = [NSData dataFromBase64String:signalingKeyString]; - NSData* signalingKeyAESKeyMaterial = [signalingKey subdataWithRange:NSMakeRange(0, 32)]; - NSData* signalingKeyHMACKeyMaterial = [signalingKey subdataWithRange:NSMakeRange(32, 20)]; - return [Cryptography decryptCBCMode:[NSData dataWithBytesNoCopy:ciphertext - length:ciphertext_length - freeWhenDone:YES] - key:signalingKeyAESKeyMaterial - IV:[NSData dataWithBytes:iv length:16] - version:[NSData dataWithBytes:version length:1] - HMACKey:signalingKeyHMACKeyMaterial - HMACType:TSHMACSHA256Truncated10Bytes - matchingHMAC:[NSData dataWithBytes:mac length:10]]; - -} - -+ (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, 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, 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]; -} - -+ (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]; - - NSData* 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]; - - TSAttachmentStream *pointer = [[TSAttachmentStream alloc] initWithIdentifier:identifier data:attachment key:outKey contentType:contentType]; - - return [[TSAttachmentEncryptionResult alloc] initWithPointer:pointer body:encryptedAttachment]; -} - -@end diff --git a/Signal/src/textsecure/Util/NSData+Base64.h b/Signal/src/textsecure/Util/NSData+Base64.h deleted file mode 100644 index c3e88dd20..000000000 --- a/Signal/src/textsecure/Util/NSData+Base64.h +++ /dev/null @@ -1,10 +0,0 @@ -#import - -@interface NSData (Base64) - -+ (NSData*)dataFromBase64StringNoPadding:(NSString*)aString; -+ (NSData*)dataFromBase64String:(NSString*)aString; - -- (NSString*)base64EncodedString; - -@end diff --git a/Signal/src/textsecure/Util/NSData+Base64.m b/Signal/src/textsecure/Util/NSData+Base64.m deleted file mode 100644 index 76be4c066..000000000 --- a/Signal/src/textsecure/Util/NSData+Base64.m +++ /dev/null @@ -1,49 +0,0 @@ - -#import "NSData+Base64.h" - - -@implementation NSData (Base64) - -+ (NSData*)dataFromBase64StringNoPadding:(NSString*)aString{ - int padding = aString.length%4; - - NSMutableString *strResult = [aString mutableCopy]; - if (padding != 0) { - int charsToAdd = 4 - padding; - for (int i = 0; i < charsToAdd; i++) { - [strResult appendString:@"="]; - } - } - return [self dataFromBase64String:strResult]; -} - -// -// dataFromBase64String: -// -// Creates an NSData object containing the base64 decoded representation of -// the base64 string 'aString' -// -// Parameters: -// aString - the base64 string to decode -// -// returns the NSData representation of the base64 string -// - -+ (NSData *)dataFromBase64String:(NSString *)aString { - return [[NSData alloc] initWithBase64EncodedString:aString options:NSDataBase64DecodingIgnoreUnknownCharacters]; -} - -// -// base64EncodedString -// -// Creates an NSString object that contains the base 64 encoding of the -// receiver's data. Lines are broken at 64 characters long. -// -// returns an NSString being the base 64 representation of the -// receiver. -// -- (NSString *)base64EncodedString { - return [self base64EncodedStringWithOptions:0]; -} - -@end diff --git a/Signal/src/textsecure/Util/NSData+hexString.h b/Signal/src/textsecure/Util/NSData+hexString.h deleted file mode 100644 index b39fe3820..000000000 --- a/Signal/src/textsecure/Util/NSData+hexString.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// NSData+hexString.h -// TextSecureKit -// -// Created by Frederic Jacobs on 28/10/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import - -@interface NSData (hexString) - --(NSString *)hexadecimalString; - -@end diff --git a/Signal/src/textsecure/Util/NSData+hexString.m b/Signal/src/textsecure/Util/NSData+hexString.m deleted file mode 100644 index a8e743aec..000000000 --- a/Signal/src/textsecure/Util/NSData+hexString.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// NSData+hexString.m -// TextSecureKit -// -// Created by Frederic Jacobs on 28/10/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "NSData+hexString.h" - -@implementation NSData (hexString) - --(NSString *)hexadecimalString { - /* Returns hexadecimal string of NSData. Empty string if data is empty. */ - const unsigned char *dataBuffer = (const unsigned char *)[self bytes]; - if (!dataBuffer) - return [NSString string]; - - NSUInteger dataLength = [self length]; - NSMutableString *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)]; - - for (NSUInteger i = 0; i < dataLength; ++i) { - [hexString appendFormat:@"%02x", dataBuffer[i]]; - } - return [NSString stringWithString:hexString]; -} - -@end diff --git a/Signal/src/textsecure/Util/NSData+messagePadding.h b/Signal/src/textsecure/Util/NSData+messagePadding.h deleted file mode 100644 index 6f4fb01a3..000000000 --- a/Signal/src/textsecure/Util/NSData+messagePadding.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// NSData+messagePadding.h -// TextSecureKit -// -// Created by Frederic Jacobs on 15/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import - -@interface NSData (messagePadding) - -- (NSData*)removePadding; - -- (NSData*)paddedMessageBody; - -@end diff --git a/Signal/src/textsecure/Util/NSData+messagePadding.m b/Signal/src/textsecure/Util/NSData+messagePadding.m deleted file mode 100644 index b133d992a..000000000 --- a/Signal/src/textsecure/Util/NSData+messagePadding.m +++ /dev/null @@ -1,61 +0,0 @@ -// -// NSData+messagePadding.m -// TextSecureKit -// -// Created by Frederic Jacobs on 15/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "NSData+messagePadding.h" - -@implementation NSData (messagePadding) - -- (NSData*)removePadding{ - unsigned long paddingStart = self.length; - - Byte data[self.length]; - [self getBytes:data length:self.length]; - - for (long i = (long)self.length-1; i >= 0; i--) { - if (data[i] == (Byte)0x80) { - paddingStart = (unsigned long) i; - break; - } else if (data[i] != (Byte)0x00) { - DDLogWarn(@"Failed to remove padding, returning unstripped padding"); - return self; - } - } - - return [self subdataWithRange:NSMakeRange(0, paddingStart)]; -} - - -- (NSData*)paddedMessageBody { - // From https://github.com/WhisperSystems/TextSecure/blob/master/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/push/PushTransportDetails.java#L55 - // NOTE: This is dumb. We have our own padding scheme, but so does the cipher. - // The +1 -1 here is to make sure the Cipher has room to add one padding byte, - // otherwise it'll add a full 16 extra bytes. - - NSUInteger paddedMessageLength = [self paddedMessageLength:(self.length + 1)]-1; - NSMutableData *paddedMessage = [NSMutableData dataWithLength:paddedMessageLength]; - - Byte paddingByte = 0x80; - - [paddedMessage replaceBytesInRange:NSMakeRange(0, self.length) withBytes:[self bytes]]; - [paddedMessage replaceBytesInRange:NSMakeRange(self.length, 1) withBytes:&paddingByte]; - - return paddedMessage; -} - -- (NSUInteger)paddedMessageLength:(NSUInteger)messageLength { - NSUInteger messageLengthWithTerminator = messageLength + 1; - NSUInteger messagePartCount = messageLengthWithTerminator / 160; - - if (messageLengthWithTerminator % 160 != 0) { - messagePartCount++; - } - - return messagePartCount * 160; -} - -@end diff --git a/Signal/src/textsecure/Util/NSDate+millisecondTimeStamp.h b/Signal/src/textsecure/Util/NSDate+millisecondTimeStamp.h deleted file mode 100644 index 9f3032162..000000000 --- a/Signal/src/textsecure/Util/NSDate+millisecondTimeStamp.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// NSDate+millisecondTimeStamp.h -// Signal -// -// Created by Frederic Jacobs on 25/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import - -@interface NSDate (millisecondTimeStamp) -+ (uint64_t)ows_millisecondTimeStamp; -@end diff --git a/Signal/src/textsecure/Util/NSDate+millisecondTimeStamp.mm b/Signal/src/textsecure/Util/NSDate+millisecondTimeStamp.mm deleted file mode 100644 index a2b38aec9..000000000 --- a/Signal/src/textsecure/Util/NSDate+millisecondTimeStamp.mm +++ /dev/null @@ -1,19 +0,0 @@ -// -// NSDate+millisecondTimeStamp.m -// Signal -// -// Created by Frederic Jacobs on 25/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "NSDate+millisecondTimeStamp.h" -#import - -@implementation NSDate (millisecondTimeStamp) - -+ (uint64_t)ows_millisecondTimeStamp{ - uint64_t milliseconds = (uint64_t) (std::chrono::system_clock::now().time_since_epoch()/std::chrono::milliseconds(1)); - return milliseconds; -} - -@end diff --git a/Signal/src/textsecure/Util/NSURLSessionDataTask+StatusCode.h b/Signal/src/textsecure/Util/NSURLSessionDataTask+StatusCode.h deleted file mode 100644 index 5eeff97f3..000000000 --- a/Signal/src/textsecure/Util/NSURLSessionDataTask+StatusCode.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// NSURLSessionDataTask+StatusCode.h -// TextSecureKit -// -// Created by Frederic Jacobs on 04/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import - -@interface NSURLSessionTask (StatusCode) - -- (long)statusCode; - -@end diff --git a/Signal/src/textsecure/Util/NSURLSessionDataTask+StatusCode.m b/Signal/src/textsecure/Util/NSURLSessionDataTask+StatusCode.m deleted file mode 100644 index 82d4de438..000000000 --- a/Signal/src/textsecure/Util/NSURLSessionDataTask+StatusCode.m +++ /dev/null @@ -1,18 +0,0 @@ -// -// NSURLSessionDataTask+StatusCode.m -// TextSecureKit -// -// Created by Frederic Jacobs on 04/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "NSURLSessionDataTask+StatusCode.h" - -@implementation NSURLSessionTask (StatusCode) - -- (long)statusCode { - NSHTTPURLResponse *response = (NSHTTPURLResponse *)self.response; - return response.statusCode; -} - -@end diff --git a/Signal/src/textsecure/Util/TSAttachmentEncryptionResult.h b/Signal/src/textsecure/Util/TSAttachmentEncryptionResult.h deleted file mode 100644 index e2af91cb9..000000000 --- a/Signal/src/textsecure/Util/TSAttachmentEncryptionResult.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// TSAttachmentEncryptionResult.h -// Signal -// -// Created by Frederic Jacobs on 21/12/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import -#import "TSAttachmentStream.h" - -@interface TSAttachmentEncryptionResult : NSData - -@property (readwrite) TSAttachmentStream *pointer; -@property (readonly) NSData *body; - -- (instancetype)initWithPointer:(TSAttachmentStream*)pointer - body:(NSData*)cipherText; - -@end diff --git a/Signal/src/textsecure/Util/TSAttachmentEncryptionResult.m b/Signal/src/textsecure/Util/TSAttachmentEncryptionResult.m deleted file mode 100644 index 0e1535063..000000000 --- a/Signal/src/textsecure/Util/TSAttachmentEncryptionResult.m +++ /dev/null @@ -1,25 +0,0 @@ -// -// 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 diff --git a/Signal/src/textsecure/Util/UIImage+contentTypes.h b/Signal/src/textsecure/Util/UIImage+contentTypes.h deleted file mode 100644 index 61a330cc9..000000000 --- a/Signal/src/textsecure/Util/UIImage+contentTypes.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// UIImage+contentTypes.h -// Signal -// -// Created by Frederic Jacobs on 21/12/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import - -@interface UIImage (contentTypes) - -- (NSString*)contentType; -- (BOOL)isSupportedImageType; - -@end diff --git a/Signal/src/textsecure/Util/UIImage+contentTypes.m b/Signal/src/textsecure/Util/UIImage+contentTypes.m deleted file mode 100644 index 93feb6af9..000000000 --- a/Signal/src/textsecure/Util/UIImage+contentTypes.m +++ /dev/null @@ -1,38 +0,0 @@ -// -// 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 diff --git a/Signal/src/util/AppStoreRating.m b/Signal/src/util/AppStoreRating.m index e9316360e..fa38be07c 100644 --- a/Signal/src/util/AppStoreRating.m +++ b/Signal/src/util/AppStoreRating.m @@ -6,13 +6,12 @@ // Copyright (c) 2015 Open Whisper Systems. All rights reserved. // -#import "AppStoreRating.h" #import +#import "AppStoreRating.h" @implementation AppStoreRating -+ (void)setupRatingLibrary -{ ++ (void)setupRatingLibrary { iRate *rate = [iRate sharedInstance]; rate.appStoreID = 874139669; rate.daysUntilPrompt = 15; diff --git a/Signal/src/util/ArrayUtil.h b/Signal/src/util/ArrayUtil.h index 60f4ac4e0..237b8bc53 100644 --- a/Signal/src/util/ArrayUtil.h +++ b/Signal/src/util/ArrayUtil.h @@ -1,7 +1,7 @@ #import @interface NSArray (Util) --(NSData*)ows_toUint8Data; --(NSData*)ows_concatDatas; --(NSArray*)ows_concatArrays; +- (NSData *)ows_toUint8Data; +- (NSData *)ows_concatDatas; +- (NSArray *)ows_concatArrays; @end diff --git a/Signal/src/util/ArrayUtil.m b/Signal/src/util/ArrayUtil.m index e2ea8bac7..3a2b3ff9b 100644 --- a/Signal/src/util/ArrayUtil.m +++ b/Signal/src/util/ArrayUtil.m @@ -3,33 +3,33 @@ @implementation NSArray (Util) --(NSData*)ows_toUint8Data { +- (NSData *)ows_toUint8Data { NSUInteger n = self.count; uint8_t x[n]; for (NSUInteger i = 0; i < n; i++) { - x[i] = [(NSNumber*)self[i] unsignedCharValue]; + x[i] = [(NSNumber *)self[i] unsignedCharValue]; } return [NSData dataWithBytes:x length:n]; } --(NSData*)ows_concatDatas { +- (NSData *)ows_concatDatas { NSUInteger t = 0; for (id d in self) { - require([d isKindOfClass:NSData.class]); - t += [(NSData*)d length]; + ows_require([d isKindOfClass:NSData.class]); + t += [(NSData *)d length]; } - - NSMutableData* result = [NSMutableData dataWithLength:t]; - uint8_t* dst = [result mutableBytes]; - for (NSData* d in self) { + + NSMutableData *result = [NSMutableData dataWithLength:t]; + uint8_t *dst = [result mutableBytes]; + for (NSData *d in self) { memcpy(dst, [d bytes], d.length); dst += d.length; } return result; } --(NSArray*)ows_concatArrays { - NSMutableArray* r = [NSMutableArray array]; +- (NSArray *)ows_concatArrays { + NSMutableArray *r = [NSMutableArray array]; for (id e in self) { - require([e isKindOfClass:NSArray.class]); + ows_require([e isKindOfClass:NSArray.class]); [r addObjectsFromArray:e]; } return r; diff --git a/Signal/src/util/Conversions.h b/Signal/src/util/Conversions.h index 65c786beb..fa432632b 100644 --- a/Signal/src/util/Conversions.h +++ b/Signal/src/util/Conversions.h @@ -1,12 +1,12 @@ -#import #import +#import #import "Constraints.h" #import "CryptoTools.h" @interface NSData (Conversions) --(uint16_t) bigEndianUInt16At:(NSUInteger)offset; --(uint32_t) bigEndianUInt32At:(NSUInteger)offset; -+(NSData*) dataWithBigEndianBytesOfUInt16:(uint16_t)value; -+(NSData*) dataWithBigEndianBytesOfUInt32:(uint32_t)value; -+(NSData*) switchEndiannessOfData:(NSData*)data; +- (uint16_t)bigEndianUInt16At:(NSUInteger)offset; +- (uint32_t)bigEndianUInt32At:(NSUInteger)offset; ++ (NSData *)dataWithBigEndianBytesOfUInt16:(uint16_t)value; ++ (NSData *)dataWithBigEndianBytesOfUInt32:(uint32_t)value; ++ (NSData *)switchEndiannessOfData:(NSData *)data; @end diff --git a/Signal/src/util/Conversions.m b/Signal/src/util/Conversions.m index 96fbdcc4e..22594d04a 100644 --- a/Signal/src/util/Conversions.m +++ b/Signal/src/util/Conversions.m @@ -3,26 +3,23 @@ @implementation NSData (Conversions) --(uint16_t) bigEndianUInt16At:(NSUInteger)offset { - require(offset <= self.length-sizeof(uint16_t)); - return (uint16_t)[self uint8At:1+offset] - | (uint16_t)((uint16_t)[self uint8At:0+offset] << 8); +- (uint16_t)bigEndianUInt16At:(NSUInteger)offset { + ows_require(offset <= self.length - sizeof(uint16_t)); + return (uint16_t)[self uint8At:1 + offset] | (uint16_t)((uint16_t)[self uint8At:0 + offset] << 8); } --(uint32_t) bigEndianUInt32At:(NSUInteger)offset { - require(offset <= self.length-sizeof(uint32_t)); - return ((uint32_t)[self uint8At:3+offset] << 0) - | ((uint32_t)[self uint8At:2+offset] << 8) - | ((uint32_t)[self uint8At:1+offset] << 16) - | ((uint32_t)[self uint8At:0+offset] << 24); +- (uint32_t)bigEndianUInt32At:(NSUInteger)offset { + ows_require(offset <= self.length - sizeof(uint32_t)); + return ((uint32_t)[self uint8At:3 + offset] << 0) | ((uint32_t)[self uint8At:2 + offset] << 8) | + ((uint32_t)[self uint8At:1 + offset] << 16) | ((uint32_t)[self uint8At:0 + offset] << 24); } -+(NSData*) dataWithBigEndianBytesOfUInt16:(uint16_t)value { ++ (NSData *)dataWithBigEndianBytesOfUInt16:(uint16_t)value { uint8_t d[sizeof(uint16_t)]; d[1] = (uint8_t)((value >> 0) & 0xFF); d[0] = (uint8_t)((value >> 8) & 0xFF); return [NSData dataWithBytes:d length:sizeof(uint16_t)]; } -+(NSData*) dataWithBigEndianBytesOfUInt32:(uint32_t)value { ++ (NSData *)dataWithBigEndianBytesOfUInt32:(uint32_t)value { uint8_t d[sizeof(uint32_t)]; d[3] = (uint8_t)((value >> 0) & 0xFF); d[2] = (uint8_t)((value >> 8) & 0xFF); @@ -30,11 +27,11 @@ d[0] = (uint8_t)((value >> 24) & 0xFF); return [NSData dataWithBytes:d length:sizeof(uint32_t)]; } -+(NSData*) switchEndiannessOfData:(NSData*)data{ - const void* bytes = [data bytes]; - NSMutableData* switchedEndianData = [NSMutableData new]; - for (NSUInteger i = data.length; i > 0; --i){ - uint8_t byte = *(((uint8_t*)(bytes))+((i-1)*sizeof(uint8_t))); ++ (NSData *)switchEndiannessOfData:(NSData *)data { + const void *bytes = [data bytes]; + NSMutableData *switchedEndianData = [NSMutableData new]; + for (NSUInteger i = data.length; i > 0; --i) { + uint8_t byte = *(((uint8_t *)(bytes)) + ((i - 1) * sizeof(uint8_t))); [switchedEndianData appendData:[NSData dataWithBytes:&byte length:sizeof(byte)]]; } return switchedEndianData; diff --git a/Signal/src/util/Crc32.h b/Signal/src/util/Crc32.h index cecc6f6e3..25367433b 100644 --- a/Signal/src/util/Crc32.h +++ b/Signal/src/util/Crc32.h @@ -2,6 +2,6 @@ @interface NSData (CRC) --(uint32_t) crc32; +- (uint32_t)crc32; @end diff --git a/Signal/src/util/Crc32.m b/Signal/src/util/Crc32.m index 76b66d15c..38ec4e251 100644 --- a/Signal/src/util/Crc32.m +++ b/Signal/src/util/Crc32.m @@ -1,7 +1,7 @@ #import "Crc32.h" #define DEFAULT_POLYNOMIAL 0xEDB88320L -#define DEFAULT_SEED 0xFFFFFFFFL +#define DEFAULT_SEED 0xFFFFFFFFL void generateCRC32Table(uint32_t *pTable, uint32_t poly); @@ -10,7 +10,7 @@ void generateCRC32Table(uint32_t *pTable, uint32_t poly); void generateCRC32Table(uint32_t *pTable, uint32_t poly) { for (uint32_t i = 0; i <= 255; i++) { uint32_t crc = i; - + for (uint32_t j = 8; j > 0; j--) { if ((crc & 1) == 1) crc = (crc >> 1) ^ poly; @@ -21,22 +21,22 @@ void generateCRC32Table(uint32_t *pTable, uint32_t poly) { } } --(uint32_t)crc32 { +- (uint32_t)crc32 { return [self crc32WithSeed:DEFAULT_SEED usingPolynomial:DEFAULT_POLYNOMIAL]; } --(uint32_t)crc32WithSeed:(uint32_t)seed usingPolynomial:(uint32_t)poly { +- (uint32_t)crc32WithSeed:(uint32_t)seed usingPolynomial:(uint32_t)poly { uint32_t *pTable = malloc(sizeof(uint32_t) * 256); generateCRC32Table(pTable, poly); - - uint32_t crc = seed; - uint8_t *pBytes = (uint8_t *)[self bytes]; + + uint32_t crc = seed; + uint8_t *pBytes = (uint8_t *)[self bytes]; NSUInteger length = self.length; - + while (length--) { - crc = (crc>>8) ^ pTable[(crc & 0xFF) ^ *pBytes++]; + crc = (crc >> 8) ^ pTable[(crc & 0xFF) ^ *pBytes++]; } - + free(pTable); return crc ^ 0xFFFFFFFFL; } diff --git a/Signal/src/util/DJWActionSheet+OWS.h b/Signal/src/util/DJWActionSheet+OWS.h index 91eed0622..ad03db5b6 100644 --- a/Signal/src/util/DJWActionSheet+OWS.h +++ b/Signal/src/util/DJWActionSheet+OWS.h @@ -11,4 +11,3 @@ @interface DJWActionSheet (OWS) + (UIColor *)DJWActionSheetButtonBackgroundColorForState:(UIControlState)controlState; @end - diff --git a/Signal/src/util/DJWActionSheet+OWS.m b/Signal/src/util/DJWActionSheet+OWS.m index 96fa731da..533089f6c 100644 --- a/Signal/src/util/DJWActionSheet+OWS.m +++ b/Signal/src/util/DJWActionSheet+OWS.m @@ -11,8 +11,7 @@ @implementation DJWActionSheet (OWS) -+ (UIColor *)DJWActionSheetButtonBackgroundColorForState:(UIControlState)controlState -{ ++ (UIColor *)DJWActionSheetButtonBackgroundColorForState:(UIControlState)controlState { switch (controlState) { case UIControlStateNormal: return [UIColor whiteColor]; @@ -20,7 +19,7 @@ case UIControlStateHighlighted: return [UIColor ows_materialBlueColor]; break; - + default: return [UIColor whiteColor]; break; diff --git a/Signal/src/util/DataUtil.h b/Signal/src/util/DataUtil.h index b0e0ca3be..bfcc7af8e 100644 --- a/Signal/src/util/DataUtil.h +++ b/Signal/src/util/DataUtil.h @@ -2,76 +2,76 @@ @interface NSData (Util) --(NSString*) encodedAsHexString; +- (NSString *)encodedAsHexString; --(const void*) bytesNotNull; +- (const void *)bytesNotNull; -+(NSData*) dataWithLength:(NSUInteger)length; ++ (NSData *)dataWithLength:(NSUInteger)length; -+(NSData*) dataWithSingleByte:(uint8_t)value; ++ (NSData *)dataWithSingleByte:(uint8_t)value; /// Decodes the data as a utf-8 string. --(NSString*) decodedAsUtf8; +- (NSString *)decodedAsUtf8; /// Decodes the data as an ascii string. /// Throws when the data contains non-ascii character data (bytes larger than 127). --(NSString*) decodedAsAscii; +- (NSString *)decodedAsAscii; /// Decodes the data as an ascii string. /// Replaces any bad or non-printable characters with dots. --(NSString*) decodedAsAsciiReplacingErrorsWithDots; +- (NSString *)decodedAsAsciiReplacingErrorsWithDots; /// Finds the first index where the given sub data is present. /// Returns nil if there is no such index. --(NSNumber*) tryFindIndexOf:(NSData*)subData; +- (NSNumber *)tryFindIndexOf:(NSData *)subData; --(NSData*) skip:(NSUInteger)offset; +- (NSData *)skip:(NSUInteger)offset; --(NSData*) take:(NSUInteger)takeCount; +- (NSData *)take:(NSUInteger)takeCount; --(NSData*) skipLast:(NSUInteger)skipLastCount; +- (NSData *)skipLast:(NSUInteger)skipLastCount; --(NSData*) takeLast:(NSUInteger)takeLastCount; +- (NSData *)takeLast:(NSUInteger)takeLastCount; /// Returns an NSData referencing a subrange of another NSData. /// Modifying the original NSData will modify the result. /// If the original is dealloced before the result, bad things happen to you. --(NSData*) subdataVolatileWithRange:(NSRange)range; +- (NSData *)subdataVolatileWithRange:(NSRange)range; /// Returns an NSData referencing the end of another NSData. /// Modifying the original NSData will modify the result. /// If the original is dealloced before the result, bad things happen to you. --(NSData*) skipVolatile:(NSUInteger)offset; +- (NSData *)skipVolatile:(NSUInteger)offset; /// Returns an NSData referencing the start of another NSData. /// Modifying the original NSData will modify the result. /// If the original is dealloced before the result, bad things happen to you. --(NSData*) takeVolatile:(NSUInteger)takeCount; +- (NSData *)takeVolatile:(NSUInteger)takeCount; /// Returns an NSData referencing the start of another NSData. /// Modifying the original NSData will modify the result. /// If the original is dealloced before the result, bad things happen to you. --(NSData*) skipLastVolatile:(NSUInteger)skipLastCount; +- (NSData *)skipLastVolatile:(NSUInteger)skipLastCount; /// Returns an NSData referencing the end of another NSData. /// Modifying the original NSData will modify the result. /// If the original is dealloced before the result, bad things happen to you. --(NSData*) takeLastVolatile:(NSUInteger)takeLastCount; +- (NSData *)takeLastVolatile:(NSUInteger)takeLastCount; --(uint8_t) uint8At:(NSUInteger)offset; +- (uint8_t)uint8At:(NSUInteger)offset; --(uint8_t) highUint4AtByteOffset:(NSUInteger)offset; +- (uint8_t)highUint4AtByteOffset:(NSUInteger)offset; --(uint8_t) lowUint4AtByteOffset:(NSUInteger)offset; +- (uint8_t)lowUint4AtByteOffset:(NSUInteger)offset; --(NSString*) encodedAsBase64; +- (NSString *)encodedAsBase64; @end @interface NSMutableData (Util) --(void) replaceBytesStartingAt:(NSUInteger)offset withData:(NSData*)data; +- (void)replaceBytesStartingAt:(NSUInteger)offset withData:(NSData *)data; --(void) setUint8At:(NSUInteger)offset to:(uint8_t)newValue; +- (void)setUint8At:(NSUInteger)offset to:(uint8_t)newValue; @end diff --git a/Signal/src/util/DataUtil.m b/Signal/src/util/DataUtil.m index f1d8741f7..10f1d8ce5 100644 --- a/Signal/src/util/DataUtil.m +++ b/Signal/src/util/DataUtil.m @@ -1,8 +1,8 @@ -#import "DataUtil.h" #import "Constraints.h" +#import "DataUtil.h" @implementation NSData (Util) --(const void*) bytesNotNull { +- (const void *)bytesNotNull { // note: this storage location is static, not auto, so its lifetime does not end // (also, by virtue of being const, there are no threading/entrancy issues) static const int SafeNonNullPointerToStaticStorageLocation[1]; @@ -10,182 +10,190 @@ if (self.length == 0) { return SafeNonNullPointerToStaticStorageLocation; } else { - require([self bytes] != nil); + ows_require([self bytes] != nil); return [self bytes]; } } -+(NSData*) dataWithLength:(NSUInteger)length { ++ (NSData *)dataWithLength:(NSUInteger)length { return [NSMutableData dataWithLength:length]; } -+(NSData*) dataWithSingleByte:(uint8_t)value{ ++ (NSData *)dataWithSingleByte:(uint8_t)value { return [NSData dataWithBytes:&value length:sizeof(value)]; } --(NSNumber*) tryFindIndexOf:(NSData*)subData { - require(subData != nil); - if (subData.length > self.length) return nil; - +- (NSNumber *)tryFindIndexOf:(NSData *)subData { + ows_require(subData != nil); + if (subData.length > self.length) + return nil; + NSUInteger subDataLength = subData.length; - NSUInteger excessLength = self.length - subDataLength; - - const uint8_t* selfBytes = [self bytes]; - const uint8_t* subDataBytes = [subData bytes]; + NSUInteger excessLength = self.length - subDataLength; + + const uint8_t *selfBytes = [self bytes]; + const uint8_t *subDataBytes = [subData bytes]; for (NSUInteger i = 0; i <= excessLength; i++) { - if (memcmp(selfBytes+i, subDataBytes, subDataLength) == 0) { + if (memcmp(selfBytes + i, subDataBytes, subDataLength) == 0) { return @(i); } } return nil; } --(NSString*) encodedAsHexString { - if (![self bytes]) return @""; - - NSMutableString* result = [NSMutableString string]; +- (NSString *)encodedAsHexString { + if (![self bytes]) + return @""; + + NSMutableString *result = [NSMutableString string]; for (NSUInteger i = 0; i < self.length; ++i) [result appendString:[NSString stringWithFormat:@"%02x", [self uint8At:i]]]; - + return result; } --(NSString*) decodedAsUtf8 { +- (NSString *)decodedAsUtf8 { // workaround for empty data having nil bytes - if (self.length == 0) return @""; - + if (self.length == 0) + return @""; + [NSString stringWithUTF8String:[self bytes]]; - NSString* result = [[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding]; + NSString *result = [[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding]; checkOperationDescribe(result != nil, @"Invalid UTF8 data."); return result; } --(NSString*) decodedAsAscii { +- (NSString *)decodedAsAscii { // workaround for empty data having nil bytes - if (self.length == 0) return @""; + if (self.length == 0) + return @""; // workaround for initWithData not enforcing the fact that NSASCIIStringEncoding means strict 7-bit for (NSUInteger i = 0; i < self.length; i++) { checkOperationDescribe(([self uint8At:i] & 0x80) == 0, @"Invalid ascii data."); } - - NSString* result = [[NSString alloc] initWithData:self encoding:NSASCIIStringEncoding]; + + NSString *result = [[NSString alloc] initWithData:self encoding:NSASCIIStringEncoding]; checkOperationDescribe(result != nil, @"Invalid ascii data."); return result; } --(NSString*) decodedAsAsciiReplacingErrorsWithDots { +- (NSString *)decodedAsAsciiReplacingErrorsWithDots { const int MinPrintableChar = ' '; const int MaxPrintableChar = '~'; - - NSMutableData* d = [NSMutableData dataWithLength:self.length]; + + NSMutableData *d = [NSMutableData dataWithLength:self.length]; for (NSUInteger i = 0; i < self.length; i++) { uint8_t v = [self uint8At:i]; - if (v < MinPrintableChar || v > MaxPrintableChar) v = '.'; + if (v < MinPrintableChar || v > MaxPrintableChar) + v = '.'; [d setUint8At:i to:v]; } return [d decodedAsAscii]; } --(NSData*) skip:(NSUInteger)offset { - require(offset <= self.length); +- (NSData *)skip:(NSUInteger)offset { + ows_require(offset <= self.length); return [self subdataWithRange:NSMakeRange(offset, self.length - offset)]; } --(NSData*) take:(NSUInteger)takeCount { - require(takeCount <= self.length); +- (NSData *)take:(NSUInteger)takeCount { + ows_require(takeCount <= self.length); return [self subdataWithRange:NSMakeRange(0, takeCount)]; } --(NSData*) skipLast:(NSUInteger)skipLastCount { - require(skipLastCount <= self.length); +- (NSData *)skipLast:(NSUInteger)skipLastCount { + ows_require(skipLastCount <= self.length); return [self subdataWithRange:NSMakeRange(0, self.length - skipLastCount)]; } --(NSData*) takeLast:(NSUInteger)takeLastCount { - require(takeLastCount <= self.length); +- (NSData *)takeLast:(NSUInteger)takeLastCount { + ows_require(takeLastCount <= self.length); return [self subdataWithRange:NSMakeRange(self.length - takeLastCount, takeLastCount)]; } --(NSData*) subdataVolatileWithRange:(NSRange)range { +- (NSData *)subdataVolatileWithRange:(NSRange)range { NSUInteger length = self.length; - require(range.location <= length); - require(range.length <= length); - require(range.location + range.length <= length); - - return [NSData dataWithBytesNoCopy:(uint8_t*)[self bytes] + range.location length:range.length freeWhenDone:NO]; + ows_require(range.location <= length); + ows_require(range.length <= length); + ows_require(range.location + range.length <= length); + + return [NSData dataWithBytesNoCopy:(uint8_t *)[self bytes] + range.location length:range.length freeWhenDone:NO]; } --(NSData*) skipVolatile:(NSUInteger)offset { - require(offset <= self.length); +- (NSData *)skipVolatile:(NSUInteger)offset { + ows_require(offset <= self.length); return [self subdataVolatileWithRange:NSMakeRange(offset, self.length - offset)]; } --(NSData*) takeVolatile:(NSUInteger)takeCount { - require(takeCount <= self.length); +- (NSData *)takeVolatile:(NSUInteger)takeCount { + ows_require(takeCount <= self.length); return [self subdataVolatileWithRange:NSMakeRange(0, takeCount)]; } --(NSData*) skipLastVolatile:(NSUInteger)skipLastCount { - require(skipLastCount <= self.length); +- (NSData *)skipLastVolatile:(NSUInteger)skipLastCount { + ows_require(skipLastCount <= self.length); return [self subdataVolatileWithRange:NSMakeRange(0, self.length - skipLastCount)]; } --(NSData*) takeLastVolatile:(NSUInteger)takeLastCount { - require(takeLastCount <= self.length); +- (NSData *)takeLastVolatile:(NSUInteger)takeLastCount { + ows_require(takeLastCount <= self.length); return [self subdataVolatileWithRange:NSMakeRange(self.length - takeLastCount, takeLastCount)]; } --(uint8_t) highUint4AtByteOffset:(NSUInteger)offset { +- (uint8_t)highUint4AtByteOffset:(NSUInteger)offset { return [self uint8At:offset] >> 4; } --(uint8_t) lowUint4AtByteOffset:(NSUInteger)offset { +- (uint8_t)lowUint4AtByteOffset:(NSUInteger)offset { return [self uint8At:offset] & 0xF; } --(uint8_t) uint8At:(NSUInteger)offset { - require(offset < self.length); - return ((const uint8_t*)[self bytes])[offset]; +- (uint8_t)uint8At:(NSUInteger)offset { + ows_require(offset < self.length); + return ((const uint8_t *)[self bytes])[offset]; } --(const uint8_t*) constPtrToUint8At:(NSUInteger)offset { - return ((uint8_t*)[self bytes]) + offset; +- (const uint8_t *)constPtrToUint8At:(NSUInteger)offset { + return ((uint8_t *)[self bytes]) + offset; } --(NSString*) encodedAsBase64 { +- (NSString *)encodedAsBase64 { const NSUInteger BitsPerBase64Word = 6; - const NSUInteger BitsPerByte = 8; - const uint8_t Base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + const NSUInteger BitsPerByte = 8; + const uint8_t Base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - NSUInteger byteCount = self.length; - NSUInteger bitCount = byteCount*BitsPerByte; + NSUInteger byteCount = self.length; + NSUInteger bitCount = byteCount * BitsPerByte; NSUInteger base64WordCount = bitCount / BitsPerBase64Word; - if (base64WordCount * BitsPerBase64Word < bitCount) base64WordCount += 1; - + if (base64WordCount * BitsPerBase64Word < bitCount) + base64WordCount += 1; + // base 256 to to base 2 bool bits[bitCount]; for (NSUInteger i = 0; i < byteCount; i++) { for (NSUInteger j = 0; j < BitsPerByte; j++) { - bits[i*BitsPerByte + BitsPerByte - 1 - j] = (([self uint8At:i] >> j) & 1) != 0; + bits[i * BitsPerByte + BitsPerByte - 1 - j] = (([self uint8At:i] >> j) & 1) != 0; } } - + // base 2 to base 64 uint8_t base64Words[base64WordCount]; for (NSUInteger i = 0; i < base64WordCount; i++) { base64Words[i] = 0; for (NSUInteger j = 0; j < BitsPerBase64Word; j++) { - NSUInteger offset = i*BitsPerBase64Word + BitsPerBase64Word - 1 - j; - if (offset >= bitCount) continue; // default to 0 - if (bits[offset]) base64Words[i] |= 1 << j; + NSUInteger offset = i * BitsPerBase64Word + BitsPerBase64Word - 1 - j; + if (offset >= bitCount) + continue; // default to 0 + if (bits[offset]) + base64Words[i] |= 1 << j; } } - + // base 64 to ASCII data - NSUInteger paddingCount = bitCount % 3; - NSMutableData* asciiData = [NSMutableData dataWithLength:base64WordCount+paddingCount]; + NSUInteger paddingCount = bitCount % 3; + NSMutableData *asciiData = [NSMutableData dataWithLength:base64WordCount + paddingCount]; for (NSUInteger i = 0; i < base64WordCount; i++) { [asciiData setUint8At:i to:Base64Chars[base64Words[i]]]; } for (NSUInteger i = 0; i < paddingCount; i++) { - [asciiData setUint8At:i+base64WordCount to:'=']; + [asciiData setUint8At:i + base64WordCount to:'=']; } - + return [asciiData decodedAsAscii]; } @end @implementation NSMutableData (Util) --(void) setUint8At:(NSUInteger)offset to:(uint8_t)newValue { - require(offset < self.length); - ((uint8_t*)[self mutableBytes])[offset] = newValue; +- (void)setUint8At:(NSUInteger)offset to:(uint8_t)newValue { + ows_require(offset < self.length); + ((uint8_t *)[self mutableBytes])[offset] = newValue; } --(void) replaceBytesStartingAt:(NSUInteger)offset withData:(NSData*)data { - require(data != nil); - require(offset + data.length <= self.length); +- (void)replaceBytesStartingAt:(NSUInteger)offset withData:(NSData *)data { + ows_require(data != nil); + ows_require(offset + data.length <= self.length); [self replaceBytesInRange:NSMakeRange(offset, data.length) withBytes:[data bytes]]; } @end diff --git a/Signal/src/util/DateUtil.m b/Signal/src/util/DateUtil.m index f4f302295..b7bb2156a 100644 --- a/Signal/src/util/DateUtil.m +++ b/Signal/src/util/DateUtil.m @@ -1,7 +1,7 @@ #import "DateUtil.h" -#define ONE_DAY_TIME_INTERVAL (double)60*60*24 -#define ONE_WEEK_TIME_INTERVAL (double)60*60*24*7 +#define ONE_DAY_TIME_INTERVAL (double)60 * 60 * 24 +#define ONE_WEEK_TIME_INTERVAL (double)60 * 60 * 24 * 7 static NSString *const DATE_FORMAT_WEEKDAY = @"EEEE"; @@ -38,16 +38,16 @@ static NSString *const DATE_FORMAT_WEEKDAY = @"EEEE"; return [[NSDate date] timeIntervalSinceDate:date] > ONE_WEEK_TIME_INTERVAL; } -+ (BOOL)date:(NSDate *)date isEqualToDateIgnoringTime:(NSDate *)anotherDate{ - static const unsigned componentFlags = (NSCalendarUnitYear| NSCalendarUnitMonth | NSCalendarUnitDay); ++ (BOOL)date:(NSDate *)date isEqualToDateIgnoringTime:(NSDate *)anotherDate { + static const unsigned componentFlags = (NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay); NSDateComponents *components1 = [[NSCalendar autoupdatingCurrentCalendar] components:componentFlags fromDate:date]; - NSDateComponents *components2 = [[NSCalendar autoupdatingCurrentCalendar] components:componentFlags fromDate:anotherDate]; - return ((components1.year == components2.year) && - (components1.month == components2.month) && + NSDateComponents *components2 = + [[NSCalendar autoupdatingCurrentCalendar] components:componentFlags fromDate:anotherDate]; + return ((components1.year == components2.year) && (components1.month == components2.month) && (components1.day == components2.day)); } -+ (BOOL)dateIsToday:(NSDate *)date{ ++ (BOOL)dateIsToday:(NSDate *)date { return [self date:[NSDate date] isEqualToDateIgnoringTime:date]; } diff --git a/Signal/src/util/DictionaryUtil.h b/Signal/src/util/DictionaryUtil.h index c23bfd058..e0ed142ef 100644 --- a/Signal/src/util/DictionaryUtil.h +++ b/Signal/src/util/DictionaryUtil.h @@ -2,6 +2,6 @@ @interface NSDictionary (Util) --(NSString*) encodedAsJson; +- (NSString *)encodedAsJson; @end diff --git a/Signal/src/util/DictionaryUtil.m b/Signal/src/util/DictionaryUtil.m index f46d9c841..5dd29ee84 100644 --- a/Signal/src/util/DictionaryUtil.m +++ b/Signal/src/util/DictionaryUtil.m @@ -1,14 +1,12 @@ +#import "Constraints.h" #import "DataUtil.h" #import "DictionaryUtil.h" -#import "Constraints.h" @implementation NSDictionary (Util) --(NSString*) encodedAsJson { - NSError* jsonSerializeError = nil; - NSData* data = [NSJSONSerialization dataWithJSONObject:self - options:0 - error:&jsonSerializeError]; +- (NSString *)encodedAsJson { + NSError *jsonSerializeError = nil; + NSData *data = [NSJSONSerialization dataWithJSONObject:self options:0 error:&jsonSerializeError]; checkOperation(jsonSerializeError == nil); return [data decodedAsUtf8]; } diff --git a/Signal/src/util/FunctionalUtil.h b/Signal/src/util/FunctionalUtil.h index dacb91864..cb22bd78c 100644 --- a/Signal/src/util/FunctionalUtil.h +++ b/Signal/src/util/FunctionalUtil.h @@ -3,30 +3,30 @@ @interface NSArray (FunctionalUtil) /// Returns true when any of the items in this array match the given predicate. --(bool) any:(int (^)(id item))predicate; +- (bool)any:(int (^)(id item))predicate; /// Returns true when all of the items in this array match the given predicate. --(bool) all:(int (^)(id item))predicate; +- (bool)all:(int (^)(id item))predicate; /// Returns the first item in this array that matches the given predicate, or else returns nil if none match it. --(id) firstMatchingElseNil:(int (^)(id item))predicate; +- (id)firstMatchingElseNil:(int (^)(id item))predicate; /// Returns an array of all the results of passing items from this array through the given projection function. --(NSArray*) map:(id (^)(id item))projection; +- (NSArray *)map:(id (^)(id item))projection; /// Returns an array of all the results of passing items from this array through the given projection function. --(NSArray*) filter:(int (^)(id item))predicate; +- (NSArray *)filter:(int (^)(id item))predicate; /// Returns the sum of the doubles in this array of doubles. --(double) sumDouble; +- (double)sumDouble; /// Returns the sum of the unsigned integers in this array of unsigned integers. --(NSUInteger) sumNSUInteger; +- (NSUInteger)sumNSUInteger; /// Returns the sum of the integers in this array of integers. --(NSInteger) sumNSInteger; +- (NSInteger)sumNSInteger; --(NSDictionary *)keyedBy:(id(^)(id))keySelector; --(NSDictionary *)groupBy:(id(^)(id value))keySelector; +- (NSDictionary *)keyedBy:(id (^)(id))keySelector; +- (NSDictionary *)groupBy:(id (^)(id value))keySelector; @end diff --git a/Signal/src/util/FunctionalUtil.m b/Signal/src/util/FunctionalUtil.m index ad29c2d44..b6b5e525e 100644 --- a/Signal/src/util/FunctionalUtil.m +++ b/Signal/src/util/FunctionalUtil.m @@ -1,9 +1,9 @@ -#import "FunctionalUtil.h" #import "Constraints.h" +#import "FunctionalUtil.h" @implementation NSArray (FunctionalUtil) --(bool) any:(int (^)(id item))predicate { - require(predicate != nil); +- (bool)any:(int (^)(id item))predicate { + ows_require(predicate != nil); for (id e in self) { if (predicate(e)) { return true; @@ -11,8 +11,8 @@ } return false; } --(bool) all:(int (^)(id item))predicate { - require(predicate != nil); +- (bool)all:(int (^)(id item))predicate { + ows_require(predicate != nil); for (id e in self) { if (!predicate(e)) { return false; @@ -20,8 +20,8 @@ } return true; } --(id) firstMatchingElseNil:(int (^)(id item))predicate { - require(predicate != nil); +- (id)firstMatchingElseNil:(int (^)(id item))predicate { + ows_require(predicate != nil); for (id e in self) { if (predicate(e)) { return e; @@ -29,19 +29,19 @@ } return nil; } --(NSArray*) map:(id (^)(id item))projection { - require(projection != nil); - - NSMutableArray* r = [NSMutableArray arrayWithCapacity:self.count]; +- (NSArray *)map:(id (^)(id item))projection { + ows_require(projection != nil); + + NSMutableArray *r = [NSMutableArray arrayWithCapacity:self.count]; for (id e in self) { [r addObject:projection(e)]; } return r; } --(NSArray*) filter:(int (^)(id item))predicate { - require(predicate != nil); - - NSMutableArray* r = [NSMutableArray array]; +- (NSArray *)filter:(int (^)(id item))predicate { + ows_require(predicate != nil); + + NSMutableArray *r = [NSMutableArray array]; for (id e in self) { if (predicate(e)) { [r addObject:e]; @@ -49,50 +49,50 @@ } return r; } --(double) sumDouble { +- (double)sumDouble { double s = 0.0; - for (NSNumber* e in self) { + for (NSNumber *e in self) { s += [e doubleValue]; } return s; } --(NSUInteger) sumNSUInteger { +- (NSUInteger)sumNSUInteger { NSUInteger s = 0; - for (NSNumber* e in self) { + for (NSNumber *e in self) { s += [e unsignedIntegerValue]; } return s; } --(NSInteger) sumNSInteger { +- (NSInteger)sumNSInteger { NSInteger s = 0; - for (NSNumber* e in self) { + for (NSNumber *e in self) { s += [e integerValue]; } return s; } --(NSDictionary *)keyedBy:(id(^)(id value))keySelector { - require(keySelector != nil); +- (NSDictionary *)keyedBy:(id (^)(id value))keySelector { + ows_require(keySelector != nil); NSMutableDictionary *result = [NSMutableDictionary dictionary]; for (id value in self) { result[keySelector(value)] = value; } - checkOperation(result.count == self.count); + ows_require(result.count == self.count); return result; } --(NSDictionary *)groupBy:(id(^)(id value))keySelector { - require(keySelector != nil); +- (NSDictionary *)groupBy:(id (^)(id value))keySelector { + ows_require(keySelector != nil); NSMutableDictionary *result = [NSMutableDictionary dictionary]; for (id item in self) { id key = keySelector(item); - - NSMutableArray* group = result[key]; + + NSMutableArray *group = result[key]; if (group == nil) { - group = [NSMutableArray array]; + group = [NSMutableArray array]; result[key] = group; } [group addObject:item]; diff --git a/Signal/src/util/FutureUtil.h b/Signal/src/util/FutureUtil.h index a90822143..48ee1662e 100644 --- a/Signal/src/util/FutureUtil.h +++ b/Signal/src/util/FutureUtil.h @@ -4,30 +4,32 @@ @interface TOCCancelToken (FutureUtil) --(void) whenCancelledTerminate:(id)terminable; +- (void)whenCancelledTerminate:(id)terminable; @end @interface TOCFuture (FutureUtil) /*! - * Wraps an asynchronous operation in a try-catch block, so it returns a failed future instead of propagating an exception. + * Wraps an asynchronous operation in a try-catch block, so it returns a failed future instead of propagating an + * exception. */ -+(TOCUntilOperation) operationTry:(TOCUntilOperation)operation; ++ (TOCUntilOperation)operationTry:(TOCUntilOperation)operation; /*! * Returns a future that completes after the receiving future completes, but replaces its result if it didn't fail. */ --(TOCFuture*) thenValue:(id)value; +- (TOCFuture *)thenValue:(id)value; /*! * A variant of `-finally` that wraps a try-catch statement around the continuation. * * @discussion Registers a continuation to run when the receiving future completes with a result or fails. * Exposes the result of the continuation as a future. - * If the continuation throwns an exception, it is caught and the returned future will fail with the caught exception as its failure. + * If the continuation throwns an exception, it is caught and the returned future will fail with the caught exception as + * its failure. */ --(TOCFuture*) finallyTry:(TOCFutureFinallyContinuation)callback; +- (TOCFuture *)finallyTry:(TOCFutureFinallyContinuation)callback; /*! * A variant of `-then` that wraps a try-catch statement around the continuation. @@ -35,24 +37,27 @@ * @discussion Registers a continuation to run when the receiving future completes with a result. * Exposes the result of the continuation as a future. * If the receiving future fails, the returned future is given the same failure and the continuation is not run. - * If the continuation throwns an exception, it is caught and the returned future will fail with the caught exception as its failure. + * If the continuation throwns an exception, it is caught and the returned future will fail with the caught exception as + * its failure. */ --(TOCFuture*) thenTry:(TOCFutureThenContinuation) projection; +- (TOCFuture *)thenTry:(TOCFutureThenContinuation)projection; /*! * A variant of `-catch` that wraps a try-catch statement around the continuation. * * @discussion Registers a continuation to run when the receiving future fails. * Exposes the result of the continuation as a future. - * If the receiving future completes with a result, the returned future is given the same result and the continuation is not run. - * If the continuation throwns an exception, it is caught and the returned future will fail with the caught exception as its failure. + * If the receiving future completes with a result, the returned future is given the same result and the continuation is + * not run. + * If the continuation throwns an exception, it is caught and the returned future will fail with the caught exception as + * its failure. */ --(TOCFuture*) catchTry:(TOCFutureCatchContinuation)catcher; +- (TOCFuture *)catchTry:(TOCFutureCatchContinuation)catcher; -+(TOCFuture*) retry:(TOCUntilOperation)operation - upToNTimes:(NSUInteger)maxTryCount - withBaseTimeout:(NSTimeInterval)baseTimeout - andRetryFactor:(NSTimeInterval)timeoutRetryFactor - untilCancelled:(TOCCancelToken*)untilCancelledToken; ++ (TOCFuture *)retry:(TOCUntilOperation)operation + upToNTimes:(NSUInteger)maxTryCount + withBaseTimeout:(NSTimeInterval)baseTimeout + andRetryFactor:(NSTimeInterval)timeoutRetryFactor + untilCancelled:(TOCCancelToken *)untilCancelledToken; @end diff --git a/Signal/src/util/FutureUtil.m b/Signal/src/util/FutureUtil.m index 017a0642c..e33ef6321 100644 --- a/Signal/src/util/FutureUtil.m +++ b/Signal/src/util/FutureUtil.m @@ -3,95 +3,98 @@ @implementation TOCCancelToken (FutureUtil) --(void) whenCancelledTerminate:(id)terminable { - require(terminable != nil); - [self whenCancelledDo:^{ [terminable terminate]; }]; +- (void)whenCancelledTerminate:(id)terminable { + ows_require(terminable != nil); + [self whenCancelledDo:^{ + [terminable terminate]; + }]; } @end @implementation TOCFuture (FutureUtil) -+(TOCUntilOperation) operationTry:(TOCUntilOperation)operation { - require(operation != nil); - return ^(TOCCancelToken* until) { - @try { - return operation(until); - } @catch (id ex) { - return [TOCFuture futureWithFailure:ex]; - } ++ (TOCUntilOperation)operationTry:(TOCUntilOperation)operation { + ows_require(operation != nil); + return ^(TOCCancelToken *until) { + @try { + return operation(until); + } @catch (id ex) { + return [TOCFuture futureWithFailure:ex]; + } }; } --(TOCFuture*) thenValue:(id)value { - return [self then:^(id _) { return value; }]; -} - --(TOCFuture*) finallyTry:(TOCFutureFinallyContinuation)completionContinuation { - require(completionContinuation != nil); - - return [self finally:^id(TOCFuture* completed){ - @try { - return completionContinuation(completed); - } @catch (id ex) { - return [TOCFuture futureWithFailure:ex]; - } +- (TOCFuture *)thenValue:(id)value { + return [self then:^(id _) { + return value; }]; } --(TOCFuture*) thenTry:(TOCFutureThenContinuation)resultContinuation { - require(resultContinuation != nil); +- (TOCFuture *)finallyTry:(TOCFutureFinallyContinuation)completionContinuation { + ows_require(completionContinuation != nil); - return [self then:^id(id result){ - @try { - return resultContinuation(result); - } @catch (id ex) { - return [TOCFuture futureWithFailure:ex]; - } + return [self finally:^id(TOCFuture *completed) { + @try { + return completionContinuation(completed); + } @catch (id ex) { + return [TOCFuture futureWithFailure:ex]; + } }]; } --(TOCFuture*) catchTry:(TOCFutureCatchContinuation)failureContinuation { - require(failureContinuation != nil); - - return [self catch:^id(id failure){ - @try { - return failureContinuation(failure); - } @catch (id ex) { - return [TOCFuture futureWithFailure:ex]; - } +- (TOCFuture *)thenTry:(TOCFutureThenContinuation)resultContinuation { + ows_require(resultContinuation != nil); + + return [self then:^id(id result) { + @try { + return resultContinuation(result); + } @catch (id ex) { + return [TOCFuture futureWithFailure:ex]; + } }]; } -+(TOCFuture*) retry:(TOCUntilOperation)operation - upToNTimes:(NSUInteger)maxTryCount - withBaseTimeout:(NSTimeInterval)baseTimeout - andRetryFactor:(NSTimeInterval)timeoutRetryFactor - untilCancelled:(TOCCancelToken*)untilCancelledToken { - - require(operation != nil); - require(maxTryCount >= 0); - require(baseTimeout >= 0); - require(timeoutRetryFactor >= 0); - - if (maxTryCount == 0) return TOCFuture.futureWithTimeoutFailure; - - TOCFuture* futureResult = [TOCFuture futureFromUntilOperation:operation - withOperationTimeout:baseTimeout - until:untilCancelledToken]; - +- (TOCFuture *)catchTry:(TOCFutureCatchContinuation)failureContinuation { + ows_require(failureContinuation != nil); + + return [self catch:^id(id failure) { + @try { + return failureContinuation(failure); + } @catch (id ex) { + return [TOCFuture futureWithFailure:ex]; + } + }]; +} + ++ (TOCFuture *)retry:(TOCUntilOperation)operation + upToNTimes:(NSUInteger)maxTryCount + withBaseTimeout:(NSTimeInterval)baseTimeout + andRetryFactor:(NSTimeInterval)timeoutRetryFactor + untilCancelled:(TOCCancelToken *)untilCancelledToken { + ows_require(operation != nil); + ows_require(maxTryCount >= 0); + ows_require(baseTimeout >= 0); + ows_require(timeoutRetryFactor >= 0); + + if (maxTryCount == 0) + return TOCFuture.futureWithTimeoutFailure; + + TOCFuture *futureResult = + [TOCFuture futureFromUntilOperation:operation withOperationTimeout:baseTimeout until:untilCancelledToken]; + return [futureResult catchTry:^(id error) { - bool operationCancelled = untilCancelledToken.isAlreadyCancelled; - bool operationDidNotTimeout = !futureResult.hasFailedWithTimeout; - if (operationCancelled || operationDidNotTimeout) { - return [TOCFuture futureWithFailure:error]; - } - - return [self retry:operation - upToNTimes:maxTryCount - 1 - withBaseTimeout:baseTimeout * timeoutRetryFactor - andRetryFactor:timeoutRetryFactor - untilCancelled:untilCancelledToken]; + bool operationCancelled = untilCancelledToken.isAlreadyCancelled; + bool operationDidNotTimeout = !futureResult.hasFailedWithTimeout; + if (operationCancelled || operationDidNotTimeout) { + return [TOCFuture futureWithFailure:error]; + } + + return [self retry:operation + upToNTimes:maxTryCount - 1 + withBaseTimeout:baseTimeout * timeoutRetryFactor + andRetryFactor:timeoutRetryFactor + untilCancelled:untilCancelledToken]; }]; } diff --git a/Signal/src/util/MIMETypeUtil.h b/Signal/src/util/MIMETypeUtil.h deleted file mode 100644 index cb4aee4e8..000000000 --- a/Signal/src/util/MIMETypeUtil.h +++ /dev/null @@ -1,42 +0,0 @@ -#import - -@interface MIMETypeUtil : NSObject - -+(BOOL)isSupportedMIMEType:(NSString*)contentType; -+(BOOL)isSupportedVideoMIMEType:(NSString*)contentType; -+(BOOL)isSupportedAudioMIMEType:(NSString*)contentType; -+(BOOL)isSupportedImageMIMEType:(NSString*)contentType; -+(BOOL)isSupportedAnimatedMIMEType:(NSString*)contentType; - -+(BOOL)isSupportedVideoFile:(NSString*)filePath; -+(BOOL)isSupportedAudioFile:(NSString*)filePath; -+(BOOL)isSupportedImageFile:(NSString*)filePath; -+(BOOL)isSupportedAnimatedFile:(NSString*)filePath; - -+(NSString*)getSupportedExtensionFromVideoMIMEType:(NSString*)supportedMIMEType; -+(NSString*)getSupportedExtensionFromAudioMIMEType:(NSString*)supportedMIMEType; -+(NSString*)getSupportedExtensionFromImageMIMEType:(NSString*)supportedMIMEType; -+(NSString*)getSupportedExtensionFromAnimatedMIMEType:(NSString*)supportedMIMEType; - -+(NSString*)getSupportedMIMETypeFromVideoFile:(NSString*)supportedVideoFile; -+(NSString*)getSupportedMIMETypeFromAudioFile:(NSString*)supportedAudioFile; -+(NSString*)getSupportedMIMETypeFromImageFile:(NSString*)supportedImageFile; -+(NSString*)getSupportedMIMETypeFromAnimatedFile:(NSString*)supportedImageFile; - -+(NSString*)getSupportedImageMIMETypeFromImage:(UIImage*)image; -+(BOOL)getIsSupportedTypeFromImage:(UIImage*)image; - -+(BOOL)isAnimated:(NSString*)contentType; -+(BOOL)isImage:(NSString*)contentType; -+(BOOL)isVideo:(NSString*)contentType; -+(BOOL)isAudio:(NSString*)contentType; - -+(NSString*)filePathForAttachment:(NSString*)uniqueId ofMIMEType:(NSString*)contentType inFolder:(NSString*)folder; -+(NSString*)filePathForImage:(NSString*)uniqueId ofMIMEType:(NSString*)contentType inFolder:(NSString*)folder; -+(NSString*)filePathForVideo:(NSString*)uniqueId ofMIMEType:(NSString*)contentType inFolder:(NSString*)folder; -+(NSString*)filePathForAudio:(NSString*)uniqueId ofMIMEType:(NSString*)contentType inFolder:(NSString*)folder; -+(NSString*)filePathForAnimated:(NSString*)uniqueId ofMIMEType:(NSString*)contentType inFolder:(NSString*)folder; - -+(NSURL*)simLinkCorrectExtensionOfFile:(NSURL*)mediaURL ofMIMEType:(NSString*)contentType; - -@end diff --git a/Signal/src/util/MIMETypeUtil.m b/Signal/src/util/MIMETypeUtil.m deleted file mode 100644 index 0983d999b..000000000 --- a/Signal/src/util/MIMETypeUtil.m +++ /dev/null @@ -1,252 +0,0 @@ -#import "MIMETypeUtil.h" -#import "UIImage+contentTypes.h" - -@implementation MIMETypeUtil - -+ (NSDictionary*)supportedVideoMIMETypesToExtensionTypes{ - return @{@"video/3gpp":@"3gp", - @"video/3gpp2":@"3g2", - @"video/mp4":@"mp4", - @"video/quicktime":@"mov", - @"video/x-m4v":@"m4v" - }; -} - -+ (NSDictionary*)supportedAudioMIMETypesToExtensionTypes{ - return @{@"audio/x-m4p":@"m4p", - @"audio/x-m4b":@"m4b", - @"audio/x-m4a":@"m4a", - @"audio/wav":@"wav", - @"audio/x-wav":@"wav", - @"audio/x-mpeg":@"mp3", - @"audio/mpeg":@"mp3", - @"audio/mp4":@"mp4", - @"audio/mp3":@"mp3", - @"audio/mpeg3":@"mp3", - @"audio/x-mp3":@"mp3", - @"audio/x-mpeg3":@"mp3", - @"audio/amr":@"amr", - @"audio/aiff":@"aiff", - @"audio/x-aiff":@"aiff", - @"audio/3gpp2":@"3g2", - @"audio/3gpp":@"3gp" - }; -} - -+ (NSDictionary*)supportedImageMIMETypesToExtensionTypes{ - return @{@"image/jpeg":@"jpeg", - @"image/pjpeg":@"jpeg", - @"image/png":@"png", - @"image/tiff":@"tif", - @"image/x-tiff":@"tif", - @"image/bmp":@"bmp", - @"image/x-windows-bmp":@"bmp" - }; -} - -+ (NSDictionary*)supportedAnimatedMIMETypesToExtensionTypes{ - return @{@"image/gif":@"gif", - }; -} - -+ (NSDictionary*)supportedVideoExtensionTypesToMIMETypes{ - return @{@"3gp":@"video/3gpp", - @"3gpp":@"video/3gpp", - @"3gp2":@"video/3gpp2", - @"3gpp2":@"video/3gpp2", - @"mp4":@"video/mp4", - @"mov":@"video/quicktime", - @"mqv":@"video/quicktime", - @"m4v":@"video/x-m4v" - }; -} -+ (NSDictionary*)supportedAudioExtensionTypesToMIMETypes{ - return @{@"3gp":@"audio/3gpp", - @"3gpp":@"@audio/3gpp", - @"3g2":@"audio/3gpp2", - @"3gp2":@"audio/3gpp2", - @"aiff":@"audio/aiff", - @"aif":@"audio/aiff", - @"aifc":@"audio/aiff", - @"cdda":@"audio/aiff", - @"amr":@"audio/amr", - @"mp3":@"audio/mp3", - @"swa":@"audio/mp3", - @"mp4":@"audio/mp4", - @"mpeg":@"audio/mpeg", - @"mpg":@"audio/mpeg", - @"wav":@"audio/wav", - @"bwf":@"audio/wav", - @"m4a":@"audio/x-m4a", - @"m4b":@"audio/x-m4b", - @"m4p":@"audio/x-m4p" - }; -} - -+ (NSDictionary*)supportedImageExtensionTypesToMIMETypes{ - return @{@"png":@"image/png", - @"x-png":@"image/png", - @"jfif":@"image/jpeg", - @"jfif":@"image/pjpeg", - @"jfif-tbnl":@"image/jpeg", - @"jpe":@"image/jpeg", - @"jpe":@"image/pjpeg", - @"jpeg":@"image/jpeg", - @"jpg":@"image/jpeg", - @"tif":@"image/tiff", - @"tiff":@"image/tiff" - }; -} - -+ (NSDictionary*)supportedAnimatedExtensionTypesToMIMETypes{ - return @{@"gif":@"image/gif", - }; -} - -+(BOOL) isSupportedVideoMIMEType:(NSString*)contentType { - return [[self supportedVideoMIMETypesToExtensionTypes] objectForKey:contentType]!=nil; -} - -+(BOOL) isSupportedAudioMIMEType:(NSString*)contentType { - return [[self supportedAudioMIMETypesToExtensionTypes] objectForKey:contentType]!=nil; -} - -+(BOOL) isSupportedImageMIMEType:(NSString*)contentType { - return [[self supportedImageMIMETypesToExtensionTypes] objectForKey:contentType]!=nil; -} - -+(BOOL) isSupportedAnimatedMIMEType:(NSString*)contentType { - return [[self supportedAnimatedMIMETypesToExtensionTypes] objectForKey:contentType]!=nil; -} - -+(BOOL) isSupportedMIMEType:(NSString*)contentType { - return [self isSupportedImageMIMEType:contentType] || [self isSupportedAudioMIMEType:contentType] || [self isSupportedVideoMIMEType:contentType] || [self isSupportedAnimatedMIMEType:contentType]; -} - -+(BOOL) isSupportedVideoFile:(NSString*) filePath { - return [[self supportedVideoExtensionTypesToMIMETypes] objectForKey:[filePath pathExtension]]!=nil; -} - -+(BOOL) isSupportedAudioFile:(NSString*) filePath { - return [[self supportedAudioExtensionTypesToMIMETypes] objectForKey:[filePath pathExtension]]!=nil; -} - -+(BOOL) isSupportedImageFile:(NSString*) filePath { - return [[self supportedImageExtensionTypesToMIMETypes] objectForKey:[filePath pathExtension]]!=nil; -} - -+(BOOL) isSupportedAnimatedFile:(NSString*) filePath { - return [[self supportedAnimatedExtensionTypesToMIMETypes] objectForKey:[filePath pathExtension]]!=nil; -} - -+(NSString*) getSupportedExtensionFromVideoMIMEType:(NSString*)supportedMIMEType { - return [[self supportedVideoMIMETypesToExtensionTypes] objectForKey:supportedMIMEType]; -} - -+(NSString*) getSupportedExtensionFromAudioMIMEType:(NSString*)supportedMIMEType { - return [[self supportedAudioMIMETypesToExtensionTypes] objectForKey:supportedMIMEType]; -} - -+(NSString*) getSupportedExtensionFromImageMIMEType:(NSString*)supportedMIMEType { - return [[self supportedImageMIMETypesToExtensionTypes] objectForKey:supportedMIMEType]; -} - -+(NSString*) getSupportedExtensionFromAnimatedMIMEType:(NSString*)supportedMIMEType { - return [[self supportedAnimatedMIMETypesToExtensionTypes] objectForKey:supportedMIMEType]; -} - -+(NSString*) getSupportedMIMETypeFromVideoFile:(NSString*)supportedVideoFile { - return [[self supportedVideoExtensionTypesToMIMETypes] objectForKey:[supportedVideoFile pathExtension]]; -} - -+(NSString*) getSupportedMIMETypeFromAudioFile:(NSString*)supportedAudioFile { - return [[self supportedAudioExtensionTypesToMIMETypes] objectForKey:[supportedAudioFile pathExtension]]; -} - -+(NSString*) getSupportedMIMETypeFromImageFile:(NSString*)supportedImageFile { - return [[self supportedImageExtensionTypesToMIMETypes] objectForKey:[supportedImageFile pathExtension]]; -} - -+(NSString*) getSupportedMIMETypeFromAnimatedFile:(NSString*)supportedAnimatedFile { - return [[self supportedAnimatedExtensionTypesToMIMETypes] objectForKey:[supportedAnimatedFile pathExtension]]; -} - -#pragma mark uses bytes -+(NSString*) getSupportedImageMIMETypeFromImage:(UIImage*)image { - return [image contentType]; -} - -+(BOOL) getIsSupportedTypeFromImage:(UIImage*)image { - return [image isSupportedImageType]; -} - -#pragma mark full attachment utilities -+ (BOOL)isAnimated:(NSString *)contentType { - return [MIMETypeUtil isSupportedAnimatedMIMEType:contentType]; -} -+ (BOOL)isImage:(NSString*)contentType { - return [MIMETypeUtil isSupportedImageMIMEType:contentType]; -} - -+ (BOOL)isVideo:(NSString*)contentType { - return [MIMETypeUtil isSupportedVideoMIMEType:contentType]; -} - -+(BOOL)isAudio:(NSString*)contentType { - return [MIMETypeUtil isSupportedAudioMIMEType:contentType]; -} - -+ (NSString*)filePathForAttachment:(NSString*)uniqueId ofMIMEType:(NSString*)contentType inFolder:(NSString*)folder { - if ([self isVideo:contentType]){ - return [MIMETypeUtil filePathForVideo:uniqueId ofMIMEType:contentType inFolder:folder]; - } - else if([self isAudio:contentType]) { - return [MIMETypeUtil filePathForAudio:uniqueId ofMIMEType:contentType inFolder:folder]; - } - else if([self isImage:contentType]){ - return [MIMETypeUtil filePathForImage:uniqueId ofMIMEType:contentType inFolder:folder]; - } - else if([self isAnimated:contentType]){ - return [MIMETypeUtil filePathForAnimated:uniqueId ofMIMEType:contentType inFolder:folder]; - } - - DDLogError(@"Got asked for path of file %@ which is unsupported", contentType); - return nil; -} - -+(NSURL*) simLinkCorrectExtensionOfFile:(NSURL*)mediaURL ofMIMEType:(NSString*)contentType { - if([self isAudio:contentType]) { - // Audio files in current framework require changing to have extension for player - return [self changeFile:mediaURL toHaveExtension:[[self supportedAudioMIMETypesToExtensionTypes] objectForKey:contentType]]; - } - return mediaURL; -} - -+(NSURL*) changeFile:(NSURL*)originalFile toHaveExtension:(NSString*)extension { - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSString* newPath = [originalFile.URLByDeletingPathExtension.absoluteString stringByAppendingPathExtension:extension]; - if (![fileManager fileExistsAtPath:newPath]) { - NSError *error = nil; - [fileManager createSymbolicLinkAtPath:newPath withDestinationPath:[originalFile path] error: &error]; - return [NSURL URLWithString:newPath]; - } - return originalFile; -} - -+ (NSString*)filePathForImage:(NSString*)uniqueId ofMIMEType:(NSString*)contentType inFolder:(NSString*)folder{ - return [[folder stringByAppendingFormat:@"/%@",uniqueId] stringByAppendingPathExtension:[self getSupportedExtensionFromImageMIMEType:contentType]]; -} - -+ (NSString*)filePathForVideo:(NSString*)uniqueId ofMIMEType:(NSString*)contentType inFolder:(NSString*)folder{ - return [[folder stringByAppendingFormat:@"/%@",uniqueId] stringByAppendingPathExtension:[self getSupportedExtensionFromVideoMIMEType:contentType]]; -} - -+ (NSString*)filePathForAudio:(NSString*)uniqueId ofMIMEType:(NSString*)contentType inFolder:(NSString*)folder{ - return [[folder stringByAppendingFormat:@"/%@",uniqueId] stringByAppendingPathExtension:[self getSupportedExtensionFromAudioMIMEType:contentType]]; -} - -+ (NSString*)filePathForAnimated:(NSString*)uniqueId ofMIMEType:(NSString*)contentType inFolder:(NSString*)folder{ - return [[folder stringByAppendingFormat:@"/%@",uniqueId] stringByAppendingPathExtension:[self getSupportedExtensionFromAnimatedMIMEType:contentType]]; -} - -@end diff --git a/Signal/src/util/NSData+ows_StripToken.h b/Signal/src/util/NSData+ows_StripToken.h index 80900bf3b..a014a3d55 100644 --- a/Signal/src/util/NSData+ows_StripToken.h +++ b/Signal/src/util/NSData+ows_StripToken.h @@ -10,6 +10,6 @@ @interface NSData (ows_StripToken) -- (NSString*)ows_tripToken; +- (NSString *)ows_tripToken; @end diff --git a/Signal/src/util/NSData+ows_StripToken.m b/Signal/src/util/NSData+ows_StripToken.m index 23cbd7272..c61ce6918 100644 --- a/Signal/src/util/NSData+ows_StripToken.m +++ b/Signal/src/util/NSData+ows_StripToken.m @@ -10,10 +10,11 @@ @implementation NSData (ows_StripToken) -- (NSString*)ows_tripToken { +- (NSString *)ows_tripToken { return [[[NSString stringWithFormat:@"%@", self] - stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] - stringByReplacingOccurrencesOfString:@" " withString:@""]; + stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] + stringByReplacingOccurrencesOfString:@" " + withString:@""]; } @end diff --git a/Signal/src/util/NumberUtil.h b/Signal/src/util/NumberUtil.h index 829137f55..3c2298cd0 100644 --- a/Signal/src/util/NumberUtil.h +++ b/Signal/src/util/NumberUtil.h @@ -1,43 +1,43 @@ #import -#import "DataUtil.h" -#import "StringUtil.h" -#import "DictionaryUtil.h" #import "ArrayUtil.h" +#import "DataUtil.h" +#import "DictionaryUtil.h" +#import "StringUtil.h" @interface NumberUtil : NSObject -+(int16_t) congruentDifferenceMod2ToThe16From:(uint16_t)s1 to:(uint16_t)s2; ++ (int16_t)congruentDifferenceMod2ToThe16From:(uint16_t)s1 to:(uint16_t)s2; -+(int8_t) signOfInt32:(int32_t)value; ++ (int8_t)signOfInt32:(int32_t)value; -+(int8_t) signOfDouble:(double)value; ++ (int8_t)signOfDouble:(double)value; -+(NSUInteger) largestIntegerThatIsAtMost:(NSUInteger)value andIsAMultipleOf:(NSUInteger)multiple; ++ (NSUInteger)largestIntegerThatIsAtMost:(NSUInteger)value andIsAMultipleOf:(NSUInteger)multiple; -+(NSUInteger) smallestIntegerThatIsAtLeast:(NSUInteger)value andIsAMultipleOf:(NSUInteger)multiple; ++ (NSUInteger)smallestIntegerThatIsAtLeast:(NSUInteger)value andIsAMultipleOf:(NSUInteger)multiple; -+(double) clamp:(double)value toMin:(double)min andMax:(double)max; ++ (double)clamp:(double)value toMin:(double)min andMax:(double)max; -+(NSUInteger) from:(NSUInteger)value subtractWithSaturationAtZero:(NSUInteger)minusDelta; ++ (NSUInteger)from:(NSUInteger)value subtractWithSaturationAtZero:(NSUInteger)minusDelta; -+(uint8_t) uint8FromLowUInt4:(uint8_t)low4UInt4 andHighUInt4:(uint8_t)highUInt4; ++ (uint8_t)uint8FromLowUInt4:(uint8_t)low4UInt4 andHighUInt4:(uint8_t)highUInt4; -+(uint8_t) lowUInt4OfUint8:(uint8_t)value; ++ (uint8_t)lowUInt4OfUint8:(uint8_t)value; -+(uint8_t) highUInt4OfUint8:(uint8_t)value; ++ (uint8_t)highUInt4OfUint8:(uint8_t)value; -+(NSUInteger) assertConvertIntToNSUInteger:(int) value; ++ (NSUInteger)assertConvertIntToNSUInteger:(int)value; -+(NSInteger) assertConvertUnsignedIntToNSInteger:(unsigned int) value; ++ (NSInteger)assertConvertUnsignedIntToNSInteger:(unsigned int)value; -+(int) assertConvertNSUIntegerToInt:(NSUInteger) value; ++ (int)assertConvertNSUIntegerToInt:(NSUInteger)value; @end @interface NSNumber (NumberUtil) --(bool) hasUnsignedIntegerValue; --(bool) hasUnsignedLongLongValue; --(bool) hasLongLongValue; +- (bool)hasUnsignedIntegerValue; +- (bool)hasUnsignedLongLongValue; +- (bool)hasLongLongValue; @end diff --git a/Signal/src/util/NumberUtil.m b/Signal/src/util/NumberUtil.m index 4ea3bc8b5..f3447b325 100644 --- a/Signal/src/util/NumberUtil.m +++ b/Signal/src/util/NumberUtil.m @@ -1,78 +1,87 @@ -#import "NumberUtil.h" #import "Constraints.h" +#import "NumberUtil.h" @implementation NumberUtil -+(int16_t) congruentDifferenceMod2ToThe16From:(uint16_t)s1 to:(uint16_t)s2 { ++ (int16_t)congruentDifferenceMod2ToThe16From:(uint16_t)s1 to:(uint16_t)s2 { int32_t d = (int32_t)(s2 - s1); - if (d > INT16_MAX) d -= 1 << 16; + if (d > INT16_MAX) + d -= 1 << 16; return (int16_t)d; } -+(int8_t) signOfInt32:(int32_t)value { - if (value < 0) return -1; - if (value > 0) return +1; ++ (int8_t)signOfInt32:(int32_t)value { + if (value < 0) + return -1; + if (value > 0) + return +1; return 0; } -+(int8_t) signOfDouble:(double)value { - if (value < 0) return -1; - if (value > 0) return +1; ++ (int8_t)signOfDouble:(double)value { + if (value < 0) + return -1; + if (value > 0) + return +1; return 0; } -+(NSUInteger) largestIntegerThatIsAtMost:(NSUInteger)value andIsAMultipleOf:(NSUInteger)multiple { - require(multiple != 0); ++ (NSUInteger)largestIntegerThatIsAtMost:(NSUInteger)value andIsAMultipleOf:(NSUInteger)multiple { + ows_require(multiple != 0); NSUInteger d = value / multiple; d *= multiple; - if (d > value) d -= multiple; + if (d > value) + d -= multiple; return d; } -+(NSUInteger) smallestIntegerThatIsAtLeast:(NSUInteger)value andIsAMultipleOf:(NSUInteger)multiple { - require(multiple != 0); ++ (NSUInteger)smallestIntegerThatIsAtLeast:(NSUInteger)value andIsAMultipleOf:(NSUInteger)multiple { + ows_require(multiple != 0); NSUInteger d = value / multiple; d *= multiple; - if (d < value) d += multiple; + if (d < value) + d += multiple; return d; } -+(double) clamp:(double)value toMin:(double)min andMax:(double)max { - require(min <= max); - if (value < min) return min; - if (value > max) return max; ++ (double)clamp:(double)value toMin:(double)min andMax:(double)max { + ows_require(min <= max); + if (value < min) + return min; + if (value > max) + return max; return value; } -+(NSUInteger) from:(NSUInteger)value subtractWithSaturationAtZero:(NSUInteger)minusDelta { ++ (NSUInteger)from:(NSUInteger)value subtractWithSaturationAtZero:(NSUInteger)minusDelta { return value - MIN(value, minusDelta); } -+(uint8_t) uint8FromLowUInt4:(uint8_t)low4UInt4 andHighUInt4:(uint8_t)highUInt4 { - require(low4UInt4 < 0x10); - require(highUInt4 < 0x10); ++ (uint8_t)uint8FromLowUInt4:(uint8_t)low4UInt4 andHighUInt4:(uint8_t)highUInt4 { + ows_require(low4UInt4 < 0x10); + ows_require(highUInt4 < 0x10); return low4UInt4 | (uint8_t)(highUInt4 << 4); } -+(uint8_t) lowUInt4OfUint8:(uint8_t)value { ++ (uint8_t)lowUInt4OfUint8:(uint8_t)value { return value & 0xF; } -+(uint8_t) highUInt4OfUint8:(uint8_t)value { ++ (uint8_t)highUInt4OfUint8:(uint8_t)value { return value >> 4; } -+(NSUInteger) assertConvertIntToNSUInteger:(int) value { ++ (NSUInteger)assertConvertIntToNSUInteger:(int)value { assert(0 <= value); return (NSUInteger)value; } -+(NSInteger) assertConvertUnsignedIntToNSInteger:(unsigned int) value { ++ (NSInteger)assertConvertUnsignedIntToNSInteger:(unsigned int)value { // uint is a subset of NSInteger(long) bounds check is always true return (NSInteger)value; } -+(int) assertConvertNSUIntegerToInt:(NSUInteger) value { ++ (int)assertConvertNSUIntegerToInt:(NSUInteger)value { assert(value <= INT32_MAX); return (int)value; } @@ -82,13 +91,13 @@ @implementation NSNumber (NumberUtil) --(bool) hasUnsignedIntegerValue { +- (bool)hasUnsignedIntegerValue { return [self isEqual:@([self unsignedIntegerValue])]; } --(bool) hasUnsignedLongLongValue { +- (bool)hasUnsignedLongLongValue { return [self isEqual:@([self unsignedLongLongValue])]; } --(bool) hasLongLongValue { +- (bool)hasLongLongValue { return [self isEqual:@([self longLongValue])]; } diff --git a/Signal/src/util/ObservableValue.h b/Signal/src/util/ObservableValue.h index 921d73739..72e43dd31 100644 --- a/Signal/src/util/ObservableValue.h +++ b/Signal/src/util/ObservableValue.h @@ -6,32 +6,37 @@ typedef void (^LatestValueCallback)(id latestValue); /** * - * An ObservableValue represents an asynchronous stream of values, such as 'latest state of toggle' or 'latest sensor reading'. + * An ObservableValue represents an asynchronous stream of values, such as 'latest state of toggle' or 'latest sensor + * reading'. * */ @interface ObservableValue : NSObject { -@protected NSMutableSet* callbacks; -@private Queue* queuedActionsToRun; -@private bool isRunningActions; -@protected bool sealed; + @protected + NSMutableSet *callbacks; + @private + Queue *queuedActionsToRun; + @private + bool isRunningActions; + @protected + bool sealed; } -@property (readonly,atomic) id currentValue; +@property (readonly, atomic) id currentValue; --(void) watchLatestValueOnArbitraryThread:(LatestValueCallback)callback - untilCancelled:(TOCCancelToken*)untilCancelledToken; +- (void)watchLatestValueOnArbitraryThread:(LatestValueCallback)callback + untilCancelled:(TOCCancelToken *)untilCancelledToken; --(void) watchLatestValue:(LatestValueCallback)callback - onThread:(NSThread*)thread - untilCancelled:(TOCCancelToken*)untilCancelledToken; +- (void)watchLatestValue:(LatestValueCallback)callback + onThread:(NSThread *)thread + untilCancelled:(TOCCancelToken *)untilCancelledToken; @end @interface ObservableValueController : ObservableValue -+(ObservableValueController *)observableValueControllerWithInitialValue:(id)value; --(void)updateValue:(id)value; --(void)adjustValue:(id(^)(id))adjustment; --(void)sealValue; ++ (ObservableValueController *)observableValueControllerWithInitialValue:(id)value; +- (void)updateValue:(id)value; +- (void)adjustValue:(id (^)(id))adjustment; +- (void)sealValue; @end diff --git a/Signal/src/util/ObservableValue.m b/Signal/src/util/ObservableValue.m index 26454f0b4..b7319b364 100644 --- a/Signal/src/util/ObservableValue.m +++ b/Signal/src/util/ObservableValue.m @@ -1,53 +1,54 @@ +#import "Environment.h" #import "ObservableValue.h" #import "Util.h" -#import "Environment.h" @implementation ObservableValue @synthesize currentValue; --(ObservableValue*) initWithValue:(id)value { - callbacks = [NSMutableSet set]; +- (ObservableValue *)initWithValue:(id)value { + callbacks = [NSMutableSet set]; queuedActionsToRun = [Queue new]; - currentValue = value; + currentValue = value; return self; } --(void) watchLatestValueOnArbitraryThread:(LatestValueCallback)callback - untilCancelled:(TOCCancelToken*)untilCancelledToken { - - require(callback != nil); - if (untilCancelledToken.isAlreadyCancelled) return; - - void(^callbackCopy)(id value) = [callback copy]; +- (void)watchLatestValueOnArbitraryThread:(LatestValueCallback)callback + untilCancelled:(TOCCancelToken *)untilCancelledToken { + ows_require(callback != nil); + if (untilCancelledToken.isAlreadyCancelled) + return; + + void (^callbackCopy)(id value) = [callback copy]; [self queueRun:^{ - callbackCopy(self.currentValue); - [callbacks addObject:callbackCopy]; + callbackCopy(self.currentValue); + [callbacks addObject:callbackCopy]; }]; [untilCancelledToken whenCancelledDo:^{ - [self queueRun:^{ - [callbacks removeObject:callbackCopy]; - }]; + [self queueRun:^{ + [callbacks removeObject:callbackCopy]; + }]; }]; } --(void) watchLatestValue:(LatestValueCallback)callback - onThread:(NSThread*)thread - untilCancelled:(TOCCancelToken*)untilCancelledToken { - - require(callback != nil); - require(thread != nil); - - void(^callbackCopy)(id value) = [callback copy]; - void(^threadedCallback)(id value) = ^(id value) { - [Operation asyncRun:^{callbackCopy(value);} onThread:thread]; +- (void)watchLatestValue:(LatestValueCallback)callback + onThread:(NSThread *)thread + untilCancelled:(TOCCancelToken *)untilCancelledToken { + ows_require(callback != nil); + ows_require(thread != nil); + + void (^callbackCopy)(id value) = [callback copy]; + void (^threadedCallback)(id value) = ^(id value) { + [Operation asyncRun:^{ + callbackCopy(value); + } + onThread:thread]; }; - - [self watchLatestValueOnArbitraryThread:threadedCallback - untilCancelled:untilCancelledToken]; + + [self watchLatestValueOnArbitraryThread:threadedCallback untilCancelled:untilCancelledToken]; } /// used for avoiding re-entrancy issues (e.g. a callback registering another callback during enumeration) --(void) queueRun:(void(^)())action { +- (void)queueRun:(void (^)())action { @synchronized(self) { if (isRunningActions) { [queuedActionsToRun enqueue:[action copy]]; @@ -55,20 +56,21 @@ } isRunningActions = true; } - + while (true) { @try { action(); } @catch (id ex) { [[Environment.logging getConditionLoggerForSender:self] - logError:@"A queued action failed and may have stalled an ObservableValue."]; + logError:@"A queued action failed and may have stalled an ObservableValue."]; @synchronized(self) { isRunningActions = false; } [ex raise]; } - - @synchronized(self) { + + @ + synchronized(self) { action = [queuedActionsToRun tryDequeue]; if (action == nil) { isRunningActions = false; @@ -78,29 +80,31 @@ } } --(void)updateValue:(id)value { +- (void)updateValue:(id)value { [self queueRun:^{ - if (value == currentValue) return; - requireState(!sealed); - - currentValue = value; - for (void(^callback)(id value) in callbacks) { - callback(value); - } + if (value == currentValue) + return; + requireState(!sealed); + + currentValue = value; + for (void (^callback)(id value) in callbacks) { + callback(value); + } }]; } --(void)adjustValue:(id(^)(id))adjustment { - require(adjustment != nil); +- (void)adjustValue:(id (^)(id))adjustment { + ows_require(adjustment != nil); [self queueRun:^{ - id oldValue = currentValue; - id newValue = adjustment(oldValue); - if (oldValue == newValue) return; - requireState(!sealed); - - currentValue = newValue; - for (void(^callback)(id value) in callbacks) { - callback(currentValue); - } + id oldValue = currentValue; + id newValue = adjustment(oldValue); + if (oldValue == newValue) + return; + requireState(!sealed); + + currentValue = newValue; + for (void (^callback)(id value) in callbacks) { + callback(currentValue); + } }]; } @@ -108,18 +112,21 @@ @implementation ObservableValueController -+(ObservableValueController *)observableValueControllerWithInitialValue:(id)value { ++ (ObservableValueController *)observableValueControllerWithInitialValue:(id)value { return [[ObservableValueController alloc] initWithValue:value]; } --(void)updateValue:(id)value { +- (void)updateValue:(id)value { [super updateValue:value]; } --(void)adjustValue:(id(^)(id))adjustment { +- (void)adjustValue:(id (^)(id))adjustment { [super adjustValue:adjustment]; } --(void) sealValue { - [self queueRun:^{sealed = true; callbacks = nil;}]; +- (void)sealValue { + [self queueRun:^{ + sealed = true; + callbacks = nil; + }]; } @end diff --git a/Signal/src/util/Operation.h b/Signal/src/util/Operation.h index b3a64c089..6f1a595c8 100644 --- a/Signal/src/util/Operation.h +++ b/Signal/src/util/Operation.h @@ -1,34 +1,32 @@ #import -#import "DataUtil.h" -#import "StringUtil.h" -#import "DictionaryUtil.h" #import "ArrayUtil.h" +#import "DataUtil.h" +#import "DictionaryUtil.h" +#import "StringUtil.h" -typedef void(^Action)(void); -typedef id(^Function)(void); +typedef void (^Action)(void); +typedef id (^Function)(void); @interface Operation : NSObject -@property (nonatomic,readonly,copy) Action callback; +@property (nonatomic, readonly, copy) Action callback; -+(Operation*) operation:(Action)block; ++ (Operation *)operation:(Action)block; -+(void) asyncRun:(Action)action - onThread:(NSThread*)thread; ++ (void)asyncRun:(Action)action onThread:(NSThread *)thread; -+(void) asyncRunAndWaitUntilDone:(Action)action - onThread:(NSThread*)thread; ++ (void)asyncRunAndWaitUntilDone:(Action)action onThread:(NSThread *)thread; -+(void) asyncRunOnNewThread:(Action)action; ++ (void)asyncRunOnNewThread:(Action)action; --(void)run; +- (void)run; --(SEL) selectorToRun; +- (SEL)selectorToRun; --(void) performOnNewThread; +- (void)performOnNewThread; --(void) performOnThread:(NSThread*)thread; +- (void)performOnThread:(NSThread *)thread; --(void) performOnThreadAndWaitUntilDone:(NSThread*)thread; +- (void)performOnThreadAndWaitUntilDone:(NSThread *)thread; @end diff --git a/Signal/src/util/Operation.m b/Signal/src/util/Operation.m index 0177bc777..68e22aa8d 100644 --- a/Signal/src/util/Operation.m +++ b/Signal/src/util/Operation.m @@ -2,55 +2,51 @@ @implementation Operation -+(Operation*) operation:(Action)block { - require(block != NULL); - Operation* a = [Operation new]; ++ (Operation *)operation:(Action)block { + ows_require(block != NULL); + Operation *a = [Operation new]; a->_callback = block; return a; } -+(void) asyncRun:(Action)action - onThread:(NSThread*)thread { - - require(action != nil); - require(thread != nil); - ++ (void)asyncRun:(Action)action onThread:(NSThread *)thread { + ows_require(action != nil); + ows_require(thread != nil); + [[Operation operation:action] performOnThread:thread]; } -+(void) asyncRunAndWaitUntilDone:(Action)action - onThread:(NSThread*)thread { - - require(action != nil); - require(thread != nil); - ++ (void)asyncRunAndWaitUntilDone:(Action)action onThread:(NSThread *)thread { + ows_require(action != nil); + ows_require(thread != nil); + [[Operation operation:action] performOnThreadAndWaitUntilDone:thread]; } -+(void) asyncRunOnNewThread:(Action)action { - require(action != nil); ++ (void)asyncRunOnNewThread:(Action)action { + ows_require(action != nil); [[Operation operation:action] performOnNewThread]; } --(SEL) selectorToRun { +- (SEL)selectorToRun { return @selector(run); } --(void) performOnThread:(NSThread*)thread { - require(thread != nil); +- (void)performOnThread:(NSThread *)thread { + ows_require(thread != nil); [self performSelector:@selector(run) onThread:thread withObject:nil waitUntilDone:thread == NSThread.currentThread]; } --(void) performOnThreadAndWaitUntilDone:(NSThread*)thread { - require(thread != nil); +- (void)performOnThreadAndWaitUntilDone:(NSThread *)thread { + ows_require(thread != nil); [self performSelector:@selector(run) onThread:thread withObject:nil waitUntilDone:true]; } --(void) performOnNewThread { +- (void)performOnNewThread { [NSThread detachNewThreadSelector:[self selectorToRun] toTarget:self withObject:nil]; } --(void) run { +- (void)run { _callback(); } diff --git a/Signal/src/util/PhoneNumberUtil.h b/Signal/src/util/PhoneNumberUtil.h deleted file mode 100644 index c880490ab..000000000 --- a/Signal/src/util/PhoneNumberUtil.h +++ /dev/null @@ -1,22 +0,0 @@ -#import -#import "PhoneNumber.h" -#import "NBPhoneNumberUtil.h" - -@interface PhoneNumberUtil : NSObject - -MacrosSingletonInterface - -@property (nonatomic, retain) NBPhoneNumberUtil *nbPhoneNumberUtil; - -+ (NSString *)callingCodeFromCountryCode:(NSString *)code; -+ (NSString *)countryNameFromCountryCode:(NSString *)code; -+ (NSArray *)countryCodesForSearchTerm:(NSString *)searchTerm; -+ (NSString*) normalizePhoneNumber:(NSString *) number; -+(NSArray *)validCountryCallingPrefixes:(NSString *)string; - -+(NSUInteger) translateCursorPosition:(NSUInteger)offset - from:(NSString*)source - to:(NSString*)target - stickingRightward:(bool)preferHigh; - -@end diff --git a/Signal/src/util/PhoneNumberUtil.m b/Signal/src/util/PhoneNumberUtil.m deleted file mode 100644 index ce99967a5..000000000 --- a/Signal/src/util/PhoneNumberUtil.m +++ /dev/null @@ -1,155 +0,0 @@ -#import "PhoneNumberUtil.h" -#import "ContactsManager.h" -#import "Util.h" - -@implementation PhoneNumberUtil - -MacrosSingletonImplemention - -- (instancetype)init { - self = [super init]; - - if (self) { - _nbPhoneNumberUtil = [[NBPhoneNumberUtil alloc] init]; - } - - return self; -} - -// country code -> country name -+ (NSString *)countryNameFromCountryCode:(NSString *)code { - NSDictionary *countryCodeComponent = @{NSLocaleCountryCode: code}; - NSString *identifier = [NSLocale localeIdentifierFromComponents:countryCodeComponent]; - NSString *country = [NSLocale.currentLocale displayNameForKey:NSLocaleIdentifier - value:identifier]; - return country; -} - -// country code -> calling code -+ (NSString *)callingCodeFromCountryCode:(NSString *)code { - NSNumber *callingCode = [[[self sharedInstance] nbPhoneNumberUtil] getCountryCodeForRegion:code]; - return [NSString stringWithFormat:@"%@%@", COUNTRY_CODE_PREFIX, callingCode]; -} - -// search term -> country codes -+ (NSArray *)countryCodesForSearchTerm:(NSString *)searchTerm { - - NSArray *countryCodes = NSLocale.ISOCountryCodes; - - if (searchTerm) { - countryCodes = [countryCodes filter:^int(NSString *code) { - NSString *countryName = [self countryNameFromCountryCode:code]; - NSString *callingCode = [self callingCodeFromCountryCode:code]; - - if ([ContactsManager name:countryName matchesQuery:searchTerm]) { - return YES; - } - - // We rely on the already internationalized string; as that is what - // the user would see entered (i.e. with COUNTRY_CODE_PREFIX). - - if ([callingCode containsString:searchTerm]) { - return YES; - } - return NO; - }]; - } - - return [self sortedCountryCodesByName:countryCodes]; -} - -+(NSArray *)validCountryCallingPrefixes:(NSString *)string { - NSArray *countryCodes = NSLocale.ISOCountryCodes; - NSArray *matches = [countryCodes filter:^int(NSString *code) { - NSString *callingCode = [self callingCodeFromCountryCode:code]; - - return [string hasPrefix:callingCode]; - }]; - - return [matches sortedArrayWithOptions:NSSortConcurrent usingComparator:^NSComparisonResult(NSString * obj1, NSString * obj2) { - if (obj1 == nil) { - return obj2 ? NSOrderedAscending : NSOrderedSame; - } - - if (obj2 == nil) { - return NSOrderedDescending; - } - - NSInteger d = (NSInteger)[obj1 length] - (NSInteger)[obj2 length]; - return d ? ( d < 0 ? NSOrderedAscending : NSOrderedDescending) : NSOrderedSame; - }]; -} - -+ (NSArray*)sortedCountryCodesByName:(NSArray*)countryCodesByISOCode{ - return [countryCodesByISOCode sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { - return [[self countryNameFromCountryCode:obj1] caseInsensitiveCompare:[self countryNameFromCountryCode:obj2]]; - }]; -} - -// normalizes a phone number, so parentheses and spaces are stripped -+ (NSString*) normalizePhoneNumber:(NSString *) number { - return [[[self sharedInstance] nbPhoneNumberUtil] normalizePhoneNumber:number]; -} - -// black magic -+(NSUInteger) translateCursorPosition:(NSUInteger)offset - from:(NSString*)source - to:(NSString*)target - stickingRightward:(bool)preferHigh { - require(source != nil); - require(target != nil); - require(offset <= source.length); - - NSUInteger n = source.length; - NSUInteger m = target.length; - - int moves[n+1][m+1]; - { - // Wagner-Fischer algorithm for computing edit distance, with a tweaks: - // - Tracks best moves at each location, to allow reconstruction of edit path - // - Does not allow substitutions - // - Over-values digits relative to other characters, so they're "harder" to delete or insert - const int DIGIT_VALUE = 10; - NSUInteger scores[n+1][m+1]; - moves[0][0] = 0; // (match) move up and left - scores[0][0] = 0; - for (NSUInteger i = 1; i <= n; i++) { - scores[i][0] = i; - moves[i][0] = -1; // (deletion) move left - } - for (NSUInteger j = 1; j <= m; j++) { - scores[0][j] = j; - moves[0][j] = +1; // (insertion) move up - } - - NSCharacterSet* digits = NSCharacterSet.decimalDigitCharacterSet; - for (NSUInteger i = 1; i <= n; i++) { - unichar c1 = [source characterAtIndex:i-1]; - bool isDigit1 = [digits characterIsMember:c1]; - for (NSUInteger j = 1; j <= m; j++) { - unichar c2 = [target characterAtIndex:j-1]; - bool isDigit2 = [digits characterIsMember:c2]; - if (c1 == c2) { - scores[i][j] = scores[i-1][j-1]; - moves[i][j] = 0; // move up-and-left - } else { - NSUInteger del = scores[i-1][j] + (isDigit1 ? DIGIT_VALUE : 1); - NSUInteger ins = scores[i][j-1] + (isDigit2 ? DIGIT_VALUE : 1); - bool isDel = del < ins; - scores[i][j] = isDel ? del : ins; - moves[i][j] = isDel ? -1 : +1; - } - } - } - } - - // Backtrack to find desired corresponding offset - for (NSUInteger i = n, j = m; ; i -= 1) { - if (i == offset && preferHigh) return j; // early exit - while (moves[i][j] == +1) j -= 1; // zip upward - if (i == offset) return j; // late exit - if (moves[i][j] == 0) j -= 1; - } -} - -@end diff --git a/Signal/src/util/StringUtil.h b/Signal/src/util/StringUtil.h index cb83cee49..c7b6a9d79 100644 --- a/Signal/src/util/StringUtil.h +++ b/Signal/src/util/StringUtil.h @@ -3,23 +3,23 @@ @interface NSString (Util) /// The utf-8 encoding of the string's text. --(NSData*) encodedAsUtf8; +- (NSData *)encodedAsUtf8; /// The ascii encoding of the string's text. /// Throws when the string contains non-ascii characters. --(NSData*) encodedAsAscii; --(NSRegularExpression*) toRegularExpression; --(NSString*) withMatchesAgainst:(NSRegularExpression*)regex replacedBy:(NSString*)replacement; --(bool) containsAnyMatches:(NSRegularExpression*)regex; --(NSString*) withPrefixRemovedElseNull:(NSString*)prefix; --(NSData*) decodedAsJsonIntoData; --(NSDictionary*) decodedAsJsonIntoDictionary; --(NSData*) decodedAsHexString; --(NSData*) decodedAsSpaceSeparatedHexString; --(NSData*) decodedAsBase64Data; --(NSNumber*) tryParseAsDecimalNumber; --(NSNumber*) tryParseAsUnsignedInteger; --(NSString*) removeAllCharactersIn:(NSCharacterSet*)characterSet; --(NSString*) digitsOnly; --(NSString*) withCharactersInRange:(NSRange)range replacedBy:(NSString*)substring; +- (NSData *)encodedAsAscii; +- (NSRegularExpression *)toRegularExpression; +- (NSString *)withMatchesAgainst:(NSRegularExpression *)regex replacedBy:(NSString *)replacement; +- (bool)containsAnyMatches:(NSRegularExpression *)regex; +- (NSString *)withPrefixRemovedElseNull:(NSString *)prefix; +- (NSData *)decodedAsJsonIntoData; +- (NSDictionary *)decodedAsJsonIntoDictionary; +- (NSData *)decodedAsHexString; +- (NSData *)decodedAsSpaceSeparatedHexString; +- (NSData *)decodedAsBase64Data; +- (NSNumber *)tryParseAsDecimalNumber; +- (NSNumber *)tryParseAsUnsignedInteger; +- (NSString *)removeAllCharactersIn:(NSCharacterSet *)characterSet; +- (NSString *)digitsOnly; +- (NSString *)withCharactersInRange:(NSRange)range replacedBy:(NSString *)substring; @end diff --git a/Signal/src/util/StringUtil.m b/Signal/src/util/StringUtil.m index 5159869fc..d018fe927 100644 --- a/Signal/src/util/StringUtil.m +++ b/Signal/src/util/StringUtil.m @@ -1,88 +1,91 @@ -#import "StringUtil.h" -#import "DataUtil.h" #import "Constraints.h" +#import "DataUtil.h" #import "NumberUtil.h" +#import "StringUtil.h" @implementation NSString (Util) --(NSData*) decodedAsHexString { - require(self.length % 2 == 0); +- (NSData *)decodedAsHexString { + ows_require(self.length % 2 == 0); NSUInteger n = self.length / 2; uint8_t result[n]; for (NSUInteger i = 0; i < n; i++) { unsigned int r; - NSScanner* scanner = [NSScanner scannerWithString:[self substringWithRange:NSMakeRange(i*2, 2)]]; + NSScanner *scanner = [NSScanner scannerWithString:[self substringWithRange:NSMakeRange(i * 2, 2)]]; checkOperation([scanner scanHexInt:&r]); checkOperation(r < 256); result[i] = (uint8_t)r; } return [NSData dataWithBytes:result length:sizeof(result)]; } --(NSData*) decodedAsSpaceSeparatedHexString{ - NSArray* hexComponents = [self componentsSeparatedByString:@" "]; - - NSMutableData* result = [NSMutableData new]; - for (NSString* component in hexComponents) { +- (NSData *)decodedAsSpaceSeparatedHexString { + NSArray *hexComponents = [self componentsSeparatedByString:@" "]; + + NSMutableData *result = [NSMutableData new]; + for (NSString *component in hexComponents) { unsigned int r; - NSScanner* scanner = [NSScanner scannerWithString:component]; + NSScanner *scanner = [NSScanner scannerWithString:component]; checkOperation([scanner scanHexInt:&r]); checkOperation(r < 256); [result appendData:[NSData dataWithSingleByte:(uint8_t)r]]; } - + return result; } --(NSData*) encodedAsUtf8 { - NSData* result = [self dataUsingEncoding:NSUTF8StringEncoding]; +- (NSData *)encodedAsUtf8 { + NSData *result = [self dataUsingEncoding:NSUTF8StringEncoding]; checkOperationDescribe(result != nil, @"Not a UTF8 string."); return result; } --(NSData*) encodedAsAscii { - NSData* result = [self dataUsingEncoding:NSASCIIStringEncoding]; +- (NSData *)encodedAsAscii { + NSData *result = [self dataUsingEncoding:NSASCIIStringEncoding]; checkOperationDescribe(result != nil, @"Not an ascii string."); return result; } --(NSRegularExpression*) toRegularExpression { +- (NSRegularExpression *)toRegularExpression { NSError *regexInitError = NULL; - NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:self options:0 error:®exInitError]; + NSRegularExpression *regex = + [NSRegularExpression regularExpressionWithPattern:self options:0 error:®exInitError]; checkOperation(regex != nil && regexInitError == NULL); return regex; } --(NSString*) withMatchesAgainst:(NSRegularExpression*)regex replacedBy:(NSString*)replacement { - require(regex != nil); - require(replacement != nil); - NSMutableString* m = self.mutableCopy; +- (NSString *)withMatchesAgainst:(NSRegularExpression *)regex replacedBy:(NSString *)replacement { + ows_require(regex != nil); + ows_require(replacement != nil); + NSMutableString *m = self.mutableCopy; [regex replaceMatchesInString:m options:0 range:NSMakeRange(0, m.length) withTemplate:replacement]; return m; } --(bool) containsAnyMatches:(NSRegularExpression*)regex { - require(regex != nil); +- (bool)containsAnyMatches:(NSRegularExpression *)regex { + ows_require(regex != nil); return [regex numberOfMatchesInString:self options:0 range:NSMakeRange(0, self.length)] > 0; } --(NSString*) withPrefixRemovedElseNull:(NSString*)prefix { - require(prefix != nil); - if (prefix.length > 0 && ![self hasPrefix:prefix]) return nil; +- (NSString *)withPrefixRemovedElseNull:(NSString *)prefix { + ows_require(prefix != nil); + if (prefix.length > 0 && ![self hasPrefix:prefix]) + return nil; return [self substringFromIndex:prefix.length]; } --(NSData*) decodedAsJsonIntoData { - NSError* jsonParseError = nil; +- (NSData *)decodedAsJsonIntoData { + NSError *jsonParseError = nil; id parsedJson = [NSJSONSerialization dataWithJSONObject:self.encodedAsUtf8 options:0 error:&jsonParseError]; checkOperationDescribe(jsonParseError == nil, ([NSString stringWithFormat:@"Invalid json: %@", self])); checkOperationDescribe([parsedJson isKindOfClass:NSData.class], @"Unexpected json data"); return parsedJson; } --(NSDictionary*) decodedAsJsonIntoDictionary { - NSError* jsonParseError = nil; +- (NSDictionary *)decodedAsJsonIntoDictionary { + NSError *jsonParseError = nil; id parsedJson = [NSJSONSerialization JSONObjectWithData:self.encodedAsUtf8 options:0 error:&jsonParseError]; - checkOperationDescribe(jsonParseError == nil, ([NSString stringWithFormat:@"Json parse error: %@, on json: %@", jsonParseError, self])); + checkOperationDescribe(jsonParseError == nil, + ([NSString stringWithFormat:@"Json parse error: %@, on json: %@", jsonParseError, self])); checkOperationDescribe([parsedJson isKindOfClass:NSDictionary.class], @"Unexpected json data"); return parsedJson; } --(NSData*) decodedAsBase64Data { +- (NSData *)decodedAsBase64Data { const NSUInteger BitsPerBase64Word = 6; - const NSUInteger BitsPerByte = 8; - const uint8_t Base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - + const NSUInteger BitsPerByte = 8; + const uint8_t Base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + uint8_t CharToValueMap[256]; for (NSUInteger i = 0; i < 256; i++) { CharToValueMap[i] = 255; @@ -93,28 +96,30 @@ // Determine amount of information (based on length and padding) NSUInteger paddingCount = 0; - while (paddingCount < 2 && paddingCount < self.length - 1 && [self characterAtIndex:self.length - paddingCount - 1] == '=') { + while (paddingCount < 2 && paddingCount < self.length - 1 && + [self characterAtIndex:self.length - paddingCount - 1] == '=') { paddingCount += 1; } NSUInteger base64WordCount = self.length - paddingCount; - NSUInteger bitCount = self.length*BitsPerBase64Word - paddingCount*BitsPerByte; - NSUInteger byteCount = bitCount / BitsPerByte; + NSUInteger bitCount = self.length * BitsPerBase64Word - paddingCount * BitsPerByte; + NSUInteger byteCount = bitCount / BitsPerByte; checkOperation(bitCount % BitsPerByte == 0); - + // ASCII to base 64 - NSData* asciiData = self.encodedAsAscii; + NSData *asciiData = self.encodedAsAscii; uint8_t base64Words[base64WordCount]; for (NSUInteger i = 0; i < base64WordCount; i++) { base64Words[i] = CharToValueMap[[asciiData uint8At:i]]; - require(base64Words[i] < 64); + ows_require(base64Words[i] < 64); } - + // base 64 to base 2 bool bits[bitCount]; for (NSUInteger i = 0; i < base64WordCount; i++) { for (NSUInteger j = 0; j < BitsPerBase64Word; j++) { - NSUInteger k = (i+1)*BitsPerBase64Word - 1 - j; - if (k >= bitCount) continue; // may occur due to padding + NSUInteger k = (i + 1) * BitsPerBase64Word - 1 - j; + if (k >= bitCount) + continue; // may occur due to padding bits[k] = ((base64Words[i] >> j) & 1) != 0; } } @@ -124,38 +129,40 @@ for (NSUInteger i = 0; i < byteCount; i++) { bytes[i] = 0; for (NSUInteger j = 0; j < BitsPerByte; j++) { - NSUInteger k = (i+1)*BitsPerByte - 1 - j; - if (bits[k]) bytes[i] |= 1 << j; + NSUInteger k = (i + 1) * BitsPerByte - 1 - j; + if (bits[k]) + bytes[i] |= 1 << j; } } return [NSData dataWithBytes:bytes length:sizeof(bytes)]; } --(NSNumber*) tryParseAsDecimalNumber { - NSNumberFormatter* formatter = [NSNumberFormatter new]; +- (NSNumber *)tryParseAsDecimalNumber { + NSNumberFormatter *formatter = [NSNumberFormatter new]; [formatter setNumberStyle:NSNumberFormatterDecimalStyle]; // NSNumberFormatter.numberFromString is good at noticing bad inputs, but loses precision for large values - // NSDecimalNumber.decimalNumberWithString has perfect precision, but lets bad inputs through sometimes (e.g. "88ffhih" -> 88) + // NSDecimalNumber.decimalNumberWithString has perfect precision, but lets bad inputs through sometimes (e.g. + // "88ffhih" -> 88) // We use both to get both accuracy and detection of bad inputs if ([formatter numberFromString:self] == nil) { return nil; } return [NSDecimalNumber decimalNumberWithString:self]; } --(NSNumber*) tryParseAsUnsignedInteger { - NSNumber* value = [self tryParseAsDecimalNumber]; +- (NSNumber *)tryParseAsUnsignedInteger { + NSNumber *value = [self tryParseAsDecimalNumber]; return value.hasUnsignedIntegerValue ? value : nil; } --(NSString*) removeAllCharactersIn:(NSCharacterSet*)characterSet { - require(characterSet != nil); +- (NSString *)removeAllCharactersIn:(NSCharacterSet *)characterSet { + ows_require(characterSet != nil); return [[self componentsSeparatedByCharactersInSet:characterSet] componentsJoinedByString:@""]; } --(NSString*) digitsOnly { +- (NSString *)digitsOnly { return [self removeAllCharactersIn:[NSCharacterSet.decimalDigitCharacterSet invertedSet]]; } --(NSString*) withCharactersInRange:(NSRange)range replacedBy:(NSString*)substring { - NSMutableString* result = self.mutableCopy; +- (NSString *)withCharactersInRange:(NSRange)range replacedBy:(NSString *)substring { + NSMutableString *result = self.mutableCopy; [result replaceCharactersInRange:range withString:substring]; return result; } diff --git a/Signal/src/util/TSAdapterCacheManager.h b/Signal/src/util/TSAdapterCacheManager.h index eafef6009..bc4ab366f 100644 --- a/Signal/src/util/TSAdapterCacheManager.h +++ b/Signal/src/util/TSAdapterCacheManager.h @@ -10,18 +10,18 @@ @class TSMessageAdapter; -@interface TSAdapterCacheManager : NSObject { - NSCache * messageAdaptersCache; +@interface TSAdapterCacheManager : NSObject { + NSCache *messageAdaptersCache; } @property (nonatomic, retain) NSCache *messageAdaptersCache; + (id)sharedManager; -- (void)cacheAdapter:(TSMessageAdapter*)adapter forInteractionId:(NSString*)identifier; -- (void)clearCacheEntryForInteractionId:(NSString*)identifier; -- (TSMessageAdapter*)adapterForInteractionId:(NSString*)identifier; -- (BOOL)containsCacheEntryForInteractionId:(NSString*)identifier; +- (void)cacheAdapter:(TSMessageAdapter *)adapter forInteractionId:(NSString *)identifier; +- (void)clearCacheEntryForInteractionId:(NSString *)identifier; +- (TSMessageAdapter *)adapterForInteractionId:(NSString *)identifier; +- (BOOL)containsCacheEntryForInteractionId:(NSString *)identifier; @end diff --git a/Signal/src/util/TSAdapterCacheManager.m b/Signal/src/util/TSAdapterCacheManager.m index 037ce636b..30a62e957 100644 --- a/Signal/src/util/TSAdapterCacheManager.m +++ b/Signal/src/util/TSAdapterCacheManager.m @@ -16,42 +16,38 @@ + (id)sharedManager { static TSAdapterCacheManager *sharedManager = nil; static dispatch_once_t onceToken; - + dispatch_once(&onceToken, ^{ - sharedManager = [[self alloc] init]; + sharedManager = [[self alloc] init]; }); - + return sharedManager; } - (id)init { if (self = [super init]) { - messageAdaptersCache = [[NSCache alloc]init]; + messageAdaptersCache = [[NSCache alloc] init]; } return self; } -- (void)cacheAdapter:(TSMessageAdapter*)adapter forInteractionId:(NSString*)identifier -{ +- (void)cacheAdapter:(TSMessageAdapter *)adapter forInteractionId:(NSString *)identifier { NSParameterAssert(adapter); NSParameterAssert(identifier); [messageAdaptersCache setObject:adapter forKey:identifier]; } --(void)clearCacheEntryForInteractionId:(NSString*)identifier -{ +- (void)clearCacheEntryForInteractionId:(NSString *)identifier { NSParameterAssert(identifier); [messageAdaptersCache removeObjectForKey:identifier]; } --(TSMessageAdapter*)adapterForInteractionId:(NSString*)identifier -{ +- (TSMessageAdapter *)adapterForInteractionId:(NSString *)identifier { NSParameterAssert(identifier); return [messageAdaptersCache objectForKey:identifier]; } --(BOOL)containsCacheEntryForInteractionId:(NSString*)identifier -{ +- (BOOL)containsCacheEntryForInteractionId:(NSString *)identifier { return [messageAdaptersCache objectForKey:identifier] != nil; } diff --git a/Signal/src/util/ThreadManager.h b/Signal/src/util/ThreadManager.h index a4c1d34da..d895adc45 100644 --- a/Signal/src/util/ThreadManager.h +++ b/Signal/src/util/ThreadManager.h @@ -2,11 +2,11 @@ @interface RunningThreadRunLoopPair : NSObject -@property (nonatomic,readonly) NSThread* thread; -@property (nonatomic,readonly) NSRunLoop* runLoop; +@property (nonatomic, readonly) NSThread *thread; +@property (nonatomic, readonly) NSRunLoop *runLoop; -+(RunningThreadRunLoopPair*) startNewWithThreadName:(NSString*)name; --(void) terminate; ++ (RunningThreadRunLoopPair *)startNewWithThreadName:(NSString *)name; +- (void)terminate; @end @@ -29,21 +29,24 @@ * */ -@interface ThreadManager : NSObject{ -@private RunningThreadRunLoopPair* low; -@private RunningThreadRunLoopPair* normal; -@private RunningThreadRunLoopPair* high; +@interface ThreadManager : NSObject { + @private + RunningThreadRunLoopPair *low; + @private + RunningThreadRunLoopPair *normal; + @private + RunningThreadRunLoopPair *high; } -+(NSThread*)lowLatencyThread; -+(NSRunLoop*)lowLatencyThreadRunLoop; ++ (NSThread *)lowLatencyThread; ++ (NSRunLoop *)lowLatencyThreadRunLoop; -+(NSThread*)normalLatencyThread; -+(NSRunLoop*)normalLatencyThreadRunLoop; ++ (NSThread *)normalLatencyThread; ++ (NSRunLoop *)normalLatencyThreadRunLoop; -+(NSThread*)highLatencyThread; -+(NSRunLoop*)highLatencyThreadRunLoop; ++ (NSThread *)highLatencyThread; ++ (NSRunLoop *)highLatencyThreadRunLoop; -+(void) terminate; ++ (void)terminate; @end diff --git a/Signal/src/util/ThreadManager.m b/Signal/src/util/ThreadManager.m index eafe1bd85..425f077bb 100644 --- a/Signal/src/util/ThreadManager.m +++ b/Signal/src/util/ThreadManager.m @@ -9,26 +9,27 @@ @synthesize runLoop, thread; -+(RunningThreadRunLoopPair*) startNewWithThreadName:(NSString*)name { - require(name != nil); - - RunningThreadRunLoopPair* instance = [RunningThreadRunLoopPair new]; ++ (RunningThreadRunLoopPair *)startNewWithThreadName:(NSString *)name { + ows_require(name != nil); + + RunningThreadRunLoopPair *instance = [RunningThreadRunLoopPair new]; instance->thread = [[NSThread alloc] initWithTarget:instance selector:@selector(runLoopUntilCancelled) object:nil]; [instance->thread setName:name]; [instance->thread start]; - + [Operation asyncRunAndWaitUntilDone:^{ - instance->runLoop = NSRunLoop.currentRunLoop; - } onThread:instance->thread]; - + instance->runLoop = NSRunLoop.currentRunLoop; + } + onThread:instance->thread]; + return instance; } --(void) terminate { +- (void)terminate { [thread cancel]; } --(void) runLoopUntilCancelled { - NSThread* curThread = NSThread.currentThread; - NSRunLoop* curRunLoop = NSRunLoop.currentRunLoop; +- (void)runLoopUntilCancelled { + NSThread *curThread = NSThread.currentThread; + NSRunLoop *curRunLoop = NSRunLoop.currentRunLoop; while (!curThread.isCancelled) { [curRunLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:5]]; } @@ -38,44 +39,45 @@ @implementation ThreadManager -static ThreadManager* sharedThreadManagerInternal; +static ThreadManager *sharedThreadManagerInternal; -+(ThreadManager*)sharedThreadManager { ++ (ThreadManager *)sharedThreadManager { @synchronized(self) { - if (sharedThreadManagerInternal == nil){ - sharedThreadManagerInternal = [ThreadManager new]; - sharedThreadManagerInternal->low = [RunningThreadRunLoopPair startNewWithThreadName:LOW_THREAD_NAME]; + if (sharedThreadManagerInternal == nil) { + sharedThreadManagerInternal = [ThreadManager new]; + sharedThreadManagerInternal->low = [RunningThreadRunLoopPair startNewWithThreadName:LOW_THREAD_NAME]; sharedThreadManagerInternal->normal = [RunningThreadRunLoopPair startNewWithThreadName:NORMAL_THREAD_NAME]; - sharedThreadManagerInternal->high = [RunningThreadRunLoopPair startNewWithThreadName:HIGH_THREAD_NAME]; + sharedThreadManagerInternal->high = [RunningThreadRunLoopPair startNewWithThreadName:HIGH_THREAD_NAME]; } } return sharedThreadManagerInternal; } -+(NSThread*)lowLatencyThread { ++ (NSThread *)lowLatencyThread { return self.sharedThreadManager->low.thread; } -+(NSRunLoop*)lowLatencyThreadRunLoop { ++ (NSRunLoop *)lowLatencyThreadRunLoop { return self.sharedThreadManager->low.runLoop; } -+(NSThread*)normalLatencyThread { ++ (NSThread *)normalLatencyThread { return self.sharedThreadManager->normal.thread; } -+(NSRunLoop *)normalLatencyThreadRunLoop { ++ (NSRunLoop *)normalLatencyThreadRunLoop { return self.sharedThreadManager->normal.runLoop; } -+(NSThread*)highLatencyThread { ++ (NSThread *)highLatencyThread { return self.sharedThreadManager->high.thread; } -+(NSRunLoop *)highLatencyThreadRunLoop { ++ (NSRunLoop *)highLatencyThreadRunLoop { return self.sharedThreadManager->high.runLoop; } -+(void) terminate { ++ (void)terminate { @synchronized(self) { - if (sharedThreadManagerInternal == nil) return; + if (sharedThreadManagerInternal == nil) + return; [sharedThreadManagerInternal->low terminate]; [sharedThreadManagerInternal->normal terminate]; [sharedThreadManagerInternal->high terminate]; diff --git a/Signal/src/util/TimeUtil.h b/Signal/src/util/TimeUtil.h index 039284e6e..0374822d6 100644 --- a/Signal/src/util/TimeUtil.h +++ b/Signal/src/util/TimeUtil.h @@ -1,38 +1,38 @@ #import -#import "Terminable.h" #import "CollapsingFutures.h" #import "Operation.h" +#import "Terminable.h" @interface TimeUtil : NSObject -+(NSTimeInterval) time; ++ (NSTimeInterval)time; /// Result has type Future(TypeOfValueReturnedByFunction) -+(TOCFuture*) scheduleEvaluate:(Function)function - afterDelay:(NSTimeInterval)delay - onRunLoop:(NSRunLoop*)runLoop - unlessCancelled:(TOCCancelToken*)unlessCancelledToken; ++ (TOCFuture *)scheduleEvaluate:(Function)function + afterDelay:(NSTimeInterval)delay + onRunLoop:(NSRunLoop *)runLoop + unlessCancelled:(TOCCancelToken *)unlessCancelledToken; /// Result has type Future(TypeOfValueReturnedByFunction) -+(TOCFuture*) scheduleEvaluate:(Function)function - at:(NSDate*)date - onRunLoop:(NSRunLoop*)runLoop - unlessCancelled:(TOCCancelToken*)unlessCancelledToken; ++ (TOCFuture *)scheduleEvaluate:(Function)function + at:(NSDate *)date + onRunLoop:(NSRunLoop *)runLoop + unlessCancelled:(TOCCancelToken *)unlessCancelledToken; -+(void) scheduleRun:(Action)action ++ (void)scheduleRun:(Action)action afterDelay:(NSTimeInterval)delay - onRunLoop:(NSRunLoop*)runLoop - unlessCancelled:(TOCCancelToken*)unlessCancelledToken; + onRunLoop:(NSRunLoop *)runLoop + unlessCancelled:(TOCCancelToken *)unlessCancelledToken; -+(void) scheduleRun:(Action)action - at:(NSDate*)date - onRunLoop:(NSRunLoop*)runLoop - unlessCancelled:(TOCCancelToken*)unlessCancelledToken; ++ (void)scheduleRun:(Action)action + at:(NSDate *)date + onRunLoop:(NSRunLoop *)runLoop + unlessCancelled:(TOCCancelToken *)unlessCancelledToken; -+(void) scheduleRun:(Action)action ++ (void)scheduleRun:(Action)action periodically:(NSTimeInterval)interval - onRunLoop:(NSRunLoop*)runLoop - untilCancelled:(TOCCancelToken*)untilCancelledToken + onRunLoop:(NSRunLoop *)runLoop + untilCancelled:(TOCCancelToken *)untilCancelledToken andRunImmediately:(BOOL)shouldRunImmediately; @end diff --git a/Signal/src/util/TimeUtil.m b/Signal/src/util/TimeUtil.m index 1c93c01b9..c83522708 100644 --- a/Signal/src/util/TimeUtil.m +++ b/Signal/src/util/TimeUtil.m @@ -3,42 +3,40 @@ @implementation TimeUtil -+(NSTimeInterval) time { ++ (NSTimeInterval)time { return [[NSProcessInfo processInfo] systemUptime]; } -+(TOCFuture*) scheduleEvaluate:(Function)function - afterDelay:(NSTimeInterval)delay - onRunLoop:(NSRunLoop*)runLoop - unlessCancelled:(TOCCancelToken*)unlessCancelledToken { - - require(function != NULL); - require(runLoop != nil); - require(delay >= 0); - - TOCFutureSource* result = [TOCFutureSource futureSourceUntil:unlessCancelledToken]; - Action evaler = ^{ - [result trySetResult:function()]; ++ (TOCFuture *)scheduleEvaluate:(Function)function + afterDelay:(NSTimeInterval)delay + onRunLoop:(NSRunLoop *)runLoop + unlessCancelled:(TOCCancelToken *)unlessCancelledToken { + ows_require(function != NULL); + ows_require(runLoop != nil); + ows_require(delay >= 0); + + TOCFutureSource *result = [TOCFutureSource futureSourceUntil:unlessCancelledToken]; + Action evaler = ^{ + [result trySetResult:function()]; }; [self scheduleHelper:evaler - withPeriod:delay - onRunLoop:runLoop - repeating:false - untilCancelled:unlessCancelledToken - andRunImmediately:NO]; - + withPeriod:delay + onRunLoop:runLoop + repeating:false + untilCancelled:unlessCancelledToken + andRunImmediately:NO]; + return result.future; } -+(TOCFuture*) scheduleEvaluate:(Function)function - at:(NSDate*)date - onRunLoop:(NSRunLoop*)runLoop - unlessCancelled:(TOCCancelToken*)unlessCancelledToken { - - require(function != NULL); - require(runLoop != nil); - require(date != nil); - ++ (TOCFuture *)scheduleEvaluate:(Function)function + at:(NSDate *)date + onRunLoop:(NSRunLoop *)runLoop + unlessCancelled:(TOCCancelToken *)unlessCancelledToken { + ows_require(function != NULL); + ows_require(runLoop != nil); + ows_require(date != nil); + NSTimeInterval delay = [date timeIntervalSinceNow]; return [self scheduleEvaluate:function afterDelay:MAX(0, delay) @@ -46,70 +44,64 @@ unlessCancelled:unlessCancelledToken]; } -+(void) scheduleRun:(Action)action ++ (void)scheduleRun:(Action)action afterDelay:(NSTimeInterval)delay - onRunLoop:(NSRunLoop*)runLoop - unlessCancelled:(TOCCancelToken*)unlessCancelledToken { - - require(action != NULL); - require(runLoop != nil); - require(delay >= 0); - if (delay == INFINITY) return; - + onRunLoop:(NSRunLoop *)runLoop + unlessCancelled:(TOCCancelToken *)unlessCancelledToken { + ows_require(action != NULL); + ows_require(runLoop != nil); + ows_require(delay >= 0); + if (delay == INFINITY) + return; + [self scheduleHelper:action - withPeriod:delay - onRunLoop:runLoop - repeating:false - untilCancelled:unlessCancelledToken - andRunImmediately:NO]; + withPeriod:delay + onRunLoop:runLoop + repeating:false + untilCancelled:unlessCancelledToken + andRunImmediately:NO]; } -+(void) scheduleRun:(Action)action - at:(NSDate*)date - onRunLoop:(NSRunLoop*)runLoop - unlessCancelled:(TOCCancelToken*)unlessCancelledToken { - - require(action != NULL); - require(runLoop != nil); - require(date != nil); - ++ (void)scheduleRun:(Action)action + at:(NSDate *)date + onRunLoop:(NSRunLoop *)runLoop + unlessCancelled:(TOCCancelToken *)unlessCancelledToken { + ows_require(action != NULL); + ows_require(runLoop != nil); + ows_require(date != nil); + NSTimeInterval delay = [date timeIntervalSinceNow]; - [self scheduleRun:action - afterDelay:MAX(0, delay) - onRunLoop:runLoop - unlessCancelled:unlessCancelledToken]; + [self scheduleRun:action afterDelay:MAX(0, delay) onRunLoop:runLoop unlessCancelled:unlessCancelledToken]; } -+(void) scheduleRun:(Action)action ++ (void)scheduleRun:(Action)action periodically:(NSTimeInterval)interval - onRunLoop:(NSRunLoop*)runLoop - untilCancelled:(TOCCancelToken*)untilCancelledToken - andRunImmediately:(BOOL)shouldRunImmediately{ - - require(action != NULL); - require(runLoop != nil); - require(interval > 0); - + onRunLoop:(NSRunLoop *)runLoop + untilCancelled:(TOCCancelToken *)untilCancelledToken + andRunImmediately:(BOOL)shouldRunImmediately { + ows_require(action != NULL); + ows_require(runLoop != nil); + ows_require(interval > 0); + [self scheduleHelper:action - withPeriod:interval - onRunLoop:runLoop - repeating:true - untilCancelled:untilCancelledToken - andRunImmediately:shouldRunImmediately]; + withPeriod:interval + onRunLoop:runLoop + repeating:true + untilCancelled:untilCancelledToken + andRunImmediately:shouldRunImmediately]; } -+(void) scheduleHelper:(Action)callback ++ (void)scheduleHelper:(Action)callback withPeriod:(NSTimeInterval)interval - onRunLoop:(NSRunLoop*)runLoop + onRunLoop:(NSRunLoop *)runLoop repeating:(bool)repeats - untilCancelled:(TOCCancelToken*)untilCancelledToken - andRunImmediately:(BOOL)shouldRunImmediately{ - - require(callback != NULL); - require(runLoop != nil); - require(interval >= 0); - require(!repeats || interval > 0); - + untilCancelled:(TOCCancelToken *)untilCancelledToken + andRunImmediately:(BOOL)shouldRunImmediately { + ows_require(callback != NULL); + ows_require(runLoop != nil); + ows_require(interval >= 0); + ows_require(!repeats || interval > 0); + if (untilCancelledToken.isAlreadyCancelled) { return; } @@ -117,33 +109,34 @@ callback(); return; } - if (shouldRunImmediately){ + if (shouldRunImmediately) { callback(); } - - callback = [callback copy]; + + callback = [callback copy]; __block bool hasBeenCancelled = false; - __block NSObject* cancelLock = [NSObject new]; - - Operation* callbackUnlessCancelled = [Operation operation:^{ - @synchronized(cancelLock) { - if (hasBeenCancelled) return; - callback(); - } + __block NSObject *cancelLock = [NSObject new]; + + Operation *callbackUnlessCancelled = [Operation operation:^{ + @synchronized(cancelLock) { + if (hasBeenCancelled) + return; + callback(); + } }]; - - NSTimer* timer = [NSTimer timerWithTimeInterval:interval + + NSTimer *timer = [NSTimer timerWithTimeInterval:interval target:callbackUnlessCancelled selector:[callbackUnlessCancelled selectorToRun] userInfo:nil repeats:repeats]; [runLoop addTimer:timer forMode:NSDefaultRunLoopMode]; - + [untilCancelledToken whenCancelledDo:^{ - @synchronized(cancelLock) { - hasBeenCancelled = true; - [timer invalidate]; - } + @synchronized(cancelLock) { + hasBeenCancelled = true; + [timer invalidate]; + } }]; } diff --git a/Signal/src/util/UIButton+OWS.h b/Signal/src/util/UIButton+OWS.h index b8b3f40bc..f6edf48c2 100644 --- a/Signal/src/util/UIButton+OWS.h +++ b/Signal/src/util/UIButton+OWS.h @@ -10,6 +10,6 @@ @interface UIButton (OWS) -+ (UIButton*) ows_blueButtonWithTitle:(NSString*)title; ++ (UIButton *)ows_blueButtonWithTitle:(NSString *)title; @end diff --git a/Signal/src/util/UIButton+OWS.m b/Signal/src/util/UIButton+OWS.m index 823016fa9..a6a32ffd4 100644 --- a/Signal/src/util/UIButton+OWS.m +++ b/Signal/src/util/UIButton+OWS.m @@ -7,17 +7,16 @@ // #import "UIButton+OWS.h" -#import "UIFont+OWS.h" #import "UIColor+OWS.h" +#import "UIFont+OWS.h" @implementation UIButton (OWS) -+ (UIButton *)ows_blueButtonWithTitle:(NSString *)title -{ ++ (UIButton *)ows_blueButtonWithTitle:(NSString *)title { NSDictionary *buttonTextAttributes = @{ NSFontAttributeName : [UIFont ows_regularFontWithSize:15.0f], NSForegroundColorAttributeName : [UIColor ows_materialBlueColor] }; - UIButton *button = [[UIButton alloc] init]; + UIButton *button = [[UIButton alloc] init]; NSMutableAttributedString *attributedTitle = [[NSMutableAttributedString alloc] initWithString:title]; [attributedTitle setAttributes:buttonTextAttributes range:NSMakeRange(0, [attributedTitle length])]; [button setAttributedTitle:attributedTitle forState:UIControlStateNormal]; @@ -29,9 +28,9 @@ NSMutableAttributedString *attributedTitleDisabled = [[NSMutableAttributedString alloc] initWithString:title]; [attributedTitleDisabled setAttributes:disabledAttributes range:NSMakeRange(0, [attributedTitle length])]; [button setAttributedTitle:attributedTitleDisabled forState:UIControlStateDisabled]; - + [button.titleLabel setTextAlignment:NSTextAlignmentCenter]; - + return button; } diff --git a/Signal/src/util/UIDevice+TSHardwareVersion.m b/Signal/src/util/UIDevice+TSHardwareVersion.m index e043c9fa0..0c0e858a3 100644 --- a/Signal/src/util/UIDevice+TSHardwareVersion.m +++ b/Signal/src/util/UIDevice+TSHardwareVersion.m @@ -12,114 +12,154 @@ // // -#import "UIDevice+TSHardwareVersion.h" #include +#import "UIDevice+TSHardwareVersion.h" @implementation UIDevice (TSHardwareVersion) -- (NSString *)getSysInfoByName:(char *)typeSpecifier -{ +- (NSString *)getSysInfoByName:(char *)typeSpecifier { size_t size; sysctlbyname(typeSpecifier, NULL, &size, NULL, 0); - + char *answer = malloc(size); sysctlbyname(typeSpecifier, answer, &size, NULL, 0); - - NSString *results = [NSString stringWithCString:answer encoding: NSUTF8StringEncoding]; - + + NSString *results = [NSString stringWithCString:answer encoding:NSUTF8StringEncoding]; + free(answer); return results; } -- (NSString *)modelIdentifier -{ +- (NSString *)modelIdentifier { return [self getSysInfoByName:"hw.machine"]; } -- (NSString *)modelName -{ +- (NSString *)modelName { return [self modelNameForModelIdentifier:[self modelIdentifier]]; } -- (NSString *)modelNameForModelIdentifier:(NSString *)modelIdentifier -{ +- (NSString *)modelNameForModelIdentifier:(NSString *)modelIdentifier { // iPhone http://theiphonewiki.com/wiki/IPhone - - if ([modelIdentifier isEqualToString:@"iPhone1,1"]) return @"iPhone 1G"; - if ([modelIdentifier isEqualToString:@"iPhone1,2"]) return @"iPhone 3G"; - if ([modelIdentifier isEqualToString:@"iPhone2,1"]) return @"iPhone 3GS"; - if ([modelIdentifier isEqualToString:@"iPhone3,1"]) return @"iPhone 4 (GSM)"; - if ([modelIdentifier isEqualToString:@"iPhone3,2"]) return @"iPhone 4 (GSM Rev A)"; - if ([modelIdentifier isEqualToString:@"iPhone3,3"]) return @"iPhone 4 (CDMA)"; - if ([modelIdentifier isEqualToString:@"iPhone4,1"]) return @"iPhone 4S"; - if ([modelIdentifier isEqualToString:@"iPhone5,1"]) return @"iPhone 5 (GSM)"; - if ([modelIdentifier isEqualToString:@"iPhone5,2"]) return @"iPhone 5 (Global)"; - if ([modelIdentifier isEqualToString:@"iPhone5,3"]) return @"iPhone 5c (GSM)"; - if ([modelIdentifier isEqualToString:@"iPhone5,4"]) return @"iPhone 5c (Global)"; - if ([modelIdentifier isEqualToString:@"iPhone6,1"]) return @"iPhone 5s (GSM)"; - if ([modelIdentifier isEqualToString:@"iPhone6,2"]) return @"iPhone 5s (Global)"; - if ([modelIdentifier isEqualToString:@"iPhone7,1"]) return @"iPhone 6 Plus"; - if ([modelIdentifier isEqualToString:@"iPhone7,2"]) return @"iPhone 6"; - + + if ([modelIdentifier isEqualToString:@"iPhone1,1"]) + return @"iPhone 1G"; + if ([modelIdentifier isEqualToString:@"iPhone1,2"]) + return @"iPhone 3G"; + if ([modelIdentifier isEqualToString:@"iPhone2,1"]) + return @"iPhone 3GS"; + if ([modelIdentifier isEqualToString:@"iPhone3,1"]) + return @"iPhone 4 (GSM)"; + if ([modelIdentifier isEqualToString:@"iPhone3,2"]) + return @"iPhone 4 (GSM Rev A)"; + if ([modelIdentifier isEqualToString:@"iPhone3,3"]) + return @"iPhone 4 (CDMA)"; + if ([modelIdentifier isEqualToString:@"iPhone4,1"]) + return @"iPhone 4S"; + if ([modelIdentifier isEqualToString:@"iPhone5,1"]) + return @"iPhone 5 (GSM)"; + if ([modelIdentifier isEqualToString:@"iPhone5,2"]) + return @"iPhone 5 (Global)"; + if ([modelIdentifier isEqualToString:@"iPhone5,3"]) + return @"iPhone 5c (GSM)"; + if ([modelIdentifier isEqualToString:@"iPhone5,4"]) + return @"iPhone 5c (Global)"; + if ([modelIdentifier isEqualToString:@"iPhone6,1"]) + return @"iPhone 5s (GSM)"; + if ([modelIdentifier isEqualToString:@"iPhone6,2"]) + return @"iPhone 5s (Global)"; + if ([modelIdentifier isEqualToString:@"iPhone7,1"]) + return @"iPhone 6 Plus"; + if ([modelIdentifier isEqualToString:@"iPhone7,2"]) + return @"iPhone 6"; + // iPad http://theiphonewiki.com/wiki/IPad - - if ([modelIdentifier isEqualToString:@"iPad1,1"]) return @"iPad 1G"; - if ([modelIdentifier isEqualToString:@"iPad2,1"]) return @"iPad 2 (Wi-Fi)"; - if ([modelIdentifier isEqualToString:@"iPad2,2"]) return @"iPad 2 (GSM)"; - if ([modelIdentifier isEqualToString:@"iPad2,3"]) return @"iPad 2 (CDMA)"; - if ([modelIdentifier isEqualToString:@"iPad2,4"]) return @"iPad 2 (Rev A)"; - if ([modelIdentifier isEqualToString:@"iPad3,1"]) return @"iPad 3 (Wi-Fi)"; - if ([modelIdentifier isEqualToString:@"iPad3,2"]) return @"iPad 3 (GSM)"; - if ([modelIdentifier isEqualToString:@"iPad3,3"]) return @"iPad 3 (Global)"; - if ([modelIdentifier isEqualToString:@"iPad3,4"]) return @"iPad 4 (Wi-Fi)"; - if ([modelIdentifier isEqualToString:@"iPad3,5"]) return @"iPad 4 (GSM)"; - if ([modelIdentifier isEqualToString:@"iPad3,6"]) return @"iPad 4 (Global)"; - - if ([modelIdentifier isEqualToString:@"iPad4,1"]) return @"iPad Air (Wi-Fi)"; - if ([modelIdentifier isEqualToString:@"iPad4,2"]) return @"iPad Air (Cellular)"; - if ([modelIdentifier isEqualToString:@"iPad5,3"]) return @"iPad Air 2 (Wi-Fi)"; - if ([modelIdentifier isEqualToString:@"iPad5,4"]) return @"iPad Air 2 (Cellular)"; - + + if ([modelIdentifier isEqualToString:@"iPad1,1"]) + return @"iPad 1G"; + if ([modelIdentifier isEqualToString:@"iPad2,1"]) + return @"iPad 2 (Wi-Fi)"; + if ([modelIdentifier isEqualToString:@"iPad2,2"]) + return @"iPad 2 (GSM)"; + if ([modelIdentifier isEqualToString:@"iPad2,3"]) + return @"iPad 2 (CDMA)"; + if ([modelIdentifier isEqualToString:@"iPad2,4"]) + return @"iPad 2 (Rev A)"; + if ([modelIdentifier isEqualToString:@"iPad3,1"]) + return @"iPad 3 (Wi-Fi)"; + if ([modelIdentifier isEqualToString:@"iPad3,2"]) + return @"iPad 3 (GSM)"; + if ([modelIdentifier isEqualToString:@"iPad3,3"]) + return @"iPad 3 (Global)"; + if ([modelIdentifier isEqualToString:@"iPad3,4"]) + return @"iPad 4 (Wi-Fi)"; + if ([modelIdentifier isEqualToString:@"iPad3,5"]) + return @"iPad 4 (GSM)"; + if ([modelIdentifier isEqualToString:@"iPad3,6"]) + return @"iPad 4 (Global)"; + + if ([modelIdentifier isEqualToString:@"iPad4,1"]) + return @"iPad Air (Wi-Fi)"; + if ([modelIdentifier isEqualToString:@"iPad4,2"]) + return @"iPad Air (Cellular)"; + if ([modelIdentifier isEqualToString:@"iPad5,3"]) + return @"iPad Air 2 (Wi-Fi)"; + if ([modelIdentifier isEqualToString:@"iPad5,4"]) + return @"iPad Air 2 (Cellular)"; + // iPad Mini http://theiphonewiki.com/wiki/IPad_mini - - if ([modelIdentifier isEqualToString:@"iPad2,5"]) return @"iPad mini 1G (Wi-Fi)"; - if ([modelIdentifier isEqualToString:@"iPad2,6"]) return @"iPad mini 1G (GSM)"; - if ([modelIdentifier isEqualToString:@"iPad2,7"]) return @"iPad mini 1G (Global)"; - if ([modelIdentifier isEqualToString:@"iPad4,4"]) return @"iPad mini 2G (Wi-Fi)"; - if ([modelIdentifier isEqualToString:@"iPad4,5"]) return @"iPad mini 2G (Cellular)"; - if ([modelIdentifier isEqualToString:@"iPad4,7"]) return @"iPad mini 3G (Wi-Fi)"; - if ([modelIdentifier isEqualToString:@"iPad4,8"]) return @"iPad mini 3G (Cellular)"; - if ([modelIdentifier isEqualToString:@"iPad4,9"]) return @"iPad mini 3G (Cellular)"; - + + if ([modelIdentifier isEqualToString:@"iPad2,5"]) + return @"iPad mini 1G (Wi-Fi)"; + if ([modelIdentifier isEqualToString:@"iPad2,6"]) + return @"iPad mini 1G (GSM)"; + if ([modelIdentifier isEqualToString:@"iPad2,7"]) + return @"iPad mini 1G (Global)"; + if ([modelIdentifier isEqualToString:@"iPad4,4"]) + return @"iPad mini 2G (Wi-Fi)"; + if ([modelIdentifier isEqualToString:@"iPad4,5"]) + return @"iPad mini 2G (Cellular)"; + if ([modelIdentifier isEqualToString:@"iPad4,7"]) + return @"iPad mini 3G (Wi-Fi)"; + if ([modelIdentifier isEqualToString:@"iPad4,8"]) + return @"iPad mini 3G (Cellular)"; + if ([modelIdentifier isEqualToString:@"iPad4,9"]) + return @"iPad mini 3G (Cellular)"; + // iPod http://theiphonewiki.com/wiki/IPod - - if ([modelIdentifier isEqualToString:@"iPod1,1"]) return @"iPod touch 1G"; - if ([modelIdentifier isEqualToString:@"iPod2,1"]) return @"iPod touch 2G"; - if ([modelIdentifier isEqualToString:@"iPod3,1"]) return @"iPod touch 3G"; - if ([modelIdentifier isEqualToString:@"iPod4,1"]) return @"iPod touch 4G"; - if ([modelIdentifier isEqualToString:@"iPod5,1"]) return @"iPod touch 5G"; - + + if ([modelIdentifier isEqualToString:@"iPod1,1"]) + return @"iPod touch 1G"; + if ([modelIdentifier isEqualToString:@"iPod2,1"]) + return @"iPod touch 2G"; + if ([modelIdentifier isEqualToString:@"iPod3,1"]) + return @"iPod touch 3G"; + if ([modelIdentifier isEqualToString:@"iPod4,1"]) + return @"iPod touch 4G"; + if ([modelIdentifier isEqualToString:@"iPod5,1"]) + return @"iPod touch 5G"; + // Simulator - if ([modelIdentifier hasSuffix:@"86"] || [modelIdentifier isEqual:@"x86_64"]) - { + if ([modelIdentifier hasSuffix:@"86"] || [modelIdentifier isEqual:@"x86_64"]) { BOOL smallerScreen = ([[UIScreen mainScreen] bounds].size.width < 768.0); return (smallerScreen ? @"iPhone Simulator" : @"iPad Simulator"); } - + return modelIdentifier; } -- (UIDeviceFamily) deviceFamily -{ +- (UIDeviceFamily)deviceFamily { NSString *modelIdentifier = [self modelIdentifier]; - if ([modelIdentifier hasPrefix:@"iPhone"]) return UIDeviceFamilyiPhone; - if ([modelIdentifier hasPrefix:@"iPod"]) return UIDeviceFamilyiPod; - if ([modelIdentifier hasPrefix:@"iPad"]) return UIDeviceFamilyiPad; + if ([modelIdentifier hasPrefix:@"iPhone"]) + return UIDeviceFamilyiPhone; + if ([modelIdentifier hasPrefix:@"iPod"]) + return UIDeviceFamilyiPod; + if ([modelIdentifier hasPrefix:@"iPad"]) + return UIDeviceFamilyiPad; return UIDeviceFamilyUnknown; } --(BOOL)isiPhoneVersionSixOrMore -{ - return [[self modelIdentifier] isEqualToString:@"iPhone7,1"] || [[self modelIdentifier] isEqualToString:@"iPhone7,2"]; +- (BOOL)isiPhoneVersionSixOrMore { + return + [[self modelIdentifier] isEqualToString:@"iPhone7,1"] || [[self modelIdentifier] isEqualToString:@"iPhone7,2"]; } @end diff --git a/Signal/src/util/UIFont+OWS.h b/Signal/src/util/UIFont+OWS.h index e0f16522a..1d9856781 100644 --- a/Signal/src/util/UIFont+OWS.h +++ b/Signal/src/util/UIFont+OWS.h @@ -10,14 +10,14 @@ @interface UIFont (OWS) -+ (UIFont*) ows_thinFontWithSize:(CGFloat)size; ++ (UIFont *)ows_thinFontWithSize:(CGFloat)size; -+ (UIFont*) ows_lightFontWithSize:(CGFloat)size; ++ (UIFont *)ows_lightFontWithSize:(CGFloat)size; -+ (UIFont*) ows_regularFontWithSize:(CGFloat)size; ++ (UIFont *)ows_regularFontWithSize:(CGFloat)size; -+ (UIFont*) ows_mediumFontWithSize:(CGFloat)size; ++ (UIFont *)ows_mediumFontWithSize:(CGFloat)size; -+ (UIFont*) ows_boldFontWithSize:(CGFloat)size; ++ (UIFont *)ows_boldFontWithSize:(CGFloat)size; @end diff --git a/Signal/src/util/UIFont+OWS.m b/Signal/src/util/UIFont+OWS.m index 279000e93..26119dcbc 100644 --- a/Signal/src/util/UIFont+OWS.m +++ b/Signal/src/util/UIFont+OWS.m @@ -10,29 +10,24 @@ @implementation UIFont (OWS) -+ (UIFont*) ows_thinFontWithSize:(CGFloat)size -{ ++ (UIFont *)ows_thinFontWithSize:(CGFloat)size { return [UIFont systemFontOfSize:size weight:UIFontWeightThin]; } -+ (UIFont*) ows_lightFontWithSize:(CGFloat)size -{ ++ (UIFont *)ows_lightFontWithSize:(CGFloat)size { return [UIFont systemFontOfSize:size weight:UIFontWeightLight]; } -+ (UIFont*) ows_regularFontWithSize:(CGFloat)size -{ ++ (UIFont *)ows_regularFontWithSize:(CGFloat)size { return [UIFont systemFontOfSize:size weight:UIFontWeightRegular]; } -+ (UIFont*) ows_mediumFontWithSize:(CGFloat)size -{ ++ (UIFont *)ows_mediumFontWithSize:(CGFloat)size { return [UIFont systemFontOfSize:size weight:UIFontWeightMedium]; } -+ (UIFont*) ows_boldFontWithSize:(CGFloat)size -{ ++ (UIFont *)ows_boldFontWithSize:(CGFloat)size { return [UIFont boldSystemFontOfSize:size]; } diff --git a/Signal/src/util/UIImage+normalizeImage.h b/Signal/src/util/UIImage+normalizeImage.h index 0669d71ff..67068fc50 100644 --- a/Signal/src/util/UIImage+normalizeImage.h +++ b/Signal/src/util/UIImage+normalizeImage.h @@ -13,7 +13,7 @@ - (UIImage *)normalizedImage; - (UIImage *)resizedWithQuality:(CGInterpolationQuality)quality rate:(CGFloat)rate; --(UIImage*)resizedImageToSize:(CGSize)dstSize; --(UIImage*)resizedImageToFitInSize:(CGSize)boundingSize scaleIfSmaller:(BOOL)scale; +- (UIImage *)resizedImageToSize:(CGSize)dstSize; +- (UIImage *)resizedImageToFitInSize:(CGSize)boundingSize scaleIfSmaller:(BOOL)scale; @end diff --git a/Signal/src/util/UIImage+normalizeImage.m b/Signal/src/util/UIImage+normalizeImage.m index 74593bae2..cfa31c0c4 100644 --- a/Signal/src/util/UIImage+normalizeImage.m +++ b/Signal/src/util/UIImage+normalizeImage.m @@ -11,8 +11,9 @@ @implementation UIImage (normalizeImage) - (UIImage *)normalizedImage { - if (self.imageOrientation == UIImageOrientationUp) return self; - + if (self.imageOrientation == UIImageOrientationUp) + return self; + UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale); [self drawInRect:(CGRect){{0, 0}, self.size}]; UIImage *normalizedImage = UIGraphicsGetImageFromCurrentImageContext(); @@ -23,96 +24,95 @@ - (UIImage *)resizedWithQuality:(CGInterpolationQuality)quality rate:(CGFloat)rate { UIImage *resized = nil; - CGFloat width = self.size.width * rate; - CGFloat height = self.size.height * rate; - + CGFloat width = self.size.width * rate; + CGFloat height = self.size.height * rate; + UIGraphicsBeginImageContext(CGSizeMake(width, height)); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetInterpolationQuality(context, quality); [self drawInRect:CGRectMake(0, 0, width, height)]; resized = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); - + return resized; } // Source: https://github.com/AliSoftware/UIImage-Resize --(UIImage*)resizedImageToSize:(CGSize)dstSize -{ +- (UIImage *)resizedImageToSize:(CGSize)dstSize { CGImageRef imgRef = self.CGImage; // the below values are regardless of orientation : for UIImages from Camera, width>height (landscape) - CGSize srcSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); // not equivalent to self.size (which is dependant on the imageOrientation)! - + CGSize srcSize = CGSizeMake( + CGImageGetWidth(imgRef), + CGImageGetHeight(imgRef)); // not equivalent to self.size (which is dependant on the imageOrientation)! + /* Don't resize if we already meet the required destination size. */ if (CGSizeEqualToSize(srcSize, dstSize)) { return self; } - - CGFloat scaleRatio = dstSize.width / srcSize.width; - UIImageOrientation orient = self.imageOrientation; + + CGFloat scaleRatio = dstSize.width / srcSize.width; + UIImageOrientation orient = self.imageOrientation; CGAffineTransform transform = CGAffineTransformIdentity; - switch(orient) { - - case UIImageOrientationUp: //EXIF = 1 + switch (orient) { + case UIImageOrientationUp: // EXIF = 1 transform = CGAffineTransformIdentity; break; - - case UIImageOrientationUpMirrored: //EXIF = 2 + + case UIImageOrientationUpMirrored: // EXIF = 2 transform = CGAffineTransformMakeTranslation(srcSize.width, 0.0); transform = CGAffineTransformScale(transform, -1.0, 1.0); break; - - case UIImageOrientationDown: //EXIF = 3 + + case UIImageOrientationDown: // EXIF = 3 transform = CGAffineTransformMakeTranslation(srcSize.width, srcSize.height); transform = CGAffineTransformRotate(transform, M_PI); break; - - case UIImageOrientationDownMirrored: //EXIF = 4 + + case UIImageOrientationDownMirrored: // EXIF = 4 transform = CGAffineTransformMakeTranslation(0.0, srcSize.height); transform = CGAffineTransformScale(transform, 1.0, -1.0); break; - - case UIImageOrientationLeftMirrored: //EXIF = 5 - dstSize = CGSizeMake(dstSize.height, dstSize.width); + + case UIImageOrientationLeftMirrored: // EXIF = 5 + dstSize = CGSizeMake(dstSize.height, dstSize.width); transform = CGAffineTransformMakeTranslation(srcSize.height, srcSize.width); transform = CGAffineTransformScale(transform, -1.0, 1.0); transform = CGAffineTransformRotate(transform, 3.0 * M_PI_2); break; - - case UIImageOrientationLeft: //EXIF = 6 - dstSize = CGSizeMake(dstSize.height, dstSize.width); + + case UIImageOrientationLeft: // EXIF = 6 + dstSize = CGSizeMake(dstSize.height, dstSize.width); transform = CGAffineTransformMakeTranslation(0.0, srcSize.width); transform = CGAffineTransformRotate(transform, 3.0 * M_PI_2); break; - - case UIImageOrientationRightMirrored: //EXIF = 7 - dstSize = CGSizeMake(dstSize.height, dstSize.width); + + case UIImageOrientationRightMirrored: // EXIF = 7 + dstSize = CGSizeMake(dstSize.height, dstSize.width); transform = CGAffineTransformMakeScale(-1.0, 1.0); transform = CGAffineTransformRotate(transform, M_PI_2); break; - - case UIImageOrientationRight: //EXIF = 8 - dstSize = CGSizeMake(dstSize.height, dstSize.width); + + case UIImageOrientationRight: // EXIF = 8 + dstSize = CGSizeMake(dstSize.height, dstSize.width); transform = CGAffineTransformMakeTranslation(srcSize.height, 0.0); transform = CGAffineTransformRotate(transform, M_PI_2); break; - + default: [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"]; - } - + ///////////////////////////////////////////////////////////////////////////// // The actual resize: draw the image on a new context, applying a transform matrix UIGraphicsBeginImageContextWithOptions(dstSize, NO, self.scale); - + CGContextRef context = UIGraphicsGetCurrentContext(); - + if (!context) { return nil; } - + if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) { CGContextScaleCTM(context, -scaleRatio, scaleRatio); CGContextTranslateCTM(context, -srcSize.height, 0); @@ -120,23 +120,25 @@ CGContextScaleCTM(context, scaleRatio, -scaleRatio); CGContextTranslateCTM(context, 0, -srcSize.height); } - + CGContextConcatCTM(context, transform); - - // we use srcSize (and not dstSize) as the size to specify is in user space (and we use the CTM to apply a scaleRatio) + + // we use srcSize (and not dstSize) as the size to specify is in user space (and we use the CTM to apply a + // scaleRatio) CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, srcSize.width, srcSize.height), imgRef); - UIImage* resizedImage = UIGraphicsGetImageFromCurrentImageContext(); + UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); - + return resizedImage; } --(UIImage*)resizedImageToFitInSize:(CGSize)boundingSize scaleIfSmaller:(BOOL)scale -{ +- (UIImage *)resizedImageToFitInSize:(CGSize)boundingSize scaleIfSmaller:(BOOL)scale { // get the image size (independant of imageOrientation) CGImageRef imgRef = self.CGImage; - CGSize srcSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); // not equivalent to self.size (which depends on the imageOrientation)! - + CGSize srcSize = + CGSizeMake(CGImageGetWidth(imgRef), + CGImageGetHeight(imgRef)); // not equivalent to self.size (which depends on the imageOrientation)! + // adjust boundingSize to make it independant on imageOrientation too for farther computations UIImageOrientation orient = self.imageOrientation; switch (orient) { @@ -150,26 +152,27 @@ // NOP break; } - + // Compute the target CGRect in order to keep aspect-ratio CGSize dstSize; - - if ( !scale && (srcSize.width < boundingSize.width) && (srcSize.height < boundingSize.height) ) { - //NSLog(@"Image is smaller, and we asked not to scale it in this case (scaleIfSmaller:NO)"); - dstSize = srcSize; // no resize (we could directly return 'self' here, but we draw the image anyway to take image orientation into account) - } else { + + if (!scale && (srcSize.width < boundingSize.width) && (srcSize.height < boundingSize.height)) { + // NSLog(@"Image is smaller, and we asked not to scale it in this case (scaleIfSmaller:NO)"); + dstSize = srcSize; // no resize (we could directly return 'self' here, but we draw the image anyway to take + // image orientation into account) + } else { CGFloat wRatio = boundingSize.width / srcSize.width; CGFloat hRatio = boundingSize.height / srcSize.height; - + if (wRatio < hRatio) { - //NSLog(@"Width imposed, Height scaled ; ratio = %f",wRatio); + // NSLog(@"Width imposed, Height scaled ; ratio = %f",wRatio); dstSize = CGSizeMake(boundingSize.width, floor(srcSize.height * wRatio)); } else { - //NSLog(@"Height imposed, Width scaled ; ratio = %f",hRatio); + // NSLog(@"Height imposed, Width scaled ; ratio = %f",hRatio); dstSize = CGSizeMake(floor(srcSize.width * hRatio), boundingSize.height); } } - + return [self resizedImageToSize:dstSize]; } diff --git a/Signal/src/util/UIUtil.h b/Signal/src/util/UIUtil.h index 3adf36704..ee9c948ab 100644 --- a/Signal/src/util/UIUtil.h +++ b/Signal/src/util/UIUtil.h @@ -1,10 +1,10 @@ #import +#import "MIMETypeUtil.h" #import "UIColor+OWS.h" #import "UIFont+OWS.h" -#import "UIImage+normalizeImage.h" #import "UIImage+contentTypes.h" -#import "MIMETypeUtil.h" +#import "UIImage+normalizeImage.h" typedef void (^completionBlock)(void); @@ -16,8 +16,8 @@ typedef void (^completionBlock)(void); @interface UIUtil : NSObject -+ (void)applyRoundedBorderToImageView:(UIImageView *__strong*)imageView; -+ (void)removeRoundedBorderToImageView:(UIImageView *__strong*)imageView; ++ (void)applyRoundedBorderToImageView:(UIImageView *__strong *)imageView; ++ (void)removeRoundedBorderToImageView:(UIImageView *__strong *)imageView; + (completionBlock)modalCompletionBlock; @end diff --git a/Signal/src/util/UIUtil.m b/Signal/src/util/UIUtil.m index 1cf221b6d..928275a0c 100644 --- a/Signal/src/util/UIUtil.m +++ b/Signal/src/util/UIUtil.m @@ -4,24 +4,24 @@ @implementation UIUtil -+ (void)applyRoundedBorderToImageView:(UIImageView *__strong*)imageView { ++ (void)applyRoundedBorderToImageView:(UIImageView *__strong *)imageView { [[*imageView layer] setBorderWidth:CONTACT_PICTURE_VIEW_BORDER_WIDTH]; [[*imageView layer] setBorderColor:[[UIColor clearColor] CGColor]]; - [[*imageView layer] setCornerRadius:CGRectGetWidth([*imageView frame])/2]; + [[*imageView layer] setCornerRadius:CGRectGetWidth([*imageView frame]) / 2]; [[*imageView layer] setMasksToBounds:YES]; } -+ (void)removeRoundedBorderToImageView:(UIImageView *__strong*)imageView { ++ (void)removeRoundedBorderToImageView:(UIImageView *__strong *)imageView { [[*imageView layer] setBorderWidth:0]; [[*imageView layer] setCornerRadius:0]; } + (completionBlock)modalCompletionBlock { completionBlock block = ^void() { - [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; + [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; }; - + return block; } diff --git a/Signal/src/util/Util.h b/Signal/src/util/Util.h index 5a1cfe8a5..abf0915a6 100644 --- a/Signal/src/util/Util.h +++ b/Signal/src/util/Util.h @@ -3,12 +3,12 @@ #import "Constraints.h" #import "Crc32.h" #import "DataUtil.h" +#import "DateUtil.h" #import "DictionaryUtil.h" #import "FunctionalUtil.h" -#import "Operation.h" +#import "FutureUtil.h" #import "NumberUtil.h" +#import "Operation.h" #import "StringUtil.h" #import "TimeUtil.h" -#import "FutureUtil.h" #import "UIUtil.h" -#import "DateUtil.h" diff --git a/Signal/src/util/Zid.h b/Signal/src/util/Zid.h index 95209f74c..77c091833 100644 --- a/Signal/src/util/Zid.h +++ b/Signal/src/util/Zid.h @@ -1,8 +1,12 @@ #import @interface Zid : NSObject { -@private NSData* data; + @private + NSData *data; } -+(Zid*) zidWithData:(NSData*)zidData; --(NSData*) getData; + ++ (instancetype)nullZid; ++ (Zid *)zidWithData:(NSData *)zidData; +- (NSData *)getData; + @end diff --git a/Signal/src/util/Zid.m b/Signal/src/util/Zid.m index 8fb7c9747..b1f99b6d7 100644 --- a/Signal/src/util/Zid.m +++ b/Signal/src/util/Zid.m @@ -1,15 +1,21 @@ -#import "Zid.h" #import "Constraints.h" +#import "Zid.h" @implementation Zid -+(Zid*) zidWithData:(NSData*)zidData { - require(zidData != nil); - require(zidData.length == 12); - Zid* s = [Zid new]; ++ (Zid *)zidWithData:(NSData *)zidData { + ows_require(zidData != nil); + ows_require(zidData.length == 12); + Zid *s = [Zid new]; s->data = zidData; return s; } --(NSData*) getData { + ++ (instancetype)nullZid { + NSMutableData *data = [NSMutableData dataWithLength:12]; + return [self zidWithData:data]; +} + +- (NSData *)getData { return data; } @end diff --git a/Signal/src/util/collections/CyclicalBuffer.h b/Signal/src/util/collections/CyclicalBuffer.h index c69f6ee8d..47d2a947a 100644 --- a/Signal/src/util/collections/CyclicalBuffer.h +++ b/Signal/src/util/collections/CyclicalBuffer.h @@ -3,46 +3,49 @@ /** * * Cyclic buffer is used to efficiently enqueue and dequeue blocks of data. - * - * Note that methods with 'volatile' in the name have results that can directly + * + * Note that methods with 'volatile' in the name have results that can directly * reference the queue's internal buffer, instead of returning a safe copy. - * The data returned by volatile methods must be used immediately and under the + * The data returned by volatile methods must be used immediately and under the * constraints that more data is not being enqueued at the time. - * Enqueueing data invalidates all previous volatile results, because the data they + * Enqueueing data invalidates all previous volatile results, because the data they * reference may have been overwritten. * */ @interface CyclicalBuffer : NSObject { -@private NSMutableData* buffer; -@private uint32_t readOffset; -@private uint32_t count; + @private + NSMutableData *buffer; + @private + uint32_t readOffset; + @private + uint32_t count; } /// Adds data to the buffer. The buffer will be resized if necessary. --(void) enqueueData:(NSData*)data; +- (void)enqueueData:(NSData *)data; /// The number of bytes in the buffer. --(NSUInteger) enqueuedLength; +- (NSUInteger)enqueuedLength; /// Returns a view of the given length of bytes from the buffer. /// Fails if there isn't enough enqueued data to satisfy the request. --(NSData*) peekDataWithLength:(NSUInteger)length; +- (NSData *)peekDataWithLength:(NSUInteger)length; /// Extracts the given length of bytes from the buffer. /// Fails if there isn't enough enqueued data to satisfy the request. --(NSData*) dequeueDataWithLength:(NSUInteger)length; +- (NSData *)dequeueDataWithLength:(NSUInteger)length; /// Dequeues the given length of bytes from the buffer, without returning them. /// Fails if there isn't enough enqueued data to satisfy the request. --(void) discard:(NSUInteger)length; +- (void)discard:(NSUInteger)length; /// Extracts the given length of bytes from the buffer, POTENTIALLY WITHOUT COPYING. /// Fails if there isn't enough enqueued data to satisfy the request. /// Consider result as invalid if more data is enqueued, because its contents may be overwritten. --(NSData*) dequeuePotentialyVolatileDataWithLength:(NSUInteger)length; +- (NSData *)dequeuePotentialyVolatileDataWithLength:(NSUInteger)length; /// Returns a volatile view of as much upcoming data-to-be-dequeued as possible, WITHOUT COPYING. /// Consider result as invalid if more data is enqueued, because its contents may be overwritten. --(NSData*) peekVolatileHeadOfData; +- (NSData *)peekVolatileHeadOfData; @end diff --git a/Signal/src/util/collections/CyclicalBuffer.m b/Signal/src/util/collections/CyclicalBuffer.m index a71fc8ff0..19ea1cef8 100644 --- a/Signal/src/util/collections/CyclicalBuffer.m +++ b/Signal/src/util/collections/CyclicalBuffer.m @@ -1,98 +1,105 @@ -#import "CyclicalBuffer.h" #import "Constraints.h" +#import "CyclicalBuffer.h" #import "Util.h" #define INITIAL_CAPACITY 100 // The buffer size can not be longer than an unsigned int. @implementation CyclicalBuffer --(id) init { +- (id)init { if (self = [super init]) { buffer = [NSMutableData dataWithLength:INITIAL_CAPACITY]; } return self; } --(void) enqueueData:(NSData*)data { - require(data != nil); - if(data.length == 0) return; +- (void)enqueueData:(NSData *)data { + ows_require(data != nil); + if (data.length == 0) + return; - NSUInteger incomingDataLength = data.length; - NSUInteger bufferCapacity = buffer.length; - NSUInteger writeOffset = (readOffset + count) % bufferCapacity; + NSUInteger incomingDataLength = data.length; + NSUInteger bufferCapacity = buffer.length; + NSUInteger writeOffset = (readOffset + count) % bufferCapacity; NSUInteger bufferSpaceAvailable = bufferCapacity - count; - NSUInteger writeSlack = bufferCapacity - writeOffset; - + NSUInteger writeSlack = bufferCapacity - writeOffset; + if (bufferSpaceAvailable < incomingDataLength) { - NSUInteger readSlack = bufferCapacity - readOffset; - NSUInteger newCapacity = bufferCapacity * 2 + incomingDataLength; - NSMutableData* newBuffer = [NSMutableData dataWithLength:newCapacity]; - [newBuffer replaceBytesInRange:NSMakeRange(0, MIN(readSlack, count)) withBytes:(uint8_t*)[buffer bytes] + readOffset]; + NSUInteger readSlack = bufferCapacity - readOffset; + NSUInteger newCapacity = bufferCapacity * 2 + incomingDataLength; + NSMutableData *newBuffer = [NSMutableData dataWithLength:newCapacity]; + [newBuffer replaceBytesInRange:NSMakeRange(0, MIN(readSlack, count)) + withBytes:(uint8_t *)[buffer bytes] + readOffset]; if (readSlack < count) { - [newBuffer replaceBytesInRange:NSMakeRange(readSlack, count - readSlack) withBytes:(uint8_t*)[buffer bytes]]; + [newBuffer replaceBytesInRange:NSMakeRange(readSlack, count - readSlack) + withBytes:(uint8_t *)[buffer bytes]]; } - buffer = newBuffer; - bufferCapacity = newCapacity; - readOffset = 0; - writeOffset = count; + buffer = newBuffer; + bufferCapacity = newCapacity; + readOffset = 0; + writeOffset = count; bufferSpaceAvailable = bufferCapacity - count; - writeSlack = bufferCapacity - writeOffset; + writeSlack = bufferCapacity - writeOffset; } - + assert(bufferSpaceAvailable >= incomingDataLength); - + [buffer replaceBytesInRange:NSMakeRange(writeOffset, MIN(writeSlack, incomingDataLength)) withBytes:[data bytes]]; if (incomingDataLength > writeSlack) { - [buffer replaceBytesInRange:NSMakeRange(0, incomingDataLength - writeSlack) withBytes:(uint8_t*)[data bytes] + writeSlack]; + [buffer replaceBytesInRange:NSMakeRange(0, incomingDataLength - writeSlack) + withBytes:(uint8_t *)[data bytes] + writeSlack]; } count += data.length; } --(NSUInteger) enqueuedLength { +- (NSUInteger)enqueuedLength { return count; } --(void) discard:(NSUInteger)length { - require(length <= count); +- (void)discard:(NSUInteger)length { + ows_require(length <= count); count -= length; - readOffset = (readOffset + length)%(unsigned int)buffer.length; + readOffset = (readOffset + length) % (unsigned int)buffer.length; } --(NSData*) peekDataWithLength:(NSUInteger)length{ - require(length <= count); - if (length == 0) return [NSData data]; - +- (NSData *)peekDataWithLength:(NSUInteger)length { + ows_require(length <= count); + if (length == 0) + return [NSData data]; + NSUInteger readSlack = buffer.length - readOffset; - - NSMutableData* result = [NSMutableData dataWithLength:length]; - [result replaceBytesInRange:NSMakeRange(0, MIN(readSlack, length)) withBytes:(uint8_t*)[buffer bytes] + readOffset]; + + NSMutableData *result = [NSMutableData dataWithLength:length]; + [result replaceBytesInRange:NSMakeRange(0, MIN(readSlack, length)) + withBytes:(uint8_t *)[buffer bytes] + readOffset]; if (readSlack < length) { [result replaceBytesInRange:NSMakeRange(readSlack, length - readSlack) withBytes:[buffer bytes]]; } - + return result; } --(NSData*) dequeueDataWithLength:(NSUInteger)length { - NSData* result = [self peekDataWithLength:length]; +- (NSData *)dequeueDataWithLength:(NSUInteger)length { + NSData *result = [self peekDataWithLength:length]; [self discard:length]; return result; } --(NSData*) dequeuePotentialyVolatileDataWithLength:(NSUInteger)length { +- (NSData *)dequeuePotentialyVolatileDataWithLength:(NSUInteger)length { NSUInteger readSlack = buffer.length - readOffset; - - if (readSlack < length) return [self dequeueDataWithLength:length]; - - NSData* result = [buffer subdataVolatileWithRange:NSMakeRange(readOffset, length)]; - + + if (readSlack < length) + return [self dequeueDataWithLength:length]; + + NSData *result = [buffer subdataVolatileWithRange:NSMakeRange(readOffset, length)]; + [self discard:length]; - return result; + return result; } --(NSData*) peekVolatileHeadOfData { +- (NSData *)peekVolatileHeadOfData { NSUInteger capacity = buffer.length; - NSUInteger slack = capacity - readOffset; + NSUInteger slack = capacity - readOffset; return [buffer subdataVolatileWithRange:NSMakeRange(readOffset, MIN(count, slack))]; } diff --git a/Signal/src/util/collections/PriorityQueue.h b/Signal/src/util/collections/PriorityQueue.h index 5e78c88e7..65e5d216b 100644 --- a/Signal/src/util/collections/PriorityQueue.h +++ b/Signal/src/util/collections/PriorityQueue.h @@ -2,14 +2,15 @@ #import "Constraints.h" @interface PriorityQueue : NSObject { -@private NSMutableArray* items; + @private + NSMutableArray *items; } -@property (readonly,nonatomic,copy) NSComparator comparator; +@property (readonly, nonatomic, copy) NSComparator comparator; -+(PriorityQueue*) priorityQueueAscendingWithComparator:(NSComparator)comparator; --(void)enqueue:(id)item; --(id)peek; --(id) dequeue; --(NSUInteger) count; ++ (PriorityQueue *)priorityQueueAscendingWithComparator:(NSComparator)comparator; +- (void)enqueue:(id)item; +- (id)peek; +- (id)dequeue; +- (NSUInteger)count; @end diff --git a/Signal/src/util/collections/PriorityQueue.m b/Signal/src/util/collections/PriorityQueue.m index cf788c88b..10864d9cd 100644 --- a/Signal/src/util/collections/PriorityQueue.m +++ b/Signal/src/util/collections/PriorityQueue.m @@ -2,64 +2,67 @@ @implementation PriorityQueue -+(PriorityQueue*) priorityQueueAscendingWithComparator:(NSComparator)comparator { - require(comparator != nil); - PriorityQueue* q = [PriorityQueue new]; - q->_comparator = comparator; - q->items = [NSMutableArray array]; ++ (PriorityQueue *)priorityQueueAscendingWithComparator:(NSComparator)comparator { + ows_require(comparator != nil); + PriorityQueue *q = [PriorityQueue new]; + q->_comparator = comparator; + q->items = [NSMutableArray array]; return q; } --(void)enqueue:(id)item { +- (void)enqueue:(id)item { NSUInteger curIndex = items.count; [items addObject:item]; while (curIndex > 0) { NSUInteger parentIndex = (curIndex - 1) >> 1; - id parentItem = items[parentIndex]; - if (_comparator(item, parentItem) >= 0) break; - + id parentItem = items[parentIndex]; + if (_comparator(item, parentItem) >= 0) + break; + [items setObject:parentItem atIndexedSubscript:curIndex]; [items setObject:item atIndexedSubscript:parentIndex]; curIndex = parentIndex; } } --(id)peek { +- (id)peek { requireState(items.count > 0); return items[0]; } --(id) dequeue { +- (id)dequeue { requireState(items.count > 0); id result = items[0]; - + // iteratively pull up smaller child until we hit the bottom of the heap NSUInteger endangeredIndex = items.count - 1; - id endangeredItem = items[endangeredIndex]; - NSUInteger i = 0; + id endangeredItem = items[endangeredIndex]; + NSUInteger i = 0; while (true) { - NSUInteger childIndex1 = i*2+1; - NSUInteger childIndex2 = i*2+2; - if (childIndex1 >= endangeredIndex) break; - - NSUInteger smallerChildIndex = _comparator(items[childIndex1], items[childIndex2]) <= 0 ? childIndex1 : childIndex2; - id smallerChild = items[smallerChildIndex]; + NSUInteger childIndex1 = i * 2 + 1; + NSUInteger childIndex2 = i * 2 + 2; + if (childIndex1 >= endangeredIndex) + break; + + NSUInteger smallerChildIndex = + _comparator(items[childIndex1], items[childIndex2]) <= 0 ? childIndex1 : childIndex2; + id smallerChild = items[smallerChildIndex]; bool useEndangered = _comparator(endangeredItem, smallerChild) <= 0; - if (useEndangered) break; - + if (useEndangered) + break; + [items setObject:smallerChild atIndexedSubscript:i]; i = smallerChildIndex; } - + // swap the item at the index to be removed into the new empty space at the bottom of heap [items setObject:endangeredItem atIndexedSubscript:i]; [items removeObjectAtIndex:endangeredIndex]; - + return result; } --(NSUInteger) count { +- (NSUInteger)count { return items.count; } @end - diff --git a/Signal/src/util/collections/Queue.h b/Signal/src/util/collections/Queue.h index 638596488..3cc6506b9 100644 --- a/Signal/src/util/collections/Queue.h +++ b/Signal/src/util/collections/Queue.h @@ -1,10 +1,10 @@ #import @interface Queue : NSObject --(void) enqueue:(id)item; --(id) dequeue; --(id) tryDequeue; --(id) peek; --(id) peekAt:(NSUInteger)offset; --(NSUInteger) count; +- (void)enqueue:(id)item; +- (id)dequeue; +- (id)tryDequeue; +- (id)peek; +- (id)peekAt:(NSUInteger)offset; +- (NSUInteger)count; @end diff --git a/Signal/src/util/collections/Queue.m b/Signal/src/util/collections/Queue.m index 5bbb43853..3f0c048ce 100644 --- a/Signal/src/util/collections/Queue.m +++ b/Signal/src/util/collections/Queue.m @@ -1,37 +1,39 @@ -#import "Queue.h" #import "Constraints.h" +#import "Queue.h" @implementation Queue { -@private NSMutableArray* items; + @private + NSMutableArray *items; } --(id) init { +- (id)init { if (self = [super init]) { self->items = [NSMutableArray array]; } return self; } --(void) enqueue:(id)item { +- (void)enqueue:(id)item { [items addObject:item]; } --(id) tryDequeue { - if (self.count == 0) return nil; +- (id)tryDequeue { + if (self.count == 0) + return nil; return [self dequeue]; } --(id) dequeue { +- (id)dequeue { requireState(self.count > 0); id result = items[0]; [items removeObjectAtIndex:0]; return result; } --(id) peek { +- (id)peek { requireState(self.count > 0); return items[0]; } --(id) peekAt:(NSUInteger)offset { - require(offset < self.count); +- (id)peekAt:(NSUInteger)offset { + ows_require(offset < self.count); return items[offset]; } --(NSUInteger) count { +- (NSUInteger)count { return items.count; } @end diff --git a/Signal/src/util/constraints/BadArgument.h b/Signal/src/util/constraints/BadArgument.h deleted file mode 100644 index f8ea1309a..000000000 --- a/Signal/src/util/constraints/BadArgument.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface BadArgument : NSException -+(BadArgument*) new:(NSString*)reason; -+(void)raise:(NSString *)message; -@end diff --git a/Signal/src/util/constraints/BadArgument.m b/Signal/src/util/constraints/BadArgument.m deleted file mode 100644 index c142d065a..000000000 --- a/Signal/src/util/constraints/BadArgument.m +++ /dev/null @@ -1,10 +0,0 @@ -#import "BadArgument.h" - -@implementation BadArgument -+(BadArgument*) new:(NSString*)reason { - return [[BadArgument alloc] initWithName:@"Invalid Argument" reason:reason userInfo:nil]; -} -+(void)raise:(NSString *)message { - [BadArgument raise:@"Invalid Argument" format:@"%@", message]; -} -@end diff --git a/Signal/src/util/constraints/BadState.h b/Signal/src/util/constraints/BadState.h deleted file mode 100644 index c8d22d36b..000000000 --- a/Signal/src/util/constraints/BadState.h +++ /dev/null @@ -1,5 +0,0 @@ -#import - -@interface BadState : NSException -+(void)raise:(NSString *)message; -@end diff --git a/Signal/src/util/constraints/BadState.m b/Signal/src/util/constraints/BadState.m deleted file mode 100644 index 26a0e6451..000000000 --- a/Signal/src/util/constraints/BadState.m +++ /dev/null @@ -1,7 +0,0 @@ -#import "Constraints.h" - -@implementation BadState -+(void)raise:(NSString *)message { - [BadState raise:@"Invalid State" format:@"%@", message]; -} -@end diff --git a/Signal/src/util/constraints/Constraints.h b/Signal/src/util/constraints/Constraints.h deleted file mode 100644 index 0e7059846..000000000 --- a/Signal/src/util/constraints/Constraints.h +++ /dev/null @@ -1,27 +0,0 @@ -#import "OperationFailed.h" -#import "BadArgument.h" -#import "SecurityFailure.h" -#import "BadState.h" -#import -/// 'require(X)' is used to indicate parameter-related preconditions that callers must satisfy. -/// Failure to satisfy indicates a bug in the caller. -#define require(expr) if (!(expr)){ NSString *reason = [NSString stringWithFormat:@"require %@ (in %s at line %d)", (@#expr), __FILE__, __LINE__]; DDLogError(@"%@", reason);[BadArgument raise:reason];}; - -/// 'requireState(X)' is used to indicate callee-state-related preconditions that callers must satisfy. -/// Failure to satisfy indicates a stateful bug in either the caller or the callee. -#define requireState(expr) if (!(expr)) [BadState raise:[NSString stringWithFormat:@"required state: %@ (in %s at line %d)", (@#expr), __FILE__, __LINE__]] - -/// 'checkOperation(X)' is used to throw exceptions if operations fail. -/// Failure does not indicate a bug. -/// Methods may throw these exceptions for callers to catch as a 'returned error' result. -#define checkOperation(expr) if (!(expr)){ NSString *reason = [NSString stringWithFormat:@"Operation failed. Expected: %@(in %s at line %d)", (@#expr),__FILE__,__LINE__];[OperationFailed raise:reason];} - -/// 'checkOperationDescribe(X, Desc)' is used to throw exceptions if operations fail, and describe the problem. -/// Failure does not indicate a bug. -/// Methods may throw these exceptions for callers to catch as a 'returned error' result. -#define checkOperationDescribe(expr, desc) if (!(expr)) [OperationFailed raise:[NSString stringWithFormat:@"Operation failed: %@ Expected: %@(in %s at line %d)", (desc), (@#expr),__FILE__,__LINE__]] - -/// 'checkSecurityOperation(X, Desc)' is used to throw exceptions if operations fail due to authentication or other crypto failures, and describe the problem. -/// Failure does not indicate a bug. -/// Methods may throw these exceptions for callers to catch as a 'returned error' result. -#define checkSecurityOperation(expr, desc) if (!(expr)) [SecurityFailure raise:[NSString stringWithFormat:@"Security related failure: %@ Expected: %@(in %s at line %d)", (desc), (@#expr),__FILE__,__LINE__]] diff --git a/Signal/src/util/constraints/OperationFailed.h b/Signal/src/util/constraints/OperationFailed.h deleted file mode 100644 index 2b7b272b3..000000000 --- a/Signal/src/util/constraints/OperationFailed.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface OperationFailed : NSException -+(OperationFailed*) new:(NSString*)reason; -+(void)raise:(NSString *)message; -@end diff --git a/Signal/src/util/constraints/OperationFailed.m b/Signal/src/util/constraints/OperationFailed.m deleted file mode 100644 index b1b911f38..000000000 --- a/Signal/src/util/constraints/OperationFailed.m +++ /dev/null @@ -1,10 +0,0 @@ -#import "Constraints.h" - -@implementation OperationFailed -+(OperationFailed*) new:(NSString*)reason { - return [[OperationFailed alloc] initWithName:@"Operation failed" reason:reason userInfo:nil]; -} -+(void)raise:(NSString *)message { - [OperationFailed raise:@"Operation failed" format:@"%@", message]; -} -@end diff --git a/Signal/src/util/constraints/SecurityFailure.h b/Signal/src/util/constraints/SecurityFailure.h deleted file mode 100644 index 2f4f8dfb5..000000000 --- a/Signal/src/util/constraints/SecurityFailure.h +++ /dev/null @@ -1,7 +0,0 @@ -#import -#import "OperationFailed.h" - -@interface SecurityFailure : OperationFailed -+(SecurityFailure*) new:(SecurityFailure*)reason; -+(void)raise:(NSString *)message; -@end diff --git a/Signal/src/util/constraints/SecurityFailure.m b/Signal/src/util/constraints/SecurityFailure.m deleted file mode 100644 index c004867b2..000000000 --- a/Signal/src/util/constraints/SecurityFailure.m +++ /dev/null @@ -1,10 +0,0 @@ -#import "SecurityFailure.h" - -@implementation SecurityFailure -+(SecurityFailure*) new:(NSString*)reason { - return [[SecurityFailure alloc] initWithName:@"Insecure" reason:reason userInfo:nil]; -} -+(void)raise:(NSString *)message { - [SecurityFailure raise:@"Insecure" format:@"%@", message]; -} -@end diff --git a/Signal/src/util/protocols/PreKeyBundle+jsonDict.h b/Signal/src/util/protocols/PreKeyBundle+jsonDict.h deleted file mode 100644 index 70e2c2ce8..000000000 --- a/Signal/src/util/protocols/PreKeyBundle+jsonDict.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// PreKeyBundle+jsonDict.h -// Signal -// -// Created by Frederic Jacobs on 26/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "PreKeyBundle.h" - -@interface PreKeyBundle (jsonDict) - -+ (PreKeyBundle*)preKeyBundleFromDictionary:(NSDictionary*)dictionary forDeviceNumber:(NSNumber*)number; - -@end diff --git a/Signal/src/util/protocols/PreKeyBundle+jsonDict.m b/Signal/src/util/protocols/PreKeyBundle+jsonDict.m deleted file mode 100644 index 7d0d311ae..000000000 --- a/Signal/src/util/protocols/PreKeyBundle+jsonDict.m +++ /dev/null @@ -1,97 +0,0 @@ -// -// PreKeyBundle+jsonDict.m -// Signal -// -// Created by Frederic Jacobs on 26/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "PreKeyBundle+jsonDict.h" -#import "NSData+Base64.h" - -@implementation PreKeyBundle (jsonDict) - -+ (PreKeyBundle*)preKeyBundleFromDictionary:(NSDictionary*)dictionary forDeviceNumber:(NSNumber*)number{ - PreKeyBundle *bundle = nil; - NSString *identityKeyString = [dictionary objectForKey:@"identityKey"]; - NSArray *devicesArray = [dictionary objectForKey:@"devices"]; - - if (!(identityKeyString && [devicesArray isKindOfClass:[NSArray class]])) { - DDLogError(@"Failed to get identity key or messages array from server request"); - return nil; - } - - NSData *identityKey = [NSData dataFromBase64StringNoPadding:identityKeyString]; - - for (NSDictionary *deviceDict in devicesArray) { - NSNumber *registrationIdString = [deviceDict objectForKey:@"registrationId"]; - NSNumber *deviceIdString = [deviceDict objectForKey:@"deviceId"]; - - if (!(registrationIdString && deviceIdString)) { - DDLogError(@"Failed to get the registration id and device id"); - return nil; - } - - if (![deviceIdString isEqualToNumber:number]) { - DDLogWarn(@"Got a keyid for another device"); - return nil; - } - - int registrationId = [registrationIdString intValue]; - int deviceId = [deviceIdString intValue]; - - NSDictionary *preKey = [deviceDict objectForKey:@"preKey"]; - int prekeyId; - NSData *preKeyPublic = nil; - - if (!preKey) { - prekeyId = -1; - } else{ - prekeyId = [[preKey objectForKey:@"keyId"] intValue]; - NSString *preKeyPublicString = [preKey objectForKey:@"publicKey"]; - preKeyPublic = [NSData dataFromBase64StringNoPadding:preKeyPublicString]; - } - - NSDictionary *signedPrekey = [deviceDict objectForKey:@"signedPreKey"]; - - if (![signedPrekey isKindOfClass:[NSDictionary class]]) { - DDLogError(@"Device doesn't have signed prekeys registered"); - return nil; - } - - NSNumber *signedKeyIdNumber = [signedPrekey objectForKey:@"keyId"]; - NSString *signedSignatureString = [signedPrekey objectForKey:@"signature"]; - NSString *signedPublicKeyString = [signedPrekey objectForKey:@"publicKey"]; - - - - if (!(signedKeyIdNumber && signedPublicKeyString && signedSignatureString)) { - DDLogError(@"Missing signed key material"); - return nil; - } - - NSData *signedPrekeyPublic = [NSData dataFromBase64StringNoPadding:signedPublicKeyString]; - NSData *signedPreKeySignature = [NSData dataFromBase64StringNoPadding:signedSignatureString]; - - if (!(signedPrekeyPublic && signedPreKeySignature)) { - DDLogError(@"Failed to parse signed keying material"); - return nil; - } - - int signedPreKeyId = [signedKeyIdNumber intValue]; - - bundle = [[self alloc] initWithRegistrationId:registrationId - deviceId:deviceId - preKeyId:prekeyId - preKeyPublic:preKeyPublic - signedPreKeyPublic:signedPrekeyPublic - signedPreKeyId:signedPreKeyId - signedPreKeySignature:signedPreKeySignature - identityKey:identityKey]; - - } - - return bundle; -} - -@end diff --git a/Signal/src/util/protocols/Terminable.h b/Signal/src/util/protocols/Terminable.h index 5038ba2c0..441ffa414 100644 --- a/Signal/src/util/protocols/Terminable.h +++ b/Signal/src/util/protocols/Terminable.h @@ -3,5 +3,5 @@ /// Cancels something when terminate is called. /// It must be safe to call terminate multiple times. @protocol Terminable --(void) terminate; +- (void)terminate; @end diff --git a/Signal/src/util/protocols/utilities/AnonymousTerminator.h b/Signal/src/util/protocols/utilities/AnonymousTerminator.h index a7279aef8..f353e4a65 100644 --- a/Signal/src/util/protocols/utilities/AnonymousTerminator.h +++ b/Signal/src/util/protocols/utilities/AnonymousTerminator.h @@ -1,11 +1,12 @@ #import #import "Terminable.h" -@interface AnonymousTerminator : NSObject { -@private bool alreadyCalled; +@interface AnonymousTerminator : NSObject { + @private + bool alreadyCalled; } -@property (readonly,nonatomic,copy) void (^terminateBlock)(void); +@property (readonly, nonatomic, copy) void (^terminateBlock)(void); -+(AnonymousTerminator*) cancellerWithCancel:(void (^)(void))terminate; ++ (AnonymousTerminator *)cancellerWithCancel:(void (^)(void))terminate; @end diff --git a/Signal/src/util/protocols/utilities/AnonymousTerminator.m b/Signal/src/util/protocols/utilities/AnonymousTerminator.m index 67221fe19..d0c4c1f36 100644 --- a/Signal/src/util/protocols/utilities/AnonymousTerminator.m +++ b/Signal/src/util/protocols/utilities/AnonymousTerminator.m @@ -3,16 +3,17 @@ @implementation AnonymousTerminator -+(AnonymousTerminator*) cancellerWithCancel:(void (^)(void))terminate { - require(terminate != nil); - AnonymousTerminator* c = [AnonymousTerminator new]; - c->_terminateBlock = terminate; ++ (AnonymousTerminator *)cancellerWithCancel:(void (^)(void))terminate { + ows_require(terminate != nil); + AnonymousTerminator *c = [AnonymousTerminator new]; + c->_terminateBlock = terminate; return c; } --(void) terminate { +- (void)terminate { @synchronized(self) { - if (alreadyCalled) return; + if (alreadyCalled) + return; alreadyCalled = true; } _terminateBlock(); diff --git a/Signal/src/view controllers/APNavigationController.h b/Signal/src/view controllers/APNavigationController.h index 5c03c41b4..658786180 100644 --- a/Signal/src/view controllers/APNavigationController.h +++ b/Signal/src/view controllers/APNavigationController.h @@ -10,13 +10,14 @@ @interface APNavigationController : UINavigationController -@property (nonatomic, strong) UIToolbar *dropDownToolbar; // Reference to dynamically change items based on which bar button item is clicked +@property (nonatomic, strong) + UIToolbar *dropDownToolbar; // Reference to dynamically change items based on which bar button item is clicked @property (nonatomic, strong) NSString *activeNavigationBarTitle; // Navigation bar title when the toolbar is shown -@property (nonatomic, strong) NSString *activeBarButtonTitle; // UIBarButton title when toolbar is shown +@property (nonatomic, strong) NSString *activeBarButtonTitle; // UIBarButton title when toolbar is shown @property (nonatomic, assign) BOOL isDropDownVisible; -- (void)setActiveBarButtonTitle:(NSString*)title; -- (void)setActiveNavigationBarTitle:(NSString*)title; +- (void)setActiveBarButtonTitle:(NSString *)title; +- (void)setActiveNavigationBarTitle:(NSString *)title; - (void)toggleDropDown:(id)sender; - (void)hideDropDown:(id)sender; - (void)showDropDown:(id)sender; diff --git a/Signal/src/view controllers/APNavigationController.m b/Signal/src/view controllers/APNavigationController.m index 9ad5f3d2f..4da58622e 100644 --- a/Signal/src/view controllers/APNavigationController.m +++ b/Signal/src/view controllers/APNavigationController.m @@ -17,8 +17,7 @@ @implementation APNavigationController -- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil -{ +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization @@ -26,25 +25,22 @@ return self; } -- (void)viewDidLoad -{ +- (void)viewDidLoad { [super viewDidLoad]; - // Do any additional setup after loading the view. + // Do any additional setup after loading the view. self.dropDownToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 64)]; self.dropDownToolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth; - self.dropDownToolbar.tintColor = self.navigationBar.tintColor; + self.dropDownToolbar.tintColor = self.navigationBar.tintColor; [self.navigationBar.superview insertSubview:self.dropDownToolbar belowSubview:self.navigationBar]; self.originalNavigationBarTitle = self.navigationBar.topItem.title; } -- (void)didReceiveMemoryWarning -{ +- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -- (void)toggleDropDown:(id)sender -{ +- (void)toggleDropDown:(id)sender { if (self.isDropDownVisible) { [self hideDropDown:sender]; } else { @@ -52,56 +48,56 @@ } } -- (void)hideDropDown:(id)sender -{ - if(self.isDropDownVisible){ +- (void)hideDropDown:(id)sender { + if (self.isDropDownVisible) { __weak APNavigationController *weakSelf = self; - CGRect frame = self.dropDownToolbar.frame; - frame.origin.y = CGRectGetMaxY(self.navigationBar.frame); - self.dropDownToolbar.frame = frame; - [UIView animateWithDuration:0.25 animations:^{ - CGRect finalframe = self.dropDownToolbar.frame; - finalframe.origin.y = 0.; - weakSelf.dropDownToolbar.frame = finalframe; - } completion:^(BOOL finished) { - weakSelf.isDropDownVisible = !weakSelf.isDropDownVisible; - weakSelf.dropDownToolbar.hidden = YES; - }]; + CGRect frame = self.dropDownToolbar.frame; + frame.origin.y = CGRectGetMaxY(self.navigationBar.frame); + self.dropDownToolbar.frame = frame; + [UIView animateWithDuration:0.25 + animations:^{ + CGRect finalframe = self.dropDownToolbar.frame; + finalframe.origin.y = 0.; + weakSelf.dropDownToolbar.frame = finalframe; + } + completion:^(BOOL finished) { + weakSelf.isDropDownVisible = !weakSelf.isDropDownVisible; + weakSelf.dropDownToolbar.hidden = YES; + }]; if (self.activeNavigationBarTitle) { - self.navigationBar.topItem.title = self.originalNavigationBarTitle; - } - if(sender && [sender isKindOfClass:[UIBarButtonItem class]]){ + self.navigationBar.topItem.title = self.originalNavigationBarTitle; + } + if (sender && [sender isKindOfClass:[UIBarButtonItem class]]) { [(UIBarButtonItem *)sender setTitle:self.originalBarButtonTitle]; } - } } -- (void)showDropDown:(id)sender -{ - if(!self.isDropDownVisible){ +- (void)showDropDown:(id)sender { + if (!self.isDropDownVisible) { __weak APNavigationController *weakSelf = self; - CGRect frame = self.dropDownToolbar.frame; - frame.origin.y = 0.f; - self.dropDownToolbar.hidden = NO; - self.dropDownToolbar.frame = frame; - [UIView animateWithDuration:0.25 animations:^{ - CGRect finalframe = self.dropDownToolbar.frame; - finalframe.origin.y = CGRectGetMaxY(self.navigationBar.frame); - weakSelf.dropDownToolbar.frame = finalframe; - } completion:^(BOOL finished) { - weakSelf.isDropDownVisible = !weakSelf.isDropDownVisible; - }]; + CGRect frame = self.dropDownToolbar.frame; + frame.origin.y = 0.f; + self.dropDownToolbar.hidden = NO; + self.dropDownToolbar.frame = frame; + [UIView animateWithDuration:0.25 + animations:^{ + CGRect finalframe = self.dropDownToolbar.frame; + finalframe.origin.y = CGRectGetMaxY(self.navigationBar.frame); + weakSelf.dropDownToolbar.frame = finalframe; + } + completion:^(BOOL finished) { + weakSelf.isDropDownVisible = !weakSelf.isDropDownVisible; + }]; if (self.activeNavigationBarTitle) { self.navigationBar.topItem.title = self.activeNavigationBarTitle; } - if(sender && [sender isKindOfClass:[UIBarButtonItem class]]){ + if (sender && [sender isKindOfClass:[UIBarButtonItem class]]) { self.originalBarButtonTitle = [(UIBarButtonItem *)sender title]; if (self.activeBarButtonTitle) { [(UIBarButtonItem *)sender setTitle:self.activeBarButtonTitle]; } } - } } diff --git a/Signal/src/view controllers/AboutTableViewController.m b/Signal/src/view controllers/AboutTableViewController.m index 5f14f6070..1164f9c47 100644 --- a/Signal/src/view controllers/AboutTableViewController.m +++ b/Signal/src/view controllers/AboutTableViewController.m @@ -6,8 +6,8 @@ // Copyright (c) 2015 Open Whisper Systems. All rights reserved. // -#import "AboutTableViewController.h" #import +#import "AboutTableViewController.h" #import "UIUtil.h" @interface AboutTableViewController () @@ -24,57 +24,56 @@ @implementation AboutTableViewController --(instancetype)init { +- (instancetype)init { return [super initWithStyle:UITableViewStyleGrouped]; } - (void)viewDidLoad { [super viewDidLoad]; [self.navigationController.navigationBar setTranslucent:NO]; - self.tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero]; + self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; } --(void)loadView -{ +- (void)loadView { [super loadView]; - + self.title = NSLocalizedString(@"SETTINGS_ABOUT", @""); - - //Version - self.versionCell = [[UITableViewCell alloc]init]; + + // Version + self.versionCell = [[UITableViewCell alloc] init]; self.versionCell.textLabel.text = NSLocalizedString(@"SETTINGS_VERSION", @""); - - self.versionLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 75, 30)]; - self.versionLabel.text = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]; + + self.versionLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 75, 30)]; + self.versionLabel.text = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]; self.versionLabel.textColor = [UIColor lightGrayColor]; - self.versionLabel.font = [UIFont ows_regularFontWithSize:16.0f]; + self.versionLabel.font = [UIFont ows_regularFontWithSize:16.0f]; self.versionLabel.textAlignment = NSTextAlignmentRight; - - self.versionCell.accessoryView = self.versionLabel; + + self.versionCell.accessoryView = self.versionLabel; self.versionCell.userInteractionEnabled = NO; - - //Support - self.supportCell = [[UITableViewCell alloc]init]; + + // Support + self.supportCell = [[UITableViewCell alloc] init]; self.supportCell.textLabel.text = NSLocalizedString(@"SETTINGS_SUPPORT", @""); - self.supportCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - - //Footer - self.footerView = [[UILabel alloc]init]; - self.footerView.text = NSLocalizedString(@"SETTINGS_COPYRIGHT", @""); - self.footerView.textColor = [UIColor ows_darkGrayColor]; - self.footerView.font = [UIFont ows_regularFontWithSize:15.0f]; + self.supportCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + + // Footer + self.footerView = [[UILabel alloc] init]; + self.footerView.text = NSLocalizedString(@"SETTINGS_COPYRIGHT", @""); + self.footerView.textColor = [UIColor ows_darkGrayColor]; + self.footerView.font = [UIFont ows_regularFontWithSize:15.0f]; self.footerView.numberOfLines = 2; self.footerView.textAlignment = NSTextAlignmentCenter; - - - //Twitter Invite - self.twitterInviteCell = [[UITableViewCell alloc]init]; + + + // Twitter Invite + self.twitterInviteCell = [[UITableViewCell alloc] init]; self.twitterInviteCell.textLabel.text = NSLocalizedString(@"SETTINGS_SHARE_INSTALL", @""); - - UIImageView* twitterImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"twitter_logo"]]; + + UIImageView *twitterImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"twitter_logo"]]; [twitterImageView setFrame:CGRectMake(0, 0, 34, 34)]; twitterImageView.contentMode = UIViewContentModeScaleAspectFit; - + self.twitterInviteCell.accessoryView = twitterImageView; } @@ -86,39 +85,47 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { switch (section) { - case 0: return 1; - case 1: return 1; - case 2: return 1; - default: return 0; + case 0: + return 1; + case 1: + return 1; + case 2: + return 1; + default: + return 0; } } -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section -{ +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { switch (section) { - case 0: return NSLocalizedString(@"SETTINGS_INFORMATION_HEADER", @""); - case 1: return NSLocalizedString(@"SETTINGS_INVITE_HEADER", @""); - case 2: return NSLocalizedString(@"SETTINGS_HELP_HEADER", @""); - - default: return nil; + case 0: + return NSLocalizedString(@"SETTINGS_INFORMATION_HEADER", @""); + case 1: + return NSLocalizedString(@"SETTINGS_INVITE_HEADER", @""); + case 2: + return NSLocalizedString(@"SETTINGS_HELP_HEADER", @""); + + default: + return nil; } } --(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { switch (indexPath.section) { - case 0: return self.versionCell; - case 1: return self.twitterInviteCell; - case 2: return self.supportCell; + case 0: + return self.versionCell; + case 1: + return self.twitterInviteCell; + case 2: + return self.supportCell; } - + return nil; } --(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; - + switch (indexPath.section) { case 1: [self tappedInviteTwitter]; @@ -126,7 +133,7 @@ case 2: [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://support.whispersystems.org"]]; break; - + default: break; } @@ -141,12 +148,10 @@ } - (void)tappedInviteTwitter { - - if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]) - { - SLComposeViewController *tweetSheet = [SLComposeViewController - composeViewControllerForServiceType:SLServiceTypeTwitter]; - + if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]) { + SLComposeViewController *tweetSheet = + [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter]; + NSString *tweetString = [NSString stringWithFormat:NSLocalizedString(@"SETTINGS_INVITE_TWITTER_TEXT", @"")]; [tweetSheet setInitialText:tweetString]; [tweetSheet addURL:[NSURL URLWithString:@"https://whispersystems.org/signal/install/"]]; @@ -154,7 +159,6 @@ }; [self presentViewController:tweetSheet animated:YES completion:[UIUtil modalCompletionBlock]]; } - } @end diff --git a/Signal/src/view controllers/AdvancedSettingsTableViewController.m b/Signal/src/view controllers/AdvancedSettingsTableViewController.m index 130093dfd..26b800ae9 100644 --- a/Signal/src/view controllers/AdvancedSettingsTableViewController.m +++ b/Signal/src/view controllers/AdvancedSettingsTableViewController.m @@ -9,11 +9,11 @@ #import "AdvancedSettingsTableViewController.h" #import -#import "Environment.h" #import "DebugLogger.h" -#import "TSAccountManager.h" +#import "Environment.h" #import "PreferencesUtil.h" #import "PushManager.h" +#import "TSAccountManager.h" @interface AdvancedSettingsTableViewController () @@ -23,7 +23,7 @@ @property (strong, nonatomic) UITableViewCell *submitLogCell; @property (strong, nonatomic) UITableViewCell *registerPushCell; -@property (strong, nonatomic) UISwitch * enableLogSwitch; +@property (strong, nonatomic) UISwitch *enableLogSwitch; @end @implementation AdvancedSettingsTableViewController @@ -31,13 +31,13 @@ - (void)viewDidLoad { [super viewDidLoad]; [self.navigationController.navigationBar setTranslucent:NO]; - self.tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero]; + self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; } --(instancetype)init { - self.sectionsArray = @[NSLocalizedString(@"LOGGING_SECTION", nil), - NSLocalizedString(@"PUSH_REGISTER_TITLE", nil)]; - +- (instancetype)init { + self.sectionsArray = + @[ NSLocalizedString(@"LOGGING_SECTION", nil), NSLocalizedString(@"PUSH_REGISTER_TITLE", nil) ]; + return [super initWithStyle:UITableViewStyleGrouped]; } @@ -45,28 +45,29 @@ [super didReceiveMemoryWarning]; } --(void)loadView -{ +- (void)loadView { [super loadView]; - + self.title = NSLocalizedString(@"SETTINGS_ADVANCED_TITLE", @""); - - //Enable Log - self.enableLogCell = [[UITableViewCell alloc]init]; - self.enableLogCell.textLabel.text = NSLocalizedString(@"SETTINGS_ADVANCED_DEBUGLOG", @""); + + // Enable Log + self.enableLogCell = [[UITableViewCell alloc] init]; + self.enableLogCell.textLabel.text = NSLocalizedString(@"SETTINGS_ADVANCED_DEBUGLOG", @""); self.enableLogCell.userInteractionEnabled = YES; - - self.enableLogSwitch = [[UISwitch alloc]initWithFrame:CGRectZero]; + + self.enableLogSwitch = [[UISwitch alloc] initWithFrame:CGRectZero]; [self.enableLogSwitch setOn:[Environment.preferences loggingIsEnabled]]; - [self.enableLogSwitch addTarget:self action:@selector(didToggleSwitch:) forControlEvents:UIControlEventTouchUpInside]; - + [self.enableLogSwitch addTarget:self + action:@selector(didToggleSwitch:) + forControlEvents:UIControlEventTouchUpInside]; + self.enableLogCell.accessoryView = self.enableLogSwitch; - - //Send Log - self.submitLogCell = [[UITableViewCell alloc]init]; + + // Send Log + self.submitLogCell = [[UITableViewCell alloc] init]; self.submitLogCell.textLabel.text = NSLocalizedString(@"SETTINGS_ADVANCED_SUBMIT_DEBUGLOG", @""); - - self.registerPushCell = [[UITableViewCell alloc] init]; + + self.registerPushCell = [[UITableViewCell alloc] init]; self.registerPushCell.textLabel.text = NSLocalizedString(@"REREGISTER_FOR_PUSH", nil); } @@ -87,61 +88,60 @@ } } -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section -{ +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return [self.sectionsArray objectAtIndex:(NSUInteger)section]; } --(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 0) { switch (indexPath.row) { - case 0: return self.enableLogCell; - case 1: return self.enableLogSwitch.isOn ? self.submitLogCell:self.registerPushCell; + case 0: + return self.enableLogCell; + case 1: + return self.enableLogSwitch.isOn ? self.submitLogCell : self.registerPushCell; } } else { return self.registerPushCell; } - + NSAssert(false, @"No Cell configured"); - + return nil; } --(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; - - if ([tableView cellForRowAtIndexPath:indexPath] == self.submitLogCell) - { + + if ([tableView cellForRowAtIndexPath:indexPath] == self.submitLogCell) { [Pastelog submitLogs]; } else if ([tableView cellForRowAtIndexPath:indexPath] == self.registerPushCell) { __block failedPushRegistrationBlock failure = ^(NSError *error) { - SignalAlertView(NSLocalizedString(@"PUSH_REGISTER_TITLE", nil), - NSLocalizedString(@"REGISTRATION_BODY", nil)); + SignalAlertView(NSLocalizedString(@"PUSH_REGISTER_TITLE", nil), NSLocalizedString(@"REGISTRATION_BODY", nil)); }; - - [[PushManager sharedManager] requestPushTokenWithSuccess:^(NSData *pushToken, NSData *voipToken) { - [TSAccountManager registerForPushNotifications:pushToken voipToken:voipToken success:^{ - SignalAlertView(NSLocalizedString(@"PUSH_REGISTER_TITLE", nil), - NSLocalizedString(@"PUSH_REGISTER_SUCCESS", nil)); - } failure:failure]; - } failure:failure]; + + [[PushManager sharedManager] requestPushTokenWithSuccess:^(NSString *pushToken, NSString *voipToken) { + [TSAccountManager registerForPushNotifications:pushToken + voipToken:voipToken + success:^{ + SignalAlertView(NSLocalizedString(@"PUSH_REGISTER_TITLE", nil), + NSLocalizedString(@"PUSH_REGISTER_SUCCESS", nil)); + } + failure:failure]; + } + failure:failure]; } - } #pragma mark - Actions --(void)didToggleSwitch:(UISwitch*)sender -{ +- (void)didToggleSwitch:(UISwitch *)sender { if (!sender.isOn) { - [DebugLogger.sharedInstance wipeLogs]; - [DebugLogger.sharedInstance disableFileLogging]; + [[DebugLogger sharedLogger] wipeLogs]; + [[DebugLogger sharedLogger] disableFileLogging]; } else { - [DebugLogger.sharedInstance enableFileLogging]; + [[DebugLogger sharedLogger] enableFileLogging]; } - + [Environment.preferences setLoggingEnabled:sender.isOn]; [self.tableView reloadData]; } diff --git a/Signal/src/view controllers/CodeVerificationViewController.h b/Signal/src/view controllers/CodeVerificationViewController.h index 229d1f1d2..b162c22d6 100644 --- a/Signal/src/view controllers/CodeVerificationViewController.h +++ b/Signal/src/view controllers/CodeVerificationViewController.h @@ -5,34 +5,36 @@ // Created by Dylan Bourgeois on 13/11/14. // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // -// This class allows the user to send the server their verification code and request new codes to be sent via SMS or voice. +// This class allows the user to send the server their verification code and request new codes to be sent via SMS or +// voice. // #import -@interface CodeVerificationViewController : UIViewController +@interface CodeVerificationViewController : UIViewController -@property(nonatomic, strong) IBOutlet UIImageView* signalLogo; +@property (nonatomic, strong) IBOutlet UIImageView *signalLogo; // Where the user enters the verification code they wish to document -@property(nonatomic, strong) IBOutlet UITextField* challengeTextField; +@property (nonatomic, strong) IBOutlet UITextField *challengeTextField; -@property(nonatomic, strong) NSString* formattedPhoneNumber; +@property (nonatomic, strong) NSString *formattedPhoneNumber; -@property(nonatomic,strong) IBOutlet UILabel *headerLabel; +@property (nonatomic, strong) IBOutlet UILabel *headerLabel; // User action buttons -@property(nonatomic, strong) IBOutlet UIButton* challengeButton; -@property(nonatomic, strong) IBOutlet UIButton* sendCodeViaSMSAgainButton; -@property(nonatomic, strong) IBOutlet UIButton* sendCodeViaVoiceButton; +@property (nonatomic, strong) IBOutlet UIButton *challengeButton; +@property (nonatomic, strong) IBOutlet UIButton *sendCodeViaSMSAgainButton; +@property (nonatomic, strong) IBOutlet UIButton *sendCodeViaVoiceButton; -@property(nonatomic, strong) IBOutlet UIActivityIndicatorView* submitCodeSpinner; -@property(nonatomic, strong) IBOutlet UIActivityIndicatorView* requestCodeAgainSpinner; -@property(nonatomic, strong) IBOutlet UIActivityIndicatorView* requestCallSpinner; -@property(nonatomic, strong) IBOutlet UIButton* changeNumberButton; -@property(nonatomic) IBOutlet NSLayoutConstraint *headerConstraint; +@property (nonatomic, strong) IBOutlet UIActivityIndicatorView *submitCodeSpinner; +@property (nonatomic, strong) IBOutlet UIActivityIndicatorView *requestCodeAgainSpinner; +@property (nonatomic, strong) IBOutlet UIActivityIndicatorView *requestCallSpinner; +@property (nonatomic, strong) IBOutlet UIButton *changeNumberButton; +@property (nonatomic) IBOutlet NSLayoutConstraint *headerConstraint; -// Displays phone number entered in previous step. There is a UI option (segue) which allows the user to go back and edit this. -@property (nonatomic, strong) IBOutlet UILabel* phoneNumberEntered; +// Displays phone number entered in previous step. There is a UI option (segue) which allows the user to go back and +// edit this. +@property (nonatomic, strong) IBOutlet UILabel *phoneNumberEntered; // User verifies code @@ -42,7 +44,8 @@ // User requests new code via voice phone call - (IBAction)sendCodeVoiceAction:(id)sender; -// This ensures the user doesn't keep creating server requests before the server has responded for all buttons that result in server requests --(void)enableServerActions:(BOOL)enabled; +// This ensures the user doesn't keep creating server requests before the server has responded for all buttons that +// result in server requests +- (void)enableServerActions:(BOOL)enabled; @end diff --git a/Signal/src/view controllers/CodeVerificationViewController.m b/Signal/src/view controllers/CodeVerificationViewController.m index 7e137076c..f7c8f1a3c 100644 --- a/Signal/src/view controllers/CodeVerificationViewController.m +++ b/Signal/src/view controllers/CodeVerificationViewController.m @@ -8,11 +8,13 @@ #import "CodeVerificationViewController.h" -#import "Environment.h" +#import #import "ContactsManager.h" -#import "RPServerRequestsManager.h" +#import "Environment.h" #import "LocalizableText.h" #import "PushManager.h" +#import "RPAccountManager.h" +#import "RPServerRequestsManager.h" #import "TSAccountManager.h" @interface CodeVerificationViewController () @@ -21,219 +23,233 @@ @implementation CodeVerificationViewController -- (void)viewDidLoad -{ +- (void)viewDidLoad { [super viewDidLoad]; [self initializeKeyboardHandlers]; - _headerLabel.text = NSLocalizedString(@"VERIFICATION_HEADER", @""); + _headerLabel.text = NSLocalizedString(@"VERIFICATION_HEADER", @""); _challengeTextField.placeholder = NSLocalizedString(@"VERIFICATION_CHALLENGE_DEFAULT_TEXT", @""); + _challengeTextField.delegate = self; [_challengeButton setTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SUBMIT_CODE", @"") forState:UIControlStateNormal]; - + [_sendCodeViaSMSAgainButton setTitle:NSLocalizedString(@"VERIFICATION_CHALLENGE_SUBMIT_AGAIN", @"") forState:UIControlStateNormal]; [_sendCodeViaVoiceButton - setTitle:[@" " stringByAppendingString:NSLocalizedString(@"VERIFICATION_CHALLENGE_SEND_VIAVOICE", @"")] - forState:UIControlStateNormal]; + setTitle:[@" " stringByAppendingString:NSLocalizedString(@"VERIFICATION_CHALLENGE_SEND_VIAVOICE", @"")] + forState:UIControlStateNormal]; [_changeNumberButton - setTitle:[@" " stringByAppendingString:NSLocalizedString(@"VERIFICATION_CHALLENGE_CHANGE_NUMBER", @"")] - forState:UIControlStateNormal]; + setTitle:[@" " stringByAppendingString:NSLocalizedString(@"VERIFICATION_CHALLENGE_CHANGE_NUMBER", @"")] + forState:UIControlStateNormal]; } -- (void)viewWillAppear:(BOOL)animated -{ +- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self enableServerActions:YES]; [_phoneNumberEntered setText:_formattedPhoneNumber]; [self adjustScreenSizes]; } -- (void)didReceiveMemoryWarning -{ +- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } -- (IBAction)verifyChallengeAction:(id)sender -{ +- (IBAction)verifyChallengeAction:(id)sender { [self enableServerActions:NO]; [_challengeTextField resignFirstResponder]; - - [self registerWithSuccess:^{ - [_submitCodeSpinner stopAnimating]; - - [self.navigationController dismissViewControllerAnimated:YES completion:^{ - [self passedVerification]; - }]; - } failure:^(NSError *error) { - [self showAlertForError:error]; - [self enableServerActions:YES]; - [_submitCodeSpinner stopAnimating]; - }]; -} -- (void)passedVerification { - if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined || - ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusRestricted) { - UIAlertController *controller = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"REGISTER_CONTACTS_WELCOME", nil) - message:NSLocalizedString(@"REGISTER_CONTACTS_BODY", nil) - preferredStyle:UIAlertControllerStyleAlert]; - - [controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"REGISTER_CONTACTS_CONTINUE", nil) - style:UIAlertActionStyleDefault - handler:^(UIAlertAction *action) { - [self setupContacts]; - }]]; - - [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:controller animated:YES completion:nil]; - - } else { - [self setupContacts]; + [self registerWithSuccess:^{ + [_submitCodeSpinner stopAnimating]; + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ + [TSAccountManager didRegister]; + dispatch_async(dispatch_get_main_queue(), ^{ + [self.navigationController + dismissViewControllerAnimated:YES + completion:^{ + if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined || + ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusRestricted) { + UIAlertController *controller = [UIAlertController + alertControllerWithTitle:NSLocalizedString(@"REGISTER_CONTACTS_WELCOME", nil) + message:NSLocalizedString(@"REGISTER_CONTACTS_BODY", nil) + preferredStyle:UIAlertControllerStyleAlert]; + + [controller addAction:[UIAlertAction + actionWithTitle:NSLocalizedString( + @"REGISTER_CONTACTS_CONTINUE", nil) + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *action) { + [self setupContacts]; + }]]; + + [[UIApplication sharedApplication] + .keyWindow.rootViewController presentViewController:controller + animated:YES + completion:nil]; + + } else { + [self setupContacts]; + } + + }]; + }); + }); } + failure:^(NSError *error) { + [self enableServerActions:YES]; + [_submitCodeSpinner stopAnimating]; + DDLogError(@"Error: %@", error.localizedDescription); + }]; } - (void)setupContacts { [[Environment getCurrent].contactsManager doAfterEnvironmentInitSetup]; + + [[PushManager sharedManager] validateUserNotificationSettings]; } -- (void)registerWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure -{ +- (NSString *)validationCodeFromTextField { + return [_challengeTextField.text stringByReplacingOccurrencesOfString:@"-" withString:@""]; +} + +- (TOCFuture *)pushRegistration { + TOCFutureSource *pushAndRegisterFuture = [[TOCFutureSource alloc] init]; + ; + [[PushManager sharedManager] requestPushTokenWithSuccess:^(NSString *pushToken, NSString *voipToken) { + NSMutableArray *pushTokens = [NSMutableArray arrayWithObject:pushToken]; + + if (voipToken) { + [pushTokens addObject:voipToken]; + } + + [pushAndRegisterFuture trySetResult:pushTokens]; + } + failure:^(NSError *error) { + [pushAndRegisterFuture trySetFailure:error]; + }]; + + return pushAndRegisterFuture.future; +} + +- (TOCFuture *)textSecureRegistrationFuture:(NSArray *)pushTokens { + TOCFutureSource *textsecureRegistration = [[TOCFutureSource alloc] init]; + + [TSAccountManager verifyAccountWithCode:[self validationCodeFromTextField] + pushToken:pushTokens[0] + voipToken:([pushTokens count] == 2) ? pushTokens.lastObject : nil + supportsVoice:YES + success:^{ + [textsecureRegistration trySetResult:@YES]; + } + failure:^(NSError *error) { + [textsecureRegistration trySetFailure:error]; + }]; + + return textsecureRegistration.future; +} + + +- (void)registerWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure { [_submitCodeSpinner startAnimating]; - [[RPServerRequestsManager sharedInstance] performRequest:[RPAPICall verifyVerificationCode:_challengeTextField.text] - success:^(NSURLSessionDataTask *task, id responseObject) { - - [PushManager.sharedManager registrationAndRedPhoneTokenRequestWithSuccess:^(NSData *pushToken, NSData *voipToken, NSString *signupToken) { - [TSAccountManager registerWithRedPhoneToken:signupToken - pushToken:pushToken - voipToken:voipToken - success:^{ - success(); - } - failure:^(NSError *error) { - failure(error); - }]; - } failure:^(NSError *error) { - failure(error); - [_submitCodeSpinner stopAnimating]; - }]; - } - failure:^(NSURLSessionDataTask *task, NSError *error) { - NSHTTPURLResponse *badResponse = (NSHTTPURLResponse *)task.response; - NSError *responseError = [self errorForResponse:badResponse]; - - failure(responseError); - [_submitCodeSpinner stopAnimating]; - - }]; + + __block NSArray *pushTokens; + + TOCFuture *tsRegistrationFuture = [[self pushRegistration] then:^id(NSArray *tokens) { + pushTokens = tokens; + return [self textSecureRegistrationFuture:pushTokens]; + }]; + + TOCFuture *redphoneRegistrationFuture = [tsRegistrationFuture then:^id(id value) { + return [[self getRPRegistrationToken] then:^(NSString *registrationFuture) { + return [self redphoneRegistrationWithTSToken:registrationFuture + pushToken:pushTokens[0] + voipToken:([pushTokens count] == 2) ? pushTokens.lastObject : nil]; + }]; + }]; + + [redphoneRegistrationFuture thenDo:^(id value) { + success(); + }]; + + [redphoneRegistrationFuture catchDo:^(NSError *error) { + failure(error); + }]; } -// TODO: If useful, this could possibly go in a less-specific class -- (void)showAlertForError:(NSError *)error -{ - if (error == nil) { - DDLogError(@"%@: Error condition, but no NSError to display", self.class); - return; - } else if (error.localizedDescription.length == 0) { - DDLogError(@"%@: Unable to display error because localizedDescription was not set: %@", self.class, error); - return; +- (TOCFuture *)getRPRegistrationToken { + TOCFutureSource *redPhoneTokenFuture = [[TOCFutureSource alloc] init]; + + [TSAccountManager obtainRPRegistrationToken:^(NSString *rpRegistrationToken) { + [redPhoneTokenFuture trySetResult:rpRegistrationToken]; } - - NSString *alertBody = nil; - if (error.localizedFailureReason.length > 0) { - alertBody = error.localizedFailureReason; - } else if (error.localizedRecoverySuggestion.length > 0) { - alertBody = error.localizedRecoverySuggestion; - } - - SignalAlertView(error.localizedDescription, alertBody); + failure:^(NSError *error) { + [redPhoneTokenFuture trySetFailure:error]; + }]; + + return redPhoneTokenFuture.future; } +- (TOCFuture *)redphoneRegistrationWithTSToken:(NSString *)tsToken + pushToken:(NSString *)pushToken + voipToken:(NSString *)voipToken { + TOCFutureSource *rpRegistration = [[TOCFutureSource alloc] init]; -- (NSError *)errorForResponse:(NSHTTPURLResponse *)badResponse -{ - NSString *description = NSLocalizedString(@"REGISTRATION_ERROR", @""); - NSString *failureReason = nil; - TSRegistrationFailure failureType; - - if (badResponse.statusCode == 401 || badResponse.statusCode == 403) { - failureReason = REGISTER_CHALLENGE_ALERT_VIEW_BODY; - failureType = kTSRegistrationFailureAuthentication; - } else if (badResponse.statusCode == 413) { - failureReason = NSLocalizedString(@"REGISTER_RATE_LIMITING_BODY", @""); - failureType = kTSRegistrationFailureRateLimit; - } else { - failureReason = [NSString - stringWithFormat:@"%@ %lu", NSLocalizedString(@"SERVER_CODE", @""), (unsigned long)badResponse.statusCode]; - failureType = kTSRegistrationFailureNetwork; - } - - NSDictionary *userInfo = - @{NSLocalizedDescriptionKey : description, NSLocalizedFailureReasonErrorKey : failureReason}; - NSError *error = [NSError errorWithDomain:TSRegistrationErrorDomain code:failureType userInfo:userInfo]; - - return error; + [RPAccountManager registrationWithTsToken:tsToken + pushToken:pushToken + voipToken:voipToken + success:^{ + [rpRegistration trySetResult:@YES]; + } + failure:^(NSError *error) { + [rpRegistration trySetFailure:error]; + }]; + + return rpRegistration.future; } #pragma mark - Send codes again -- (IBAction)sendCodeSMSAction:(id)sender -{ +- (IBAction)sendCodeSMSAction:(id)sender { [self enableServerActions:NO]; - + [_requestCodeAgainSpinner startAnimating]; - [[RPServerRequestsManager sharedInstance] performRequest:[RPAPICall requestVerificationCode] - success:^(NSURLSessionDataTask *task, id responseObject) { - [self enableServerActions:YES]; - [_requestCodeAgainSpinner stopAnimating]; - - } - failure:^(NSURLSessionDataTask *task, NSError *error) { - - DDLogError(@"Registration failed with information %@", error.description); - - UIAlertView *registrationErrorAV = [[UIAlertView alloc] initWithTitle:REGISTER_ERROR_ALERT_VIEW_TITLE - message:REGISTER_ERROR_ALERT_VIEW_BODY - delegate:nil - cancelButtonTitle:REGISTER_ERROR_ALERT_VIEW_DISMISS - otherButtonTitles:nil, nil]; - - [registrationErrorAV show]; - - [self enableServerActions:YES]; - [_requestCodeAgainSpinner stopAnimating]; - }]; + [TSAccountManager rerequestSMSWithSuccess:^{ + [self enableServerActions:YES]; + [_requestCodeAgainSpinner stopAnimating]; + } + failure:^(NSError *error) { + [self showRegistrationErrorMessage:error]; + [self enableServerActions:YES]; + [_requestCodeAgainSpinner stopAnimating]; + }]; } -- (IBAction)sendCodeVoiceAction:(id)sender -{ +- (IBAction)sendCodeVoiceAction:(id)sender { [self enableServerActions:NO]; - + [_requestCallSpinner startAnimating]; - [[RPServerRequestsManager sharedInstance] performRequest:[RPAPICall requestVerificationCodeWithVoice] - success:^(NSURLSessionDataTask *task, id responseObject) { - - [self enableServerActions:YES]; - [_requestCallSpinner stopAnimating]; - - } - failure:^(NSURLSessionDataTask *task, NSError *error) { - - DDLogError(@"Registration failed with information %@", error.description); - - UIAlertView *registrationErrorAV = [[UIAlertView alloc] initWithTitle:REGISTER_ERROR_ALERT_VIEW_TITLE - message:REGISTER_ERROR_ALERT_VIEW_BODY - delegate:nil - cancelButtonTitle:REGISTER_ERROR_ALERT_VIEW_DISMISS - otherButtonTitles:nil, nil]; - - [registrationErrorAV show]; - [self enableServerActions:YES]; - [_requestCallSpinner stopAnimating]; - }]; + [TSAccountManager rerequestVoiceWithSuccess:^{ + [self enableServerActions:YES]; + [_requestCallSpinner stopAnimating]; + } + failure:^(NSError *error) { + [self showRegistrationErrorMessage:error]; + [self enableServerActions:YES]; + [_requestCallSpinner stopAnimating]; + }]; } -- (void)enableServerActions:(BOOL)enabled -{ +- (void)showRegistrationErrorMessage:(NSError *)registrationError { + UIAlertView *registrationErrorAV = [[UIAlertView alloc] initWithTitle:registrationError.localizedDescription + message:registrationError.localizedRecoverySuggestion + delegate:nil + cancelButtonTitle:REGISTER_ERROR_ALERT_VIEW_DISMISS + otherButtonTitles:nil, nil]; + + [registrationErrorAV show]; +} + +- (void)enableServerActions:(BOOL)enabled { [_challengeButton setEnabled:enabled]; [_sendCodeViaSMSAgainButton setEnabled:enabled]; [_sendCodeViaVoiceButton setEnabled:enabled]; @@ -242,30 +258,54 @@ #pragma mark - Keyboard notifications -- (void)initializeKeyboardHandlers -{ +- (void)initializeKeyboardHandlers { UITapGestureRecognizer *outsideTabRecognizer = - [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)]; + [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)]; [self.view addGestureRecognizer:outsideTabRecognizer]; } -- (void)dismissKeyboardFromAppropriateSubView -{ +- (void)dismissKeyboardFromAppropriateSubView { [self.view endEditing:NO]; } -- (void)adjustScreenSizes -{ +- (BOOL)textField:(UITextField *)textField + shouldChangeCharactersInRange:(NSRange)range + replacementString:(NSString *)string { + if (range.location == 7) { + return NO; + } + + if (range.length == 0 && + ![[NSCharacterSet decimalDigitCharacterSet] characterIsMember:[string characterAtIndex:0]]) { + return NO; + } + + if (range.length == 0 && range.location == 3) { + textField.text = [NSString stringWithFormat:@"%@-%@", textField.text, string]; + return NO; + } + + if (range.length == 1 && range.location == 4) { + range.location--; + range.length = 2; + textField.text = [textField.text stringByReplacingCharactersInRange:range withString:@""]; + return NO; + } + + return YES; +} + +- (void)adjustScreenSizes { CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height; CGFloat blueHeaderHeight; - + if (screenHeight < 667) { self.signalLogo.hidden = YES; - blueHeaderHeight = screenHeight - 400; + blueHeaderHeight = screenHeight - 400; } else { blueHeaderHeight = screenHeight - 410; } - + _headerConstraint.constant = blueHeaderHeight; } diff --git a/Signal/src/view controllers/CountryCodeViewController.h b/Signal/src/view controllers/CountryCodeViewController.h index 49a807462..1cf0d26a4 100644 --- a/Signal/src/view controllers/CountryCodeViewController.h +++ b/Signal/src/view controllers/CountryCodeViewController.h @@ -12,12 +12,13 @@ @end -@interface CountryCodeViewController : UIViewController +@interface CountryCodeViewController + : UIViewController @property (nonatomic, strong) IBOutlet UITableView *countryCodeTableView; @property (nonatomic, strong) IBOutlet UISearchBar *searchBar; @property (nonatomic, assign) id delegate; -@property (nonatomic, strong) NSString* callingCodeSelected; -@property (nonatomic, strong) NSString* countryNameSelected; +@property (nonatomic, strong) NSString *callingCodeSelected; +@property (nonatomic, strong) NSString *countryNameSelected; @end diff --git a/Signal/src/view controllers/CountryCodeViewController.m b/Signal/src/view controllers/CountryCodeViewController.m index 30e126db8..05b016e19 100644 --- a/Signal/src/view controllers/CountryCodeViewController.m +++ b/Signal/src/view controllers/CountryCodeViewController.m @@ -1,9 +1,9 @@ -#import "CountryCodeViewController.h" #import "CountryCodeTableViewCell.h" +#import "CountryCodeViewController.h" #import "PhoneNumberUtil.h" -static NSString *const CONTRY_CODE_TABLE_CELL_IDENTIFIER = @"CountryCodeTableViewCell"; +static NSString *const CONTRY_CODE_TABLE_CELL_IDENTIFIER = @"CountryCodeTableViewCell"; static NSString *const kUnwindToCountryCodeWasSelectedSegue = @"UnwindToCountryCodeWasSelectedSegue"; @@ -19,7 +19,7 @@ static NSString *const kUnwindToCountryCodeWasSelectedSegue = @"UnwindToCountryC [super viewDidLoad]; [self.navigationController.navigationBar setTranslucent:NO]; _countryCodes = [PhoneNumberUtil countryCodesForSearchTerm:nil]; - self.title = NSLocalizedString(@"COUNTRYCODE_SELECT_TITLE", @""); + self.title = NSLocalizedString(@"COUNTRYCODE_SELECT_TITLE", @""); } #pragma mark - UITableViewDelegate @@ -34,24 +34,24 @@ static NSString *const kUnwindToCountryCodeWasSelectedSegue = @"UnwindToCountryC cell = [[CountryCodeTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CONTRY_CODE_TABLE_CELL_IDENTIFIER]; } - + NSString *countryCode = _countryCodes[(NSUInteger)indexPath.row]; - + [cell configureWithCountryCode:[PhoneNumberUtil callingCodeFromCountryCode:countryCode] - andCountryName:[PhoneNumberUtil countryNameFromCountryCode:countryCode]]; - + andCountryName:[PhoneNumberUtil countryNameFromCountryCode:countryCode]]; + return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSString *countryCode = _countryCodes[(NSUInteger)indexPath.row]; - _callingCodeSelected = [PhoneNumberUtil callingCodeFromCountryCode:countryCode]; - _countryNameSelected = [PhoneNumberUtil countryNameFromCountryCode:countryCode]; + _callingCodeSelected = [PhoneNumberUtil callingCodeFromCountryCode:countryCode]; + _countryNameSelected = [PhoneNumberUtil countryNameFromCountryCode:countryCode]; [self.searchBar resignFirstResponder]; [self performSegueWithIdentifier:kUnwindToCountryCodeWasSelectedSegue sender:self]; } --(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 44.0f; } @@ -62,8 +62,7 @@ static NSString *const kUnwindToCountryCodeWasSelectedSegue = @"UnwindToCountryC [self.countryCodeTableView reloadData]; } --(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope -{ +- (void)filterContentForSearchText:(NSString *)searchText scope:(NSString *)scope { _countryCodes = [PhoneNumberUtil countryCodesForSearchTerm:searchText]; } diff --git a/Signal/src/view controllers/FingerprintViewController.h b/Signal/src/view controllers/FingerprintViewController.h index bdc53970f..f17e659ab 100644 --- a/Signal/src/view controllers/FingerprintViewController.h +++ b/Signal/src/view controllers/FingerprintViewController.h @@ -7,44 +7,45 @@ // #import -#import "TSContactThread.h" #import "MessagesViewController.h" +#import "TSContactThread.h" @interface FingerprintViewController : UIViewController -- (void)configWithThread:(TSThread*)thread; +- (void)configWithThread:(TSThread *)thread; -@property (nonatomic, strong) IBOutlet UILabel *presentationLabel; +@property (nonatomic, strong) IBOutlet UILabel *presentationLabel; -@property (nonatomic, strong) IBOutlet UIView *myFingerprintView; -@property (nonatomic, strong) IBOutlet UIView *theirFingerprintView; +@property (nonatomic, strong) IBOutlet UIView *myFingerprintView; +@property (nonatomic, strong) IBOutlet UIView *theirFingerprintView; @property (nonatomic, strong) IBOutlet UIImageView *contactImageView; -@property (nonatomic, strong) IBOutlet UILabel *contactFingerprintTitleLabel; -@property (nonatomic, strong) IBOutlet UILabel *contactFingerprintLabel; +@property (nonatomic, strong) IBOutlet UILabel *contactFingerprintTitleLabel; +@property (nonatomic, strong) IBOutlet UILabel *contactFingerprintLabel; @property (nonatomic, strong) IBOutlet UIImageView *userImageView; -@property (nonatomic, strong) IBOutlet UILabel *userFingerprintTitleLabel; -@property (nonatomic, strong) IBOutlet UILabel *userFingerprintLabel; +@property (nonatomic, strong) IBOutlet UILabel *userFingerprintTitleLabel; +@property (nonatomic, strong) IBOutlet UILabel *userFingerprintLabel; -@property (nonatomic, strong) IBOutlet UILabel *infoMyFingerprint; -@property (nonatomic, strong) IBOutlet UILabel *infoTheirFingerprint; +@property (nonatomic, strong) IBOutlet UILabel *infoMyFingerprint; +@property (nonatomic, strong) IBOutlet UILabel *infoTheirFingerprint; @property (nonatomic, strong) IBOutlet UIImageView *infoArrowTop; @property (nonatomic, strong) IBOutlet UIImageView *infoArrowBottom; -@property (nonatomic, strong) IBOutlet UIButton *closeButton; -@property (nonatomic, strong) IBOutlet UIView *myFPBorderView; - +@property (nonatomic, strong) IBOutlet UIButton *closeButton; +@property (nonatomic, strong) IBOutlet UIView *myFPBorderView; // returns my public identity key as NSData --(NSData*) getMyPublicIdentityKey; +- (NSData *)getMyPublicIdentityKey; // returns recipient's public identity key as NSData --(NSData*) getTheirPublicIdentityKey; +- (NSData *)getTheirPublicIdentityKey; -// This is called when the recipient's public key is verified. Later can be used to mark as such if we want a step above TOFU in UX. +// This is called when the recipient's public key is verified. Later can be used to mark as such if we want a step above +// TOFU in UX. - (IBAction)unwindToIdentityKeyWasVerified:(UIStoryboardSegue *)segue; -// Just a cancelation of the user's request to verify reciepient fingerprint or have their fingerprint verified by recipient +// Just a cancelation of the user's request to verify reciepient fingerprint or have their fingerprint verified by +// recipient - (IBAction)unwindIdentityVerificationCancel:(UIStoryboardSegue *)segue; @end diff --git a/Signal/src/view controllers/FingerprintViewController.m b/Signal/src/view controllers/FingerprintViewController.m index 38c80893b..70104fffb 100644 --- a/Signal/src/view controllers/FingerprintViewController.m +++ b/Signal/src/view controllers/FingerprintViewController.m @@ -8,8 +8,8 @@ #import "FingerprintViewController.h" -#import #import <25519/Curve25519.h> +#import #import "DJWActionSheet+OWS.h" #import "PresentIdentityQRCodeViewController.h" #import "ScanIdentityBarcodeViewController.h" @@ -23,46 +23,48 @@ @property (nonatomic) BOOL isPresentingDialog; @end -static NSString* const kPresentIdentityQRCodeViewSegue = @"PresentIdentityQRCodeViewSegue"; -static NSString* const kScanIdentityBarcodeViewSegue = @"ScanIdentityBarcodeViewSegue"; +static NSString *const kPresentIdentityQRCodeViewSegue = @"PresentIdentityQRCodeViewSegue"; +static NSString *const kScanIdentityBarcodeViewSegue = @"ScanIdentityBarcodeViewSegue"; @implementation FingerprintViewController -- (void)configWithThread:(TSThread *)thread{ - self.thread = (TSContactThread*)thread; +- (void)configWithThread:(TSThread *)thread { + self.thread = (TSContactThread *)thread; } - (void)viewDidLoad { [super viewDidLoad]; [self.view setAlpha:0]; - - UILongPressGestureRecognizer *longpressToResetSession = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(shredAndDelete:)]; + + UILongPressGestureRecognizer *longpressToResetSession = + [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(shredAndDelete:)]; longpressToResetSession.minimumPressDuration = 1.0; [self.view addGestureRecognizer:longpressToResetSession]; - _infoTheirFingerprint.text = NSLocalizedString(@"FINGERPRINT_INFO_THEIRS", @""); - _infoMyFingerprint.text = NSLocalizedString(@"FINGERPRINT_INFO_YOURS", @""); - _presentationLabel.text = NSLocalizedString(@"FINGERPRINT_INFO_ABOUT", @""); - _userFingerprintTitleLabel.text = NSLocalizedString(@"FINGERPRINT_YOURS",@""); - + _infoTheirFingerprint.text = NSLocalizedString(@"FINGERPRINT_INFO_THEIRS", @""); + _infoMyFingerprint.text = NSLocalizedString(@"FINGERPRINT_INFO_YOURS", @""); + _presentationLabel.text = NSLocalizedString(@"FINGERPRINT_INFO_ABOUT", @""); + _userFingerprintTitleLabel.text = NSLocalizedString(@"FINGERPRINT_YOURS", @""); + if ([UIScreen mainScreen].bounds.size.height <= 480) { self.presentationLabel.hidden = YES; self.myFPBorderView.hidden = YES; } } -- (void)viewWillAppear:(BOOL)animated -{ - +- (void)viewWillAppear:(BOOL)animated { [self setTheirKeyInformation]; - - NSData *myPublicKey = [[TSStorageManager sharedManager] identityKeyPair].publicKey; + + NSData *myPublicKey = [[TSStorageManager sharedManager] identityKeyPair].publicKey; self.userFingerprintLabel.text = [TSFingerprintGenerator getFingerprintForDisplay:myPublicKey]; - - [UIView animateWithDuration:0.6 delay:0. options:UIViewAnimationOptionCurveEaseInOut animations:^{ - [self.view setAlpha:1]; - } completion:nil]; - + + [UIView animateWithDuration:0.6 + delay:0. + options:UIViewAnimationOptionCurveEaseInOut + animations:^{ + [self.view setAlpha:1]; + } + completion:nil]; } - (void)didReceiveMemoryWarning { @@ -73,88 +75,89 @@ static NSString* const kScanIdentityBarcodeViewSegue = @"ScanIdentityBarcodeView self.contactFingerprintTitleLabel.text = self.thread.name; NSData *identityKey = [[TSStorageManager sharedManager] identityKeyForRecipientId:self.thread.contactIdentifier]; self.contactFingerprintLabel.text = [TSFingerprintGenerator getFingerprintForDisplay:identityKey]; - - if([self.contactFingerprintLabel.text length] == 0) { + + if ([self.contactFingerprintLabel.text length] == 0) { // no fingerprint, hide this view - _presentationLabel.hidden = YES; + _presentationLabel.hidden = YES; _theirFingerprintView.hidden = YES; } - } --(NSData*) getMyPublicIdentityKey { +- (NSData *)getMyPublicIdentityKey { return [[TSStorageManager sharedManager] identityKeyPair].publicKey; } --(NSData*) getTheirPublicIdentityKey { +- (NSData *)getTheirPublicIdentityKey { return [[TSStorageManager sharedManager] identityKeyForRecipientId:self.thread.contactIdentifier]; - } #pragma mark - Action -- (IBAction)closeButtonAction:(id)sender -{ - [UIView animateWithDuration:0.6 delay:0. options:UIViewAnimationOptionCurveEaseInOut animations:^{ - [self.view setAlpha:0]; - } completion:^(BOOL succeeded){ - [self dismissViewControllerAnimated:NO completion:nil]; - }]; - +- (IBAction)closeButtonAction:(id)sender { + [UIView animateWithDuration:0.6 + delay:0. + options:UIViewAnimationOptionCurveEaseInOut + animations:^{ + [self.view setAlpha:0]; + } + completion:^(BOOL succeeded) { + [self dismissViewControllerAnimated:NO completion:nil]; + }]; } -- (IBAction)shredAndDelete:(id)sender -{ - if(!_isPresentingDialog) { +- (IBAction)shredAndDelete:(id)sender { + if (!_isPresentingDialog) { _isPresentingDialog = YES; - [DJWActionSheet showInView:self.view withTitle:NSLocalizedString(@"FINGERPRINT_SHRED_KEYMATERIAL_CONFIRMATION", @"") cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") destructiveButtonTitle:nil otherButtonTitles:@[NSLocalizedString(@"FINGERPRINT_SHRED_KEYMATERIAL_BUTTON", @"")] + [DJWActionSheet showInView:self.view + withTitle:NSLocalizedString(@"FINGERPRINT_SHRED_KEYMATERIAL_CONFIRMATION", @"") + cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") + destructiveButtonTitle:nil + otherButtonTitles:@[ NSLocalizedString(@"FINGERPRINT_SHRED_KEYMATERIAL_BUTTON", @"") ] tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) { - _isPresentingDialog = NO; - if (tappedButtonIndex == actionSheet.cancelButtonIndex) { - DDLogDebug(@"User Cancelled"); - } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { - DDLogDebug(@"Destructive button tapped"); - } else { - switch (tappedButtonIndex) { - case 0: - [self shredKeyingMaterial]; - break; - default: - break; - } - } + _isPresentingDialog = NO; + if (tappedButtonIndex == actionSheet.cancelButtonIndex) { + DDLogDebug(@"User Cancelled"); + } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { + DDLogDebug(@"Destructive button tapped"); + } else { + switch (tappedButtonIndex) { + case 0: + [self shredKeyingMaterial]; + break; + default: + break; + } + } }]; } } --(IBAction) showFingerprint { +- (IBAction)showFingerprint { [self performSegueWithIdentifier:kPresentIdentityQRCodeViewSegue sender:self]; } --(IBAction) scanFingerprint { +- (IBAction)scanFingerprint { [self performSegueWithIdentifier:kScanIdentityBarcodeViewSegue sender:self]; } - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - if([[segue identifier] isEqualToString:kPresentIdentityQRCodeViewSegue]){ + if ([[segue identifier] isEqualToString:kPresentIdentityQRCodeViewSegue]) { [segue.destinationViewController setIdentityKey:[[self getMyPublicIdentityKey] prependKeyType]]; - } - else if([[segue identifier] isEqualToString:kScanIdentityBarcodeViewSegue]){ + } else if ([[segue identifier] isEqualToString:kScanIdentityBarcodeViewSegue]) { [segue.destinationViewController setIdentityKey:[[self getTheirPublicIdentityKey] prependKeyType]]; } - } -- (IBAction)unwindToIdentityKeyWasVerified:(UIStoryboardSegue *)segue{ +- (IBAction)unwindToIdentityKeyWasVerified:(UIStoryboardSegue *)segue { // Can later be used to mark identity key as verified if we want step above TOFU in UX } -- (IBAction)unwindIdentityVerificationCancel:(UIStoryboardSegue *)segue{ +- (IBAction)unwindIdentityVerificationCancel:(UIStoryboardSegue *)segue { DDLogDebug(@"action cancelled"); // Can later be used to mark identity key as verified if we want step above TOFU in UX } @@ -168,7 +171,7 @@ static NSString* const kScanIdentityBarcodeViewSegue = @"ScanIdentityBarcodeView } - (void)shredDiscussionsWithContact { - UINavigationController *nVC = (UINavigationController*)self.presentingViewController; + UINavigationController *nVC = (UINavigationController *)self.presentingViewController; for (UIViewController __strong *vc in nVC.viewControllers) { if ([vc isKindOfClass:[MessagesViewController class]]) { vc = nil; @@ -176,10 +179,11 @@ static NSString* const kScanIdentityBarcodeViewSegue = @"ScanIdentityBarcodeView } [self.thread remove]; // this removes the thread and all it's discussion (YapDatabaseRelationships) - __block SignalsNavigationController *vc = (SignalsNavigationController*)[self presentingViewController]; - [vc dismissViewControllerAnimated:YES completion:^{ - [vc popToRootViewControllerAnimated:YES]; - }]; + __block SignalsNavigationController *vc = (SignalsNavigationController *)[self presentingViewController]; + [vc dismissViewControllerAnimated:YES + completion:^{ + [vc popToRootViewControllerAnimated:YES]; + }]; } @end diff --git a/Signal/src/view controllers/FullImageViewController.h b/Signal/src/view controllers/FullImageViewController.h index ac5b6a336..ca8a181b8 100644 --- a/Signal/src/view controllers/FullImageViewController.h +++ b/Signal/src/view controllers/FullImageViewController.h @@ -12,11 +12,11 @@ @interface FullImageViewController : UIViewController -- (instancetype)initWithAttachment:(TSAttachmentStream*)attachment +- (instancetype)initWithAttachment:(TSAttachmentStream *)attachment fromRect:(CGRect)rect - forInteraction:(TSInteraction*)interaction + forInteraction:(TSInteraction *)interaction isAnimated:(BOOL)animated; -- (void)presentFromViewController:(UIViewController*)viewController; +- (void)presentFromViewController:(UIViewController *)viewController; @end diff --git a/Signal/src/view controllers/FullImageViewController.m b/Signal/src/view controllers/FullImageViewController.m index 2db5aa003..66c0fe825 100644 --- a/Signal/src/view controllers/FullImageViewController.m +++ b/Signal/src/view controllers/FullImageViewController.m @@ -7,11 +7,11 @@ // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // -#import "FullImageViewController.h" -#import "DJWActionSheet+OWS.h" -#import "UIUtil.h" #import +#import "DJWActionSheet+OWS.h" #import "FLAnimatedImage.h" +#import "FullImageViewController.h" +#import "UIUtil.h" #define kImageViewCornerRadius 5.0f @@ -40,32 +40,31 @@ @property NSData *fileData; @property TSAttachmentStream *attachment; -@property TSInteraction *interaction; +@property TSInteraction *interaction; @end @implementation FullImageViewController -- (instancetype)initWithAttachment:(TSAttachmentStream*)attachment +- (instancetype)initWithAttachment:(TSAttachmentStream *)attachment fromRect:(CGRect)rect - forInteraction:(TSInteraction*)interaction - isAnimated:(BOOL)animated -{ + forInteraction:(TSInteraction *)interaction + isAnimated:(BOOL)animated { self = [super initWithNibName:nil bundle:nil]; - - if (self) { - self.attachment = attachment; - self.originRect = rect; + + if (self) { + self.attachment = attachment; + self.originRect = rect; self.interaction = interaction; - self.isAnimated = animated; - self.fileData = [NSData dataWithContentsOfURL:[attachment mediaURL]]; + self.isAnimated = animated; + self.fileData = [NSData dataWithContentsOfURL:[attachment mediaURL]]; } - + return self; } -- (UIImage*)image{ +- (UIImage *)image { return self.attachment.image; } @@ -76,7 +75,7 @@ [self initializeScrollView]; [self initializeImageView]; [self initializeGestureRecognizers]; - + [self populateImageView:self.image]; } @@ -88,19 +87,17 @@ #pragma mark - Initializers -- (void)initializeBackground -{ +- (void)initializeBackground { self.imageView.backgroundColor = [UIColor colorWithWhite:0 alpha:kBackgroundAlpha]; self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:kBackgroundAlpha]; self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.backgroundView = [[UIView alloc] initWithFrame:CGRectInset(self.view.bounds, -512, -512)]; self.backgroundView.backgroundColor = [UIColor colorWithWhite:0 alpha:kBackgroundAlpha]; - + [self.view addSubview:self.backgroundView]; } -- (void)initializeScrollView -{ +- (void)initializeScrollView { self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; self.scrollView.delegate = self; self.scrollView.zoomScale = 1.0f; @@ -109,21 +106,19 @@ [self.view addSubview:self.scrollView]; } -- (void)initializeImageView -{ +- (void)initializeImageView { if (self.isAnimated) { // Present the animated image using Flipboard/FLAnimatedImage - FLAnimatedImage *animatedGif = [FLAnimatedImage animatedImageWithGIFData:self.fileData]; + FLAnimatedImage *animatedGif = [FLAnimatedImage animatedImageWithGIFData:self.fileData]; FLAnimatedImageView *imageView = [[FLAnimatedImageView alloc] init]; - imageView.animatedImage = animatedGif; - imageView.frame = self.originRect; - imageView.contentMode = UIViewContentModeScaleAspectFill; - imageView.clipsToBounds = YES; - self.imageView = imageView; - } - else { + imageView.animatedImage = animatedGif; + imageView.frame = self.originRect; + imageView.contentMode = UIViewContentModeScaleAspectFill; + imageView.clipsToBounds = YES; + self.imageView = imageView; + } else { // Present the static image using standard UIImageView - self.imageView = [[UIImageView alloc]initWithFrame:self.originRect]; + self.imageView = [[UIImageView alloc] initWithFrame:self.originRect]; self.imageView.layer.cornerRadius = kImageViewCornerRadius; self.imageView.contentMode = UIViewContentModeScaleAspectFill; self.imageView.userInteractionEnabled = YES; @@ -134,21 +129,19 @@ [self.scrollView addSubview:self.imageView]; } -- (void)populateImageView:(UIImage*)image -{ +- (void)populateImageView:(UIImage *)image { if (image && !self.isAnimated) { self.imageView.image = image; } } -- (void)initializeGestureRecognizers -{ - self.doubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(imageDoubleTapped:)]; +- (void)initializeGestureRecognizers { + self.doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageDoubleTapped:)]; self.doubleTap.numberOfTapsRequired = 2; - - self.singleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(imageSingleTapped:)]; + + self.singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageSingleTapped:)]; [self.singleTap requireGestureRecognizerToFail:self.doubleTap]; - + self.singleTap.delegate = self; self.doubleTap.delegate = self; @@ -156,117 +149,118 @@ [self.view addGestureRecognizer:self.doubleTap]; } -- (void) initializeShareButton -{ +- (void)initializeShareButton { CGFloat buttonRadius = 50.0f; - CGFloat x = 14.0f; - CGFloat y = self.view.bounds.size.height - buttonRadius - 10.0f; - - self.shareButton = [[UIButton alloc]initWithFrame:CGRectMake(x, y, buttonRadius, buttonRadius)]; + CGFloat x = 14.0f; + CGFloat y = self.view.bounds.size.height - buttonRadius - 10.0f; + + self.shareButton = [[UIButton alloc] initWithFrame:CGRectMake(x, y, buttonRadius, buttonRadius)]; [self.shareButton addTarget:self action:@selector(shareButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; [self.shareButton setImage:[UIImage imageNamed:@"savephoto"] forState:UIControlStateNormal]; - + [self.view addSubview:self.shareButton]; } #pragma mark - Gesture Recognizers -- (void)imageDoubleTapped:(UITapGestureRecognizer*)doubleTap -{ - CGPoint tap = [doubleTap locationInView:doubleTap.view]; +- (void)imageDoubleTapped:(UITapGestureRecognizer *)doubleTap { + CGPoint tap = [doubleTap locationInView:doubleTap.view]; CGPoint convertCoord = [self.scrollView convertPoint:tap fromView:doubleTap.view]; CGRect targetZoomRect; UIEdgeInsets targetInsets; - - CGSize zoom ; - + + CGSize zoom; + if (self.scrollView.zoomScale == 1.0f) { - zoom = CGSizeMake(self.view.bounds.size.width / kTargetDoubleTapZoom, self.view.bounds.size.height / kTargetDoubleTapZoom); - targetZoomRect = CGRectMake(convertCoord.x - (zoom.width/2.0f), convertCoord.y - (zoom.height/2.0f), zoom.width, zoom.height); + zoom = CGSizeMake(self.view.bounds.size.width / kTargetDoubleTapZoom, + self.view.bounds.size.height / kTargetDoubleTapZoom); + targetZoomRect = CGRectMake( + convertCoord.x - (zoom.width / 2.0f), convertCoord.y - (zoom.height / 2.0f), zoom.width, zoom.height); targetInsets = [self contentInsetForScrollView:kTargetDoubleTapZoom]; } else { - zoom = CGSizeMake(self.view.bounds.size.width * self.scrollView.zoomScale, self.view.bounds.size.height * self.scrollView.zoomScale); - targetZoomRect = CGRectMake(convertCoord.x - (zoom.width/2.0f), convertCoord.y - (zoom.height/2.0f), zoom.width, zoom.height); + zoom = CGSizeMake(self.view.bounds.size.width * self.scrollView.zoomScale, + self.view.bounds.size.height * self.scrollView.zoomScale); + targetZoomRect = CGRectMake( + convertCoord.x - (zoom.width / 2.0f), convertCoord.y - (zoom.height / 2.0f), zoom.width, zoom.height); targetInsets = [self contentInsetForScrollView:1.0f]; } - + self.view.userInteractionEnabled = NO; - + [CATransaction begin]; [CATransaction setCompletionBlock:^{ - self.scrollView.contentInset = targetInsets; - self.view.userInteractionEnabled = YES; + self.scrollView.contentInset = targetInsets; + self.view.userInteractionEnabled = YES; }]; [self.scrollView zoomToRect:targetZoomRect animated:YES]; [CATransaction commit]; - } -- (void)imageSingleTapped:(UITapGestureRecognizer*)singleTap -{ +- (void)imageSingleTapped:(UITapGestureRecognizer *)singleTap { [self dismiss]; } #pragma mark - Presentation --(void)presentFromViewController:(UIViewController*)viewController -{ - _isPresenting = YES; +- (void)presentFromViewController:(UIViewController *)viewController { + _isPresenting = YES; self.view.userInteractionEnabled = NO; [self.view addSubview:self.imageView]; self.modalPresentationStyle = UIModalPresentationOverCurrentContext; - self.view.alpha = 0; - - [viewController presentViewController:self animated:NO completion:^{ - [UIView animateWithDuration:0.4f - delay:0 - options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseInOut - animations:^(){ - self.view.alpha = 1.0f; - self.imageView.frame = [self resizedFrameForImageView:self.image.size]; - self.imageView.center = CGPointMake(self.view.bounds.size.width/2.0f, self.view.bounds.size.height/2.0f); - } completion:^(BOOL completed){ - self.scrollView.frame = self.view.bounds; - [self.scrollView addSubview:self.imageView]; - [self updateLayouts]; - [self initializeShareButton]; - self.view.userInteractionEnabled = YES; - _isPresenting = NO; - }]; - [UIUtil modalCompletionBlock](); - }]; + self.view.alpha = 0; + [viewController + presentViewController:self + animated:NO + completion:^{ + [UIView animateWithDuration:0.4f + delay:0 + options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseInOut + animations:^() { + self.view.alpha = 1.0f; + self.imageView.frame = [self resizedFrameForImageView:self.image.size]; + self.imageView.center = + CGPointMake(self.view.bounds.size.width / 2.0f, self.view.bounds.size.height / 2.0f); + } + completion:^(BOOL completed) { + self.scrollView.frame = self.view.bounds; + [self.scrollView addSubview:self.imageView]; + [self updateLayouts]; + [self initializeShareButton]; + self.view.userInteractionEnabled = YES; + _isPresenting = NO; + }]; + [UIUtil modalCompletionBlock](); + }]; } -- (void)dismiss -{ +- (void)dismiss { self.view.userInteractionEnabled = NO; [UIView animateWithDuration:0.4f - delay:0 - options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseInOut - animations:^(){ - self.backgroundView.backgroundColor = [UIColor clearColor]; - self.scrollView.alpha = 0; - self.view.alpha = 0; - } completion:^(BOOL completed){ - [self.presentingViewController dismissViewControllerAnimated:NO completion:nil]; - }]; + delay:0 + options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseInOut + animations:^() { + self.backgroundView.backgroundColor = [UIColor clearColor]; + self.scrollView.alpha = 0; + self.view.alpha = 0; + } + completion:^(BOOL completed) { + [self.presentingViewController dismissViewControllerAnimated:NO completion:nil]; + }]; } #pragma mark - Update Layout -- (void)viewDidLayoutSubviews -{ +- (void)viewDidLayoutSubviews { [self updateLayouts]; } -- (void) updateLayouts -{ +- (void)updateLayouts { if (_isPresenting) { return; } - + self.scrollView.frame = self.view.bounds; self.imageView.frame = [self resizedFrameForImageView:self.image.size]; self.scrollView.contentSize = self.imageView.frame.size; @@ -278,9 +272,10 @@ - (CGRect)resizedFrameForImageView:(CGSize)imageSize { CGRect frame = self.view.bounds; - CGSize screenSize = CGSizeMake(frame.size.width * self.scrollView.zoomScale, frame.size.height * self.scrollView.zoomScale); + CGSize screenSize = + CGSizeMake(frame.size.width * self.scrollView.zoomScale, frame.size.height * self.scrollView.zoomScale); CGSize targetSize = screenSize; - + if ([self isImagePortrait]) { if ([self getAspectRatioForCGSize:screenSize] < [self getAspectRatioForCGSize:imageSize]) { targetSize.width = screenSize.height / [self getAspectRatioForCGSize:imageSize]; @@ -294,55 +289,55 @@ targetSize.width = screenSize.height / [self getAspectRatioForCGSize:imageSize]; } } - - frame.size = targetSize; + + frame.size = targetSize; frame.origin = CGPointMake(0, 0); return frame; } - (UIEdgeInsets)contentInsetForScrollView:(CGFloat)targetZoomScale { UIEdgeInsets inset = UIEdgeInsetsZero; - - CGSize boundsSize = self.scrollView.bounds.size; + + CGSize boundsSize = self.scrollView.bounds.size; CGSize contentSize = self.image.size; CGSize minSize; - + if ([self isImagePortrait]) { if ([self getAspectRatioForCGSize:boundsSize] < [self getAspectRatioForCGSize:contentSize]) { minSize.height = boundsSize.height; - minSize.width = minSize.height / [self getAspectRatioForCGSize:contentSize]; + minSize.width = minSize.height / [self getAspectRatioForCGSize:contentSize]; } else { - minSize.width = boundsSize.width; + minSize.width = boundsSize.width; minSize.height = minSize.width * [self getAspectRatioForCGSize:contentSize]; } } else { if ([self getAspectRatioForCGSize:boundsSize] > [self getAspectRatioForCGSize:contentSize]) { - minSize.width = boundsSize.width; - minSize.height = minSize.width * [self getAspectRatioForCGSize:contentSize]; + minSize.width = boundsSize.width; + minSize.height = minSize.width * [self getAspectRatioForCGSize:contentSize]; } else { minSize.height = boundsSize.height; - minSize.width = minSize.height / [self getAspectRatioForCGSize:contentSize]; + minSize.width = minSize.height / [self getAspectRatioForCGSize:contentSize]; } } - + CGSize finalSize = self.view.bounds.size; minSize.width *= targetZoomScale; minSize.height *= targetZoomScale; - + if (minSize.height > finalSize.height && minSize.width > finalSize.width) { inset = UIEdgeInsetsZero; } else { CGFloat dy = boundsSize.height - minSize.height; CGFloat dx = boundsSize.width - minSize.width; - + dy = (dy > 0) ? dy : 0; dx = (dx > 0) ? dx : 0; - - inset.top = dy/2.0f; - inset.bottom = dy/2.0f; - inset.left = dx/2.0f; - inset.right = dx/2.0f; + + inset.top = dy / 2.0f; + inset.bottom = dy / 2.0f; + inset.left = dx / 2.0f; + inset.right = dx / 2.0f; } return inset; } @@ -354,9 +349,8 @@ } - (void)scrollViewDidZoom:(UIScrollView *)scrollView { - scrollView.contentInset = [self contentInsetForScrollView:scrollView.zoomScale]; - + if (self.scrollView.scrollEnabled == NO) { self.scrollView.scrollEnabled = YES; } @@ -364,64 +358,73 @@ - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale { self.scrollView.scrollEnabled = (scale > 1); - self.scrollView.contentInset = [self contentInsetForScrollView:scale]; + self.scrollView.contentInset = [self contentInsetForScrollView:scale]; } #pragma mark - Utility -- (BOOL)isImagePortrait -{ +- (BOOL)isImagePortrait { return ([self getAspectRatioForCGSize:self.image.size] > 1.0f); } -- (CGFloat)getAspectRatioForCGSize:(CGSize)size -{ +- (CGFloat)getAspectRatioForCGSize:(CGSize)size { return size.height / size.width; } #pragma mark - Actions --(void)shareButtonTapped:(UIButton*)sender -{ - [DJWActionSheet showInView:self.view withTitle:nil cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") destructiveButtonTitle:NSLocalizedString(@"TXT_DELETE_TITLE", @"") otherButtonTitles:@[NSLocalizedString(@"CAMERA_ROLL_SAVE_BUTTON", @""), NSLocalizedString(@"CAMERA_ROLL_COPY_BUTTON", @"")] tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) { - if (tappedButtonIndex == actionSheet.cancelButtonIndex) { +- (void)shareButtonTapped:(UIButton *)sender { + [DJWActionSheet showInView:self.view + withTitle:nil + cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") + destructiveButtonTitle:NSLocalizedString(@"TXT_DELETE_TITLE", @"") + otherButtonTitles:@[ + NSLocalizedString(@"CAMERA_ROLL_SAVE_BUTTON", @""), + NSLocalizedString(@"CAMERA_ROLL_COPY_BUTTON", @"") + ] + tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) { + if (tappedButtonIndex == actionSheet.cancelButtonIndex) { + } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { + __block TSInteraction *interaction = [self interaction]; + [self dismissViewControllerAnimated:YES + completion:^{ + [interaction remove]; + }]; - } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex){ - __block TSInteraction *interaction = [self interaction]; - [self dismissViewControllerAnimated:YES completion:^{ - [interaction remove]; - }]; - - } else { - switch (tappedButtonIndex) { - case 0: { - ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; - [library writeImageDataToSavedPhotosAlbum:self.fileData metadata:nil completionBlock:^(NSURL *assetURL, NSError *error) { - if (error) { - DDLogWarn(@"Error Saving image to photo album: %@", error); + } else { + switch (tappedButtonIndex) { + case 0: { + ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; + [library writeImageDataToSavedPhotosAlbum:self.fileData + metadata:nil + completionBlock:^(NSURL *assetURL, NSError *error) { + if (error) { + DDLogWarn(@"Error Saving image to photo album: %@", + error); + } + }]; + break; + } + case 1: + [[UIPasteboard generalPasteboard] setImage:self.image]; + break; + default: + DDLogWarn(@"Illegal Action sheet field #%ld <%s>", + (long)tappedButtonIndex, + __PRETTY_FUNCTION__); + break; + } } - }]; - break; - } - case 1: - [[UIPasteboard generalPasteboard] setImage:self.image]; - break; - default: - DDLogWarn(@"Illegal Action sheet field #%ld <%s>",(long)tappedButtonIndex, __PRETTY_FUNCTION__); - break; - } - } - }]; + }]; } #pragma mark - Saving images to Camera Roll -- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error - contextInfo:(void *)contextInfo -{ - if (error) - { - DDLogWarn(@"There was a problem saving <%@> to camera roll from %s ", error.localizedDescription ,__PRETTY_FUNCTION__); +- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo { + if (error) { + DDLogWarn(@"There was a problem saving <%@> to camera roll from %s ", + error.localizedDescription, + __PRETTY_FUNCTION__); } } diff --git a/Signal/src/view controllers/InCallViewController.h b/Signal/src/view controllers/InCallViewController.h index 231a00f3f..1d334d4dc 100644 --- a/Signal/src/view controllers/InCallViewController.h +++ b/Signal/src/view controllers/InCallViewController.h @@ -18,7 +18,7 @@ @property (nonatomic, strong) IBOutlet UIView *safeWordsView; @property (nonatomic, strong) IBOutlet UILabel *authenicationStringLabel; -@property (nonatomic, strong) IBOutlet UILabel* explainAuthenticationStringLabel; +@property (nonatomic, strong) IBOutlet UILabel *explainAuthenticationStringLabel; @property (nonatomic, strong) IBOutlet UIView *activeOrIncomingButtonsView; @@ -38,15 +38,11 @@ @property (nonatomic, readonly) CallState *callState; @property (nonatomic, readonly) Contact *potentiallyKnownContact; -typedef NS_ENUM(NSInteger, PushAcceptState){ - PushDidAcceptState, - PushDidDeclineState, - PushNotSetState -}; +typedef NS_ENUM(NSInteger, PushAcceptState) { PushDidAcceptState, PushDidDeclineState, PushNotSetState }; @property (nonatomic, readonly) PushAcceptState callPushState; --(void)configureWithLatestCall:(CallState*)callState; +- (void)configureWithLatestCall:(CallState *)callState; - (IBAction)endCallTapped; - (IBAction)muteButtonTapped; diff --git a/Signal/src/view controllers/InCallViewController.m b/Signal/src/view controllers/InCallViewController.m index 33c4c3791..849b6b247 100644 --- a/Signal/src/view controllers/InCallViewController.m +++ b/Signal/src/view controllers/InCallViewController.m @@ -25,26 +25,28 @@ @implementation InCallViewController --(void)configureWithLatestCall:(CallState*)callState { +- (void)configureWithLatestCall:(CallState *)callState { _potentiallyKnownContact = callState.potentiallySpecifiedContact; - _callState = callState; - _callPushState = PushNotSetState; + _callState = callState; + _callPushState = PushNotSetState; } - (void)viewDidLoad { [super viewDidLoad]; - + [self showCallState]; [self setPotentiallyKnownContact:_potentiallyKnownContact]; [self localizeButtons]; [self linkActions]; [[[[Environment getCurrent] contactsManager] getObservableContacts] watchLatestValue:^(NSArray *latestContacts) { - [self setPotentiallyKnownContact:[[[Environment getCurrent] contactsManager] latestContactForPhoneNumber:_callState.remoteNumber]]; - } onThread:[NSThread mainThread] untilCancelled:nil]; + [self setPotentiallyKnownContact:[[[Environment getCurrent] contactsManager] + latestContactForPhoneNumber:_callState.remoteNumber]]; + } + onThread:[NSThread mainThread] + untilCancelled:nil]; } --(void)linkActions -{ +- (void)linkActions { [_muteButton addTarget:self action:@selector(muteButtonTapped) forControlEvents:UIControlEventTouchUpInside]; [_speakerButton addTarget:self action:@selector(speakerButtonTapped) forControlEvents:UIControlEventTouchUpInside]; } @@ -62,7 +64,7 @@ [UIDevice.currentDevice setProximityMonitoringEnabled:NO]; } --(void) showCallState { +- (void)showCallState { [self clearDetails]; [self populateImmediateDetails]; [self handleIncomingDetails]; @@ -70,7 +72,7 @@ - (void)startRingingAnimation { [self stopConnectingFlashAnimation]; - + if (!_incomingCallButtonsView.hidden) { _vibrateTimer = [NSTimer scheduledTimerWithTimeInterval:VIBRATE_TIMER_DURATION target:self @@ -78,7 +80,7 @@ userInfo:nil repeats:YES]; } - + [_ringingAnimationTimer fire]; } @@ -114,32 +116,31 @@ - (void)setPotentiallyKnownContact:(Contact *)potentiallyKnownContact { _potentiallyKnownContact = potentiallyKnownContact; - - if (_potentiallyKnownContact) { + if (_potentiallyKnownContact) { if (_potentiallyKnownContact.image) { [UIUtil applyRoundedBorderToImageView:&_contactImageView]; } - + _nameLabel.text = _potentiallyKnownContact.fullName; } else { _nameLabel.text = _callState.remoteNumber.toE164; } } --(void) clearDetails { - _callStatusLabel.text = @""; - _nameLabel.text = @""; - _authenicationStringLabel.text = @""; +- (void)clearDetails { + _callStatusLabel.text = @""; + _nameLabel.text = @""; + _authenicationStringLabel.text = @""; _explainAuthenticationStringLabel.text = @""; - _contactImageView.image = nil; - _safeWordsView.hidden = YES; - _muteButton.hidden = YES; - _speakerButton.hidden = YES; + _contactImageView.image = nil; + _safeWordsView.hidden = YES; + _muteButton.hidden = YES; + _speakerButton.hidden = YES; [self displayAcceptRejectButtons:NO]; } --(void) populateImmediateDetails { +- (void)populateImmediateDetails { if (_potentiallyKnownContact) { _nameLabel.text = _potentiallyKnownContact.fullName; if (_potentiallyKnownContact.image) { @@ -147,45 +148,47 @@ } } } --(void) handleIncomingDetails { - [_callState.futureShortAuthenticationString thenDo:^(NSString* sas) { - _authenicationStringLabel.textColor = [UIColor ows_materialBlueColor]; - _safeWordsView.hidden = NO; - _muteButton.hidden = NO; - _speakerButton.hidden = NO; - _authenicationStringLabel.text = sas; +- (void)handleIncomingDetails { + [_callState.futureShortAuthenticationString thenDo:^(NSString *sas) { + _authenicationStringLabel.textColor = [UIColor ows_materialBlueColor]; + _safeWordsView.hidden = NO; + _muteButton.hidden = NO; + _speakerButton.hidden = NO; + _authenicationStringLabel.text = sas; }]; - [[_callState observableProgress] watchLatestValue:^(CallProgress* latestProgress) { - [self onCallProgressed:latestProgress]; - } onThread:NSThread.mainThread untilCancelled:nil]; + [[_callState observableProgress] watchLatestValue:^(CallProgress *latestProgress) { + [self onCallProgressed:latestProgress]; + } + onThread:NSThread.mainThread + untilCancelled:nil]; } --(void) onCallProgressed:(CallProgress*)latestProgress { +- (void)onCallProgressed:(CallProgress *)latestProgress { BOOL showAcceptRejectButtons = !_callState.initiatedLocally && [latestProgress type] <= CallProgressType_Ringing; [self displayAcceptRejectButtons:showAcceptRejectButtons]; [AppAudioManager.sharedInstance respondToProgressChange:[latestProgress type] forLocallyInitiatedCall:_callState.initiatedLocally]; - + if ([latestProgress type] == CallProgressType_Ringing) { [self startRingingAnimation]; } - + if ([latestProgress type] == CallProgressType_Terminated) { - [_callState.futureTermination thenDo:^(CallTermination* termination) { - [self onCallEnded:termination]; - [AppAudioManager.sharedInstance respondToTerminationType:[termination type]]; + [_callState.futureTermination thenDo:^(CallTermination *termination) { + [self onCallEnded:termination]; + [AppAudioManager.sharedInstance respondToTerminationType:[termination type]]; }]; } else { _callStatusLabel.text = latestProgress.localizedDescriptionForUser; } } --(void) onCallEnded:(CallTermination*)termination { +- (void)onCallEnded:(CallTermination *)termination { [self updateViewForTermination:termination]; [Environment.phoneManager hangupOrDenyCall]; - - [self dismissViewWithOptionalDelay: [termination type] != CallTerminationType_ReplacedByNext ]; + + [self dismissViewWithOptionalDelay:[termination type] != CallTerminationType_ReplacedByNext]; } - (void)endCallTapped { @@ -212,39 +215,38 @@ [self dismissViewControllerAnimated:YES completion:nil]; } --(void) updateViewForTermination:(CallTermination*) termination{ - NSString* message = termination.localizedDescriptionForUser; - +- (void)updateViewForTermination:(CallTermination *)termination { + NSString *message = termination.localizedDescriptionForUser; + if ([termination type] == CallTerminationType_ServerMessage) { - CallFailedServerMessage* serverMessage = [termination messageInfo]; - message = [message stringByAppendingString:[serverMessage text]]; + CallFailedServerMessage *serverMessage = [termination messageInfo]; + message = [message stringByAppendingString:[serverMessage text]]; } - + _callStatusLabel.textColor = [UIColor ows_redColor]; - + [self showConnectingError]; _callStatusLabel.text = message; } --(void) dismissViewWithOptionalDelay:(BOOL) useDelay { - if(useDelay && UIApplicationStateActive == [UIApplication.sharedApplication applicationState]){ +- (void)dismissViewWithOptionalDelay:(BOOL)useDelay { + if (useDelay && UIApplicationStateActive == [UIApplication.sharedApplication applicationState]) { [self dismissViewControllerAfterDelay:END_CALL_CLEANUP_DELAY]; - }else{ + } else { [self dismissViewControllerAnimated:NO completion:nil]; } } --(void) dismissViewControllerAfterDelay:(int) delay { +- (void)dismissViewControllerAfterDelay:(int)delay { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay), dispatch_get_main_queue(), ^{ - [self dismissViewControllerAnimated:YES completion:nil]; + [self dismissViewControllerAnimated:YES completion:nil]; }); } --(void) displayAcceptRejectButtons:(BOOL) enable{ - +- (void)displayAcceptRejectButtons:(BOOL)enable { _incomingCallButtonsView.hidden = !enable; - _activeCallButtonsView.hidden = enable; - + _activeCallButtonsView.hidden = enable; + if (_vibrateTimer && enable == false) { [_vibrateTimer invalidate]; } diff --git a/Signal/src/view controllers/InboxTableViewCell.h b/Signal/src/view controllers/InboxTableViewCell.h index 01c040c6a..afc112e88 100644 --- a/Signal/src/view controllers/InboxTableViewCell.h +++ b/Signal/src/view controllers/InboxTableViewCell.h @@ -10,10 +10,7 @@ #import "NextResponderScrollView.h" #import "TSThread.h" -typedef enum : NSUInteger { - kArchiveState = 0, - kInboxState = 1 -} CellState; +typedef enum : NSUInteger { kArchiveState = 0, kInboxState = 1 } CellState; @class InboxTableViewCell; @@ -23,10 +20,10 @@ typedef enum : NSUInteger { @end -@interface InboxTableViewCell : UITableViewCell +@interface InboxTableViewCell : UITableViewCell @property (nonatomic, strong) IBOutlet UILabel *nameLabel; -@property (nonatomic, strong) IBOutlet UILabel * snippetLabel; +@property (nonatomic, strong) IBOutlet UILabel *snippetLabel; @property (nonatomic, strong) IBOutlet UIImageView *contactPictureView; @property (nonatomic, strong) IBOutlet UILabel *timeLabel; @property (nonatomic, strong) IBOutlet NextResponderScrollView *scrollView; @@ -39,7 +36,7 @@ typedef enum : NSUInteger { @property (nonatomic, retain) NSString *threadId; + (instancetype)inboxTableViewCell; -- (void)configureWithThread:(TSThread*)thread; +- (void)configureWithThread:(TSThread *)thread; - (void)configureForState:(CellState)state; - (void)animateDisappear; diff --git a/Signal/src/view controllers/InboxTableViewCell.m b/Signal/src/view controllers/InboxTableViewCell.m index ed5121078..0bf2bc669 100644 --- a/Signal/src/view controllers/InboxTableViewCell.m +++ b/Signal/src/view controllers/InboxTableViewCell.m @@ -6,15 +6,15 @@ // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // -#import "InboxTableViewCell.h" #import "Environment.h" -#import "PreferencesUtil.h" -#import "Util.h" -#import "UIImage+JSQMessages.h" -#import "TSGroupThread.h" -#import "TSContactThread.h" +#import "InboxTableViewCell.h" #import "JSQMessagesAvatarImageFactory.h" +#import "PreferencesUtil.h" +#import "TSContactThread.h" +#import "TSGroupThread.h" #import "TSMessagesManager.h" +#import "UIImage+JSQMessages.h" +#import "Util.h" #define ARCHIVE_IMAGE_VIEW_WIDTH 22.0f #define DELETE_IMAGE_VIEW_WIDTH 19.0f @@ -25,29 +25,28 @@ @interface InboxTableViewCell () @property NSUInteger unreadMessages; -@property UIView *messagesBadge; -@property UILabel *unreadLabel; +@property UIView *messagesBadge; +@property UILabel *unreadLabel; @end @implementation InboxTableViewCell + (instancetype)inboxTableViewCell { - InboxTableViewCell *cell = [NSBundle.mainBundle loadNibNamed:NSStringFromClass(self.class) - owner:self - options:nil][0]; - + InboxTableViewCell *cell = + [NSBundle.mainBundle loadNibNamed:NSStringFromClass(self.class) owner:self options:nil][0]; + [cell initializeLayout]; return cell; } - (void)initializeLayout { - _scrollView.contentSize = CGSizeMake(CGRectGetWidth(_contentContainerView.bounds), - CGRectGetHeight(_scrollView.frame)); - + _scrollView.contentSize = + CGSizeMake(CGRectGetWidth(_contentContainerView.bounds), CGRectGetHeight(_scrollView.frame)); + _scrollView.contentOffset = CGPointMake(CGRectGetWidth(_archiveView.frame), 0); _archiveImageView.image = [_archiveImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; - + self.selectionStyle = UITableViewCellSelectionStyleDefault; } @@ -55,90 +54,97 @@ return NSStringFromClass(self.class); } --(void)configureWithThread:(TSThread*)thread { +- (void)configureWithThread:(TSThread *)thread { if (!_threadId || ![_threadId isEqualToString:thread.uniqueId]) { self.hidden = YES; } - - NSString *name = thread.name; - _threadId = thread.uniqueId; - NSString *snippetLabel = thread.lastMessageLabel; + + NSString *name = thread.name; + _threadId = thread.uniqueId; + NSString *snippetLabel = thread.lastMessageLabel; NSAttributedString *attributedDate = [self dateAttributedString:thread.lastMessageDate]; - NSUInteger unreadCount = [[TSMessagesManager sharedManager] unreadMessagesInThread:thread]; - + NSUInteger unreadCount = [[TSMessagesManager sharedManager] unreadMessagesInThread:thread]; + dispatch_async(dispatch_get_main_queue(), ^{ - _nameLabel.text = name; - _snippetLabel.text = snippetLabel; - _timeLabel.attributedText = attributedDate; - - if([thread isKindOfClass:[TSGroupThread class]]) { - _contactPictureView.image = ((TSGroupThread*)thread).groupModel.groupImage!=nil ? ((TSGroupThread*)thread).groupModel.groupImage : [UIImage imageNamed:@"empty-group-avatar"]; - if([_nameLabel.text length]==0) { - _nameLabel.text = NSLocalizedString(@"NEW_GROUP_DEFAULT_TITLE", @""); - } - if(_contactPictureView.image!=nil) { - dispatch_async(dispatch_get_main_queue(), ^{ - [UIUtil applyRoundedBorderToImageView:&_contactPictureView]; - }); - } - } - else { - NSMutableString *initials = [NSMutableString string]; - - if([name length]>0) { - NSArray *words = [name componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; - for (NSString * word in words) { - if ([word length] > 0) { - NSString *firstLetter = [word substringToIndex:1]; - [initials appendString:[firstLetter uppercaseString]]; - } - } - } - - NSRange stringRange = {0, MIN([initials length], (NSUInteger)3)}; //Rendering max 3 letters. - initials = [[initials substringWithRange:stringRange] mutableCopy]; - - UIColor *backgroundColor = thread.isGroupThread ? [UIColor whiteColor] : [UIColor backgroundColorForContact:((TSContactThread*)thread).contactIdentifier]; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - UIImage* image = [[JSQMessagesAvatarImageFactory avatarImageWithUserInitials:initials backgroundColor:backgroundColor textColor:[UIColor whiteColor] font:[UIFont ows_boldFontWithSize:36.0] diameter:100] avatarImage]; - dispatch_async(dispatch_get_main_queue(), ^{ - _contactPictureView.image = thread.image!=nil ? thread.image : image; - - if(thread.image!=nil) { - [UIUtil applyRoundedBorderToImageView:&_contactPictureView]; - } - }); + _nameLabel.text = name; + _snippetLabel.text = snippetLabel; + _timeLabel.attributedText = attributedDate; + + if ([thread isKindOfClass:[TSGroupThread class]]) { + _contactPictureView.image = ((TSGroupThread *)thread).groupModel.groupImage != nil + ? ((TSGroupThread *)thread).groupModel.groupImage + : [UIImage imageNamed:@"empty-group-avatar"]; + if ([_nameLabel.text length] == 0) { + _nameLabel.text = NSLocalizedString(@"NEW_GROUP_DEFAULT_TITLE", @""); + } + if (_contactPictureView.image != nil) { + dispatch_async(dispatch_get_main_queue(), ^{ + [UIUtil applyRoundedBorderToImageView:&_contactPictureView]; + }); + } + } else { + NSMutableString *initials = [NSMutableString string]; + + if ([name length] > 0) { + NSArray *words = [name componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + for (NSString *word in words) { + if ([word length] > 0) { + NSString *firstLetter = [word substringToIndex:1]; + [initials appendString:[firstLetter uppercaseString]]; + } + } + } + + NSRange stringRange = {0, MIN([initials length], (NSUInteger)3)}; // Rendering max 3 letters. + initials = [[initials substringWithRange:stringRange] mutableCopy]; + + UIColor *backgroundColor = + thread.isGroupThread ? [UIColor whiteColor] + : [UIColor backgroundColorForContact:((TSContactThread *)thread).contactIdentifier]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + UIImage *image = + [[JSQMessagesAvatarImageFactory avatarImageWithUserInitials:initials + backgroundColor:backgroundColor + textColor:[UIColor whiteColor] + font:[UIFont ows_boldFontWithSize:36.0] + diameter:100] avatarImage]; + dispatch_async(dispatch_get_main_queue(), ^{ + _contactPictureView.image = thread.image != nil ? thread.image : image; + + if (thread.image != nil) { + [UIUtil applyRoundedBorderToImageView:&_contactPictureView]; + } }); - } - - self.separatorInset = UIEdgeInsetsMake(0,_contactPictureView.frame.size.width*1.5f, 0, 0); - - if (thread.hasUnreadMessages) { - [self updateCellForUnreadMessage]; - } else { - [self updateCellForReadMessage]; - } - [self setUnreadMsgCount:unreadCount]; - self.hidden = NO; + }); + } + + self.separatorInset = UIEdgeInsetsMake(0, _contactPictureView.frame.size.width * 1.5f, 0, 0); + + if (thread.hasUnreadMessages) { + [self updateCellForUnreadMessage]; + } else { + [self updateCellForReadMessage]; + } + [self setUnreadMsgCount:unreadCount]; + self.hidden = NO; }); } --(void)configureForState:(CellState)state -{ +- (void)configureForState:(CellState)state { switch (state) { case kArchiveState: - _archiveImageView.image = [[UIImage imageNamed:@"cellBtnMoveToInbox--blue"]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; + _archiveImageView.image = [[UIImage imageNamed:@"cellBtnMoveToInbox--blue"] + imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; break; case kInboxState: break; - + default: break; } } --(void)updateCellForUnreadMessage -{ +- (void)updateCellForUnreadMessage { _nameLabel.font = [UIFont ows_boldFontWithSize:14.0f]; _nameLabel.textColor = [UIColor ows_blackColor]; _snippetLabel.font = [UIFont ows_mediumFontWithSize:12]; @@ -146,8 +152,7 @@ _timeLabel.textColor = [UIColor ows_materialBlueColor]; } --(void)updateCellForReadMessage -{ +- (void)updateCellForReadMessage { _nameLabel.font = [UIFont ows_boldFontWithSize:14.0f]; _nameLabel.textColor = [UIColor ows_blackColor]; _snippetLabel.font = [UIFont ows_regularFontWithSize:12]; @@ -159,93 +164,92 @@ - (NSAttributedString *)dateAttributedString:(NSDate *)date { NSString *timeString; - + if ([DateUtil dateIsToday:date]) { timeString = [[DateUtil timeFormatter] stringFromDate:date]; } else { - timeString = [[DateUtil dateFormatter] stringFromDate:date]; } - + NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:timeString]; - + [attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor ows_darkGrayColor] range:NSMakeRange(0, timeString.length)]; - - - + + [attributedString addAttribute:NSFontAttributeName value:[UIFont ows_regularFontWithSize:TIME_LABEL_SIZE] range:NSMakeRange(0, timeString.length)]; - - + + return attributedString; } #pragma mark - UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView { - if (_scrollView.contentOffset.x < 0) { - _archiveImageView.image = [_archiveImageView.image jsq_imageMaskedWithColor:[UIColor ows_materialBlueColor]]; + _archiveImageView.image = [_archiveImageView.image jsq_imageMaskedWithColor:[UIColor ows_materialBlueColor]]; _archiveImageView.bounds = CGRectMake(_archiveImageView.bounds.origin.x, _archiveImageView.bounds.origin.y, ARCHIVE_IMAGE_VIEW_WIDTH, _archiveImageView.bounds.size.height); } else { - _archiveImageView.image = [_archiveImageView.image jsq_imageMaskedWithColor:[UIColor ows_darkGrayColor]]; - double ratio = (_archiveView.frame.size.width/2.0f - _scrollView.contentOffset.x) / (_archiveView.frame.size.width/2.0f); - double newWidth = ARCHIVE_IMAGE_VIEW_WIDTH/2.0f + (ARCHIVE_IMAGE_VIEW_WIDTH * ratio)/2.0f; + double ratio = (_archiveView.frame.size.width / 2.0f - _scrollView.contentOffset.x) / + (_archiveView.frame.size.width / 2.0f); + double newWidth = ARCHIVE_IMAGE_VIEW_WIDTH / 2.0f + (ARCHIVE_IMAGE_VIEW_WIDTH * ratio) / 2.0f; _archiveImageView.bounds = CGRectMake(_archiveImageView.bounds.origin.x, _archiveImageView.bounds.origin.y, (CGFloat)newWidth, _archiveImageView.bounds.size.height); - } } - (void)setUnreadMsgCount:(NSUInteger)unreadMessages { if (_unreadMessages != unreadMessages) { _unreadMessages = unreadMessages; - + if (_unreadMessages > 0) { if (_messagesBadge == nil) { static UIImage *backgroundImage = nil; static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^ - { - UIGraphicsBeginImageContextWithOptions(CGSizeMake(25.0f, 25.0f), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, [UIColor ows_materialBlueColor].CGColor); - CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, 25.0f, 25.0f)); - backgroundImage = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:8 topCapHeight:8]; - UIGraphicsEndImageContext(); - }); - - _messagesBadge = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, - _messageCounter.frame.size - .height, - _messageCounter.frame.size.width)]; + dispatch_once(&onceToken, ^{ + UIGraphicsBeginImageContextWithOptions(CGSizeMake(25.0f, 25.0f), false, 0.0f); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSetFillColorWithColor(context, [UIColor ows_materialBlueColor].CGColor); + CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, 25.0f, 25.0f)); + backgroundImage = + [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:8 topCapHeight:8]; + UIGraphicsEndImageContext(); + }); + + _messagesBadge = [[UIImageView alloc] + initWithFrame:CGRectMake( + 0.0f, 0.0f, _messageCounter.frame.size.height, _messageCounter.frame.size.width)]; _messagesBadge.userInteractionEnabled = NO; _messagesBadge.layer.zPosition = 2000; - + UIImageView *unreadBackground = [[UIImageView alloc] initWithImage:backgroundImage]; [_messageCounter addSubview:unreadBackground]; - + _unreadLabel = [[UILabel alloc] init]; _unreadLabel.backgroundColor = [UIColor clearColor]; _unreadLabel.textColor = [UIColor whiteColor]; _unreadLabel.font = [UIFont systemFontOfSize:12]; [_messageCounter addSubview:_unreadLabel]; } - + _unreadLabel.text = [[NSNumber numberWithUnsignedInteger:unreadMessages] stringValue]; [_unreadLabel sizeToFit]; - + CGPoint offset = CGPointMake(0.0f, 5.0f); - _unreadLabel.frame = CGRectMake(offset.x + floor((2.0f*(25 - _unreadLabel.frame.size.width)/ 2.0f)/2.0f), offset.y, _unreadLabel.frame.size.width, _unreadLabel.frame.size.height); + _unreadLabel.frame = + CGRectMake(offset.x + floor((2.0f * (25 - _unreadLabel.frame.size.width) / 2.0f) / 2.0f), + offset.y, + _unreadLabel.frame.size.width, + _unreadLabel.frame.size.height); _messageCounter.hidden = NO; } else { _messageCounter.hidden = YES; @@ -260,8 +264,7 @@ // archive the thread [_delegate tableViewCellTappedArchive:self]; [Environment.preferences setHasArchivedAMessage:YES]; - } - else { + } else { // don't do anything *targetContentOffset = CGPointMake(CGRectGetWidth(_archiveView.frame), 0); } @@ -269,11 +272,11 @@ #pragma mark - Animation --(void)animateDisappear -{ - [UIView animateWithDuration:1.0f animations:^(){ - self.alpha = 0; - }]; +- (void)animateDisappear { + [UIView animateWithDuration:1.0f + animations:^() { + self.alpha = 0; + }]; } diff --git a/Signal/src/view controllers/LockInteractionController.h b/Signal/src/view controllers/LockInteractionController.h index 81cdf4b3b..cb54b0940 100644 --- a/Signal/src/view controllers/LockInteractionController.h +++ b/Signal/src/view controllers/LockInteractionController.h @@ -12,7 +12,8 @@ typedef void (^LIControllerCompletionBlock)(); typedef BOOL (^LIControllerBlockingOperation)(); -typedef void (^LIControllerRetryBlock)(LIControllerBlockingOperation operationBlock, LIControllerCompletionBlock completionBlock); +typedef void (^LIControllerRetryBlock)(LIControllerBlockingOperation operationBlock, + LIControllerCompletionBlock completionBlock); + (void)performBlock:(LIControllerBlockingOperation)blockingOperation completionBlock:(LIControllerCompletionBlock)completionBlock diff --git a/Signal/src/view controllers/LockInteractionController.m b/Signal/src/view controllers/LockInteractionController.m index ea1ca6269..ad3b50373 100644 --- a/Signal/src/view controllers/LockInteractionController.m +++ b/Signal/src/view controllers/LockInteractionController.m @@ -14,7 +14,14 @@ @implementation LockInteractionController -MacrosSingletonImplemention ++ (instancetype)sharedController { + static LockInteractionController *sharedController = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedController = [self new]; + }); + return sharedController; +} + (void)performBlock:(LIControllerBlockingOperation)blockingOperation completionBlock:(LIControllerCompletionBlock)completionBlock @@ -22,63 +29,69 @@ MacrosSingletonImplemention usesNetwork:(BOOL)networkFlag { - - if (networkFlag) { [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:networkFlag]; } - - LockInteractionController *sharedInstance = [LockInteractionController sharedInstance]; - sharedInstance.alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Upgrading Signal ...", nil) - message:nil - preferredStyle:UIAlertControllerStyleAlert]; - - [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:sharedInstance.alertController - animated:YES - completion:nil]; - + + LockInteractionController *sharedController = [LockInteractionController sharedController]; + sharedController.alertController = + [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Upgrading Signal ...", nil) + message:nil + preferredStyle:UIAlertControllerStyleAlert]; + + [[UIApplication sharedApplication] + .keyWindow.rootViewController presentViewController:sharedController.alertController + animated:YES + completion:nil]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - BOOL success = blockingOperation(); - - dispatch_async(dispatch_get_main_queue(), ^{ - [sharedInstance.alertController dismissViewControllerAnimated:YES completion:^{ - if (networkFlag) { - [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; - } - - if (!success) { - retryBlock(blockingOperation, completionBlock); - } else { - completionBlock(); - } - }]; - }); - + BOOL success = blockingOperation(); + + dispatch_async(dispatch_get_main_queue(), ^{ + [sharedController.alertController + dismissViewControllerAnimated:YES + completion:^{ + if (networkFlag) { + [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; + } + + if (!success) { + retryBlock(blockingOperation, completionBlock); + } else { + completionBlock(); + } + }]; + }); + }); } -+ (LIControllerRetryBlock)defaultNetworkRetry -{ - LIControllerRetryBlock retryBlock = ^void(LIControllerBlockingOperation blockingOperation, LIControllerCompletionBlock completionBlock) { - UIAlertController *retryController = [UIAlertController alertControllerWithTitle:@"Upgrading Signal failed" - message:@"An network error occured while upgrading, please check your connectivity and try again." - preferredStyle:UIAlertControllerStyleAlert]; - - [retryController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"REGISTER_FAILED_TRY_AGAIN", nil) - style:UIAlertActionStyleDefault - handler:^(UIAlertAction *action) { - [self performBlock:blockingOperation - completionBlock:completionBlock - retryBlock:[LockInteractionController defaultNetworkRetry] - usesNetwork:YES]; - }]]; - - [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:retryController - animated:YES - completion:nil]; - }; - ++ (LIControllerRetryBlock)defaultNetworkRetry { + LIControllerRetryBlock retryBlock = + ^void(LIControllerBlockingOperation blockingOperation, LIControllerCompletionBlock completionBlock) { + UIAlertController *retryController = + [UIAlertController alertControllerWithTitle:@"Upgrading Signal failed" + message:@"An network error occured while upgrading, please check " + @"your connectivity and try again." + preferredStyle:UIAlertControllerStyleAlert]; + + [retryController + addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"REGISTER_FAILED_TRY_AGAIN", nil) + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *action) { + [self performBlock:blockingOperation + completionBlock:completionBlock + retryBlock:[LockInteractionController defaultNetworkRetry] + usesNetwork:YES]; + }]]; + + [[UIApplication sharedApplication] + .keyWindow.rootViewController presentViewController:retryController + animated:YES + completion:nil]; + }; + return retryBlock; } diff --git a/Signal/src/view controllers/MessageComposeTableViewController.h b/Signal/src/view controllers/MessageComposeTableViewController.h index e126f7fdc..00898a8d7 100644 --- a/Signal/src/view controllers/MessageComposeTableViewController.h +++ b/Signal/src/view controllers/MessageComposeTableViewController.h @@ -1,6 +1,6 @@ // // MessageComposeTableViewController.h -// +// // // Created by Dylan Bourgeois on 02/11/14. // @@ -10,9 +10,9 @@ #import "Contact.h" -#import "JSQMessagesToolbarContentView.h" -#import "JSQMessagesInputToolbar.h" #import "JSQMessagesComposerTextView.h" +#import "JSQMessagesInputToolbar.h" +#import "JSQMessagesToolbarContentView.h" #import "JSQMessagesKeyboardController.h" #import "LocalizableText.h" diff --git a/Signal/src/view controllers/MessageComposeTableViewController.m b/Signal/src/view controllers/MessageComposeTableViewController.m index 2136d6666..2adebcc64 100644 --- a/Signal/src/view controllers/MessageComposeTableViewController.m +++ b/Signal/src/view controllers/MessageComposeTableViewController.m @@ -7,21 +7,22 @@ // #import "MessageComposeTableViewController.h" -#import "Environment.h" -#import "ContactsManager+updater.h" #import #import "ContactTableViewCell.h" +#import "ContactsUpdater.h" +#import "Environment.h" #import "UIColor+OWS.h" #import "UIUtil.h" -@interface MessageComposeTableViewController () -{ - UIButton* sendTextButton; - NSString* currentSearchTerm; - NSArray* contacts; - NSArray* searchResults; +@interface MessageComposeTableViewController () { + UIButton *sendTextButton; + NSString *currentSearchTerm; + NSArray *contacts; + NSArray *searchResults; } @property (nonatomic, strong) UISearchController *searchController; @@ -37,15 +38,15 @@ - (void)viewDidLoad { [super viewDidLoad]; [self.navigationController.navigationBar setTranslucent:NO]; - - contacts = [[Environment getCurrent] contactsManager].signalContacts; + + contacts = [[Environment getCurrent] contactsManager].signalContacts; searchResults = contacts; [self initializeSearch]; - - self.searchController.searchBar.hidden = NO; + + self.searchController.searchBar.hidden = NO; self.searchController.searchBar.backgroundColor = [UIColor whiteColor]; - - self.tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero]; + + self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; [self createLoadingAndBackgroundViews]; self.title = NSLocalizedString(@"MESSAGE_COMPOSEVIEW_TITLE", @""); } @@ -55,37 +56,48 @@ } --(void) viewDidAppear:(BOOL)animated { +- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; - - if([contacts count]==0) { + + if ([contacts count] == 0) { [self showEmptyBackgroundView:YES]; } } --(UILabel*) createLabelWithFirstLine:(NSString*) firstLine andSecondLine:(NSString*)secondLine { - UILabel *label = [[UILabel alloc] init]; - label.textColor = [UIColor grayColor]; - label.font = [UIFont ows_regularFontWithSize:18.f]; +- (UILabel *)createLabelWithFirstLine:(NSString *)firstLine andSecondLine:(NSString *)secondLine { + UILabel *label = [[UILabel alloc] init]; + label.textColor = [UIColor grayColor]; + label.font = [UIFont ows_regularFontWithSize:18.f]; label.textAlignment = NSTextAlignmentCenter; label.numberOfLines = 4; - - NSMutableAttributedString *fullLabelString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@\n%@",firstLine,secondLine]]; - - [fullLabelString addAttribute:NSFontAttributeName value:[UIFont ows_boldFontWithSize:15.f] range:NSMakeRange(0,firstLine.length)]; - [fullLabelString addAttribute:NSFontAttributeName value:[UIFont ows_regularFontWithSize:14.f] range:NSMakeRange(firstLine.length + 1, secondLine.length)]; - [fullLabelString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0,firstLine.length)]; - [fullLabelString addAttribute:NSForegroundColorAttributeName value:[UIColor ows_darkGrayColor] range:NSMakeRange(firstLine.length + 1, secondLine.length)]; + + NSMutableAttributedString *fullLabelString = + [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@\n%@", firstLine, secondLine]]; + + [fullLabelString addAttribute:NSFontAttributeName + value:[UIFont ows_boldFontWithSize:15.f] + range:NSMakeRange(0, firstLine.length)]; + [fullLabelString addAttribute:NSFontAttributeName + value:[UIFont ows_regularFontWithSize:14.f] + range:NSMakeRange(firstLine.length + 1, secondLine.length)]; + [fullLabelString addAttribute:NSForegroundColorAttributeName + value:[UIColor blackColor] + range:NSMakeRange(0, firstLine.length)]; + [fullLabelString addAttribute:NSForegroundColorAttributeName + value:[UIColor ows_darkGrayColor] + range:NSMakeRange(firstLine.length + 1, secondLine.length)]; label.attributedText = fullLabelString; - //250, 66, 140 - [label setFrame:CGRectMake([self marginSize], 100+140, [self contentWidth], 66)]; + // 250, 66, 140 + [label setFrame:CGRectMake([self marginSize], 100 + 140, [self contentWidth], 66)]; return label; } --(UIButton*) createButtonWithTitle:(NSString*)title { - NSDictionary* buttonTextAttributes = @{NSFontAttributeName:[UIFont ows_regularFontWithSize:15.0f], - NSForegroundColorAttributeName:[UIColor ows_materialBlueColor]}; - UIButton* button = [[UIButton alloc] initWithFrame:CGRectMake(0,0,65,24)]; +- (UIButton *)createButtonWithTitle:(NSString *)title { + NSDictionary *buttonTextAttributes = @{ + NSFontAttributeName : [UIFont ows_regularFontWithSize:15.0f], + NSForegroundColorAttributeName : [UIColor ows_materialBlueColor] + }; + UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 65, 24)]; NSMutableAttributedString *attributedTitle = [[NSMutableAttributedString alloc] initWithString:title]; [attributedTitle setAttributes:buttonTextAttributes range:NSMakeRange(0, [attributedTitle length])]; [button setAttributedTitle:attributedTitle forState:UIControlStateNormal]; @@ -93,135 +105,152 @@ return button; } --(void) createLoadingAndBackgroundViews { - // This will be further tweaked per design recs. It must currently be hardcoded (or we can place in separate .xib I suppose) as the controller must be a TableViewController to have access to the native pull to refresh capabilities. That means we can't do a UIView in the storyboard - _loadingBackgroundView = [[UIView alloc] initWithFrame:self.tableView.frame]; +- (void)createLoadingAndBackgroundViews { + // This will be further tweaked per design recs. It must currently be hardcoded (or we can place in separate .xib I + // suppose) as the controller must be a TableViewController to have access to the native pull to refresh + // capabilities. That means we can't do a UIView in the storyboard + _loadingBackgroundView = [[UIView alloc] initWithFrame:self.tableView.frame]; UIImageView *loadingImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"uiEmpty"]]; [loadingImageView setBackgroundColor:[UIColor whiteColor]]; [loadingImageView setContentMode:UIViewContentModeCenter]; - [loadingImageView setFrame:CGRectMake(self.tableView.frame.size.width/2.0f-115.0f/2.0f, 100, 115, 110)]; + [loadingImageView setFrame:CGRectMake(self.tableView.frame.size.width / 2.0f - 115.0f / 2.0f, 100, 115, 110)]; loadingImageView.contentMode = UIViewContentModeCenter; loadingImageView.contentMode = UIViewContentModeScaleAspectFit; - - UIActivityIndicatorView *loadingProgressView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; - [loadingProgressView setFrame:CGRectMake(self.tableView.frame.size.width/2.0f-loadingProgressView.frame.size.width/2.0f, 100+110/2.0f-loadingProgressView.frame.size.height/2.0f, loadingProgressView.frame.size.width, loadingProgressView.frame.size.height)]; + + UIActivityIndicatorView *loadingProgressView = + [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; + [loadingProgressView + setFrame:CGRectMake(self.tableView.frame.size.width / 2.0f - loadingProgressView.frame.size.width / 2.0f, + 100 + 110 / 2.0f - loadingProgressView.frame.size.height / 2.0f, + loadingProgressView.frame.size.width, + loadingProgressView.frame.size.height)]; [loadingProgressView setHidesWhenStopped:NO]; [loadingProgressView startAnimating]; - UILabel *loadingLabel = [self createLabelWithFirstLine:NSLocalizedString(@"LOADING_CONTACTS_LABEL_LINE1", @"") andSecondLine:NSLocalizedString(@"LOADING_CONTACTS_LABEL_LINE2" , @"")]; + UILabel *loadingLabel = [self createLabelWithFirstLine:NSLocalizedString(@"LOADING_CONTACTS_LABEL_LINE1", @"") + andSecondLine:NSLocalizedString(@"LOADING_CONTACTS_LABEL_LINE2", @"")]; [_loadingBackgroundView addSubview:loadingImageView]; [_loadingBackgroundView addSubview:loadingProgressView]; [_loadingBackgroundView addSubview:loadingLabel]; - - _emptyBackgroundView = [[UIView alloc] initWithFrame:self.tableView.frame]; + + _emptyBackgroundView = [[UIView alloc] initWithFrame:self.tableView.frame]; UIImageView *emptyImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"uiEmptyContact"]]; [emptyImageView setBackgroundColor:[UIColor whiteColor]]; [emptyImageView setContentMode:UIViewContentModeCenter]; - [emptyImageView setFrame:CGRectMake(self.tableView.frame.size.width/2.0f-115.0f/2.0f, 100, 115, 110)]; + [emptyImageView setFrame:CGRectMake(self.tableView.frame.size.width / 2.0f - 115.0f / 2.0f, 100, 115, 110)]; emptyImageView.contentMode = UIViewContentModeCenter; emptyImageView.contentMode = UIViewContentModeScaleAspectFit; - UILabel *emptyLabel = [self createLabelWithFirstLine:NSLocalizedString(@"EMPTY_CONTACTS_LABEL_LINE1", @"") andSecondLine:NSLocalizedString(@"EMPTY_CONTACTS_LABEL_LINE2" , @"")]; - - UIButton *inviteContactButton = [self createButtonWithTitle:NSLocalizedString(@"EMPTY_CONTACTS_INVITE_BUTTON", @"")]; - + UILabel *emptyLabel = [self createLabelWithFirstLine:NSLocalizedString(@"EMPTY_CONTACTS_LABEL_LINE1", @"") + andSecondLine:NSLocalizedString(@"EMPTY_CONTACTS_LABEL_LINE2", @"")]; + + UIButton *inviteContactButton = + [self createButtonWithTitle:NSLocalizedString(@"EMPTY_CONTACTS_INVITE_BUTTON", @"")]; + [inviteContactButton addTarget:self action:@selector(sendText) forControlEvents:UIControlEventTouchUpInside]; - [inviteContactButton setFrame:CGRectMake([self marginSize], self.tableView.frame.size.height - 200, [self contentWidth],60)]; + [inviteContactButton + setFrame:CGRectMake([self marginSize], self.tableView.frame.size.height - 200, [self contentWidth], 60)]; [inviteContactButton.titleLabel setTextAlignment:NSTextAlignmentCenter]; - + [_emptyBackgroundView addSubview:emptyImageView]; [_emptyBackgroundView addSubview:emptyLabel]; [_emptyBackgroundView addSubview:inviteContactButton]; - } --(void) showLoadingBackgroundView:(BOOL)show { - if(show) { - _addGroup = self.navigationItem.rightBarButtonItem!=nil ? _addGroup : self.navigationItem.rightBarButtonItem; +- (void)showLoadingBackgroundView:(BOOL)show { + if (show) { + _addGroup = self.navigationItem.rightBarButtonItem != nil ? _addGroup : self.navigationItem.rightBarButtonItem; self.navigationItem.rightBarButtonItem = nil; self.searchController.searchBar.hidden = YES; - self.tableView.backgroundView = _loadingBackgroundView; - self.refreshControl = nil; - self.tableView.backgroundView.opaque = YES; - } - else { + self.tableView.backgroundView = _loadingBackgroundView; + self.refreshControl = nil; + self.tableView.backgroundView.opaque = YES; + } else { [self initializeRefreshControl]; - self.navigationItem.rightBarButtonItem = self.navigationItem.rightBarButtonItem!=nil ? self.navigationItem.rightBarButtonItem : _addGroup; + self.navigationItem.rightBarButtonItem = + self.navigationItem.rightBarButtonItem != nil ? self.navigationItem.rightBarButtonItem : _addGroup; self.searchController.searchBar.hidden = NO; - self.tableView.backgroundView = nil; + self.tableView.backgroundView = nil; } } --(void) showEmptyBackgroundView:(BOOL)show { - - if(show) { +- (void)showEmptyBackgroundView:(BOOL)show { + if (show) { self.refreshControl = nil; - _addGroup = self.navigationItem.rightBarButtonItem!=nil ? _addGroup : self.navigationItem.rightBarButtonItem; - self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[[UIImage imageNamed:@"btnRefresh--white"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] style:UIBarButtonItemStylePlain target:self action:@selector(refreshContacts)]; - self.navigationItem.rightBarButtonItem.imageInsets = UIEdgeInsetsMake(8,8,8,8); - - + _addGroup = self.navigationItem.rightBarButtonItem != nil ? _addGroup : self.navigationItem.rightBarButtonItem; + self.navigationItem.rightBarButtonItem = + [[UIBarButtonItem alloc] initWithImage:[[UIImage imageNamed:@"btnRefresh--white"] + imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] + style:UIBarButtonItemStylePlain + target:self + action:@selector(refreshContacts)]; + self.navigationItem.rightBarButtonItem.imageInsets = UIEdgeInsetsMake(8, 8, 8, 8); + + self.searchController.searchBar.hidden = YES; - self.tableView.backgroundView = _emptyBackgroundView; - self.tableView.backgroundView.opaque = YES; - } - else { + self.tableView.backgroundView = _emptyBackgroundView; + self.tableView.backgroundView.opaque = YES; + } else { [self initializeRefreshControl]; self.refreshControl.enabled = YES; - self.navigationItem.rightBarButtonItem = self.navigationItem.rightBarButtonItem!=nil ? self.navigationItem.rightBarButtonItem : _addGroup; + self.navigationItem.rightBarButtonItem = + self.navigationItem.rightBarButtonItem != nil ? self.navigationItem.rightBarButtonItem : _addGroup; self.searchController.searchBar.hidden = NO; - self.tableView.backgroundView = nil; + self.tableView.backgroundView = nil; } } #pragma mark - Initializers --(void)initializeSearch -{ +- (void)initializeSearch { self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil]; - + self.searchController.searchResultsUpdater = self; - + self.searchController.dimsBackgroundDuringPresentation = NO; - + self.searchController.hidesNavigationBarDuringPresentation = NO; - - self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, self.searchController.searchBar.frame.size.width, 44.0); - + + self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, + self.searchController.searchBar.frame.origin.y, + self.searchController.searchBar.frame.size.width, + 44.0); + self.tableView.tableHeaderView = self.searchController.searchBar; - - + + self.searchController.searchBar.searchBarStyle = UISearchBarStyleMinimal; - self.searchController.searchBar.delegate = self; - self.searchController.searchBar.placeholder = NSLocalizedString(@"SEARCH_BYNAMEORNUMBER_PLACEHOLDER_TEXT", @""); - + self.searchController.searchBar.delegate = self; + self.searchController.searchBar.placeholder = NSLocalizedString(@"SEARCH_BYNAMEORNUMBER_PLACEHOLDER_TEXT", @""); + sendTextButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [sendTextButton setBackgroundColor:[UIColor ows_materialBlueColor]]; [sendTextButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - sendTextButton.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y + 44.0, self.searchController.searchBar.frame.size.width, 44.0); + sendTextButton.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, + self.searchController.searchBar.frame.origin.y + 44.0, + self.searchController.searchBar.frame.size.width, + 44.0); [self.view addSubview:sendTextButton]; sendTextButton.hidden = YES; - + [sendTextButton addTarget:self action:@selector(sendText) forControlEvents:UIControlEventTouchUpInside]; [self initializeRefreshControl]; } --(void)initializeRefreshControl { - UIRefreshControl *refreshControl = [[UIRefreshControl alloc]init]; +- (void)initializeRefreshControl { + UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init]; [refreshControl addTarget:self action:@selector(refreshContacts) forControlEvents:UIControlEventValueChanged]; self.refreshControl = refreshControl; [self.tableView addSubview:self.refreshControl]; - } #pragma mark - UISearchResultsUpdating --(void)updateSearchResultsForSearchController:(UISearchController *)searchController { - +- (void)updateSearchResultsForSearchController:(UISearchController *)searchController { NSString *searchString = [self.searchController.searchBar text]; - + [self filterContentForSearchText:searchString scope:nil]; - + [self.tableView reloadData]; } @@ -230,7 +259,6 @@ - (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope { [self updateSearchResultsForSearchController:self.searchController]; - } - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { @@ -240,27 +268,26 @@ #pragma mark - Filter -- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope -{ +- (void)filterContentForSearchText:(NSString *)searchText scope:(NSString *)scope { // search by contact name or number - NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"(fullName contains[c] %@) OR (allPhoneNumbers contains[c] %@)", searchText, searchText]; + NSPredicate *resultPredicate = [NSPredicate + predicateWithFormat:@"(fullName contains[c] %@) OR (allPhoneNumbers contains[c] %@)", searchText, searchText]; searchResults = [contacts filteredArrayUsingPredicate:resultPredicate]; if (!searchResults.count && _searchController.searchBar.text.length == 0) { searchResults = contacts; } NSString *formattedNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:searchText].toE164; - + // text to a non-signal number if we have no results and a valid phone # if (searchResults.count == 0 && searchText.length > 8 && formattedNumber) { NSString *sendTextTo = NSLocalizedString(@"SEND_SMS_BUTTON", @""); - sendTextTo = [sendTextTo stringByAppendingString:formattedNumber]; + sendTextTo = [sendTextTo stringByAppendingString:formattedNumber]; [sendTextButton setTitle:sendTextTo forState:UIControlStateNormal]; sendTextButton.hidden = NO; - currentSearchTerm = formattedNumber; + currentSearchTerm = formattedNumber; } else { sendTextButton.hidden = YES; } - } @@ -268,81 +295,96 @@ - (void)sendText { NSString *confirmMessage = NSLocalizedString(@"SEND_SMS_CONFIRM_TITLE", @""); - if([currentSearchTerm length]>0) { - confirmMessage = NSLocalizedString(@"SEND_SMS_INVITE_TITLE", @""); + if ([currentSearchTerm length] > 0) { + confirmMessage = NSLocalizedString(@"SEND_SMS_INVITE_TITLE", @""); confirmMessage = [confirmMessage stringByAppendingString:currentSearchTerm]; confirmMessage = [confirmMessage stringByAppendingString:NSLocalizedString(@"QUESTIONMARK_PUNCTUATION", @"")]; } - - UIAlertController *alertController = [UIAlertController - alertControllerWithTitle:NSLocalizedString(@"CONFIRMATION_TITLE", @"") - message:confirmMessage - preferredStyle:UIAlertControllerStyleAlert]; - - UIAlertAction *cancelAction = [UIAlertAction - actionWithTitle:NSLocalizedString(@"Cancel", @"") - style:UIAlertActionStyleCancel - handler:^(UIAlertAction *action) - { - DDLogDebug(@"Cancel action"); - }]; - + + UIAlertController *alertController = + [UIAlertController alertControllerWithTitle:NSLocalizedString(@"CONFIRMATION_TITLE", @"") + message:confirmMessage + preferredStyle:UIAlertControllerStyleAlert]; + + UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", @"") + style:UIAlertActionStyleCancel + handler:^(UIAlertAction *action) { + DDLogDebug(@"Cancel action"); + }]; + UIAlertAction *okAction = [UIAlertAction - actionWithTitle:NSLocalizedString(@"OK", @"") - style:UIAlertActionStyleDefault - handler:^(UIAlertAction *action) { - [self.searchController setActive:NO]; - - UIDevice *device = [UIDevice currentDevice]; - if ([[device model] isEqualToString:@"iPhone"]) { - MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init]; - picker.messageComposeDelegate = self; - - picker.recipients = [currentSearchTerm length]> 0 ? [NSArray arrayWithObject:currentSearchTerm] : nil; - picker.body = [NSLocalizedString(@"SMS_INVITE_BODY", @"") stringByAppendingString:@" https://itunes.apple.com/us/app/signal-private-messenger/id874139669?mt=8"]; - [self presentViewController:picker animated:YES completion:[UIUtil modalCompletionBlock]]; - } else { - // TODO: better backup for iPods (just don't support on) - UIAlertView *notPermitted=[[UIAlertView alloc] initWithTitle:@"" message:NSLocalizedString(@"UNSUPPORTED_FEATURE_ERROR", @"") delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"") otherButtonTitles:nil]; - [notPermitted show]; - } - }]; - + actionWithTitle:NSLocalizedString(@"OK", @"") + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *action) { + [self.searchController setActive:NO]; + + UIDevice *device = [UIDevice currentDevice]; + if ([[device model] isEqualToString:@"iPhone"]) { + MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init]; + picker.messageComposeDelegate = self; + + picker.recipients = + [currentSearchTerm length] > 0 ? [NSArray arrayWithObject:currentSearchTerm] : nil; + picker.body = [NSLocalizedString(@"SMS_INVITE_BODY", @"") + stringByAppendingString: + @" https://itunes.apple.com/us/app/signal-private-messenger/id874139669?mt=8"]; + [self presentViewController:picker animated:YES completion:[UIUtil modalCompletionBlock]]; + } else { + // TODO: better backup for iPods (just don't support on) + UIAlertView *notPermitted = + [[UIAlertView alloc] initWithTitle:@"" + message:NSLocalizedString(@"UNSUPPORTED_FEATURE_ERROR", @"") + delegate:nil + cancelButtonTitle:NSLocalizedString(@"OK", @"") + otherButtonTitles:nil]; + [notPermitted show]; + } + }]; + [alertController addAction:cancelAction]; [alertController addAction:okAction]; - sendTextButton.hidden = YES; + sendTextButton.hidden = YES; self.searchController.searchBar.text = @""; - - [self presentViewController:alertController - animated:YES - completion:[UIUtil modalCompletionBlock]]; + + [self presentViewController:alertController animated:YES completion:[UIUtil modalCompletionBlock]]; } #pragma mark - SMS Composer Delegate // called on completion of message screen -- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult) result -{ +- (void)messageComposeViewController:(MFMessageComposeViewController *)controller + didFinishWithResult:(MessageComposeResult)result { switch (result) { case MessageComposeResultCancelled: break; case MessageComposeResultFailed: { - UIAlertView *warningAlert = [[UIAlertView alloc] initWithTitle:@"" message:NSLocalizedString(@"SEND_SMS_INVITE_FAILURE", @"") delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"") otherButtonTitles:nil]; + UIAlertView *warningAlert = + [[UIAlertView alloc] initWithTitle:@"" + message:NSLocalizedString(@"SEND_SMS_INVITE_FAILURE", @"") + delegate:nil + cancelButtonTitle:NSLocalizedString(@"OK", @"") + otherButtonTitles:nil]; [warningAlert show]; break; } case MessageComposeResultSent: { - [self dismissViewControllerAnimated:NO completion:^{ - DDLogDebug(@"view controller dismissed"); - }]; - UIAlertView *successAlert = [[UIAlertView alloc] initWithTitle:@"" message:NSLocalizedString(@"SEND_SMS_INVITE_SUCCESS", @"") delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"") otherButtonTitles:nil]; + [self dismissViewControllerAnimated:NO + completion:^{ + DDLogDebug(@"view controller dismissed"); + }]; + UIAlertView *successAlert = + [[UIAlertView alloc] initWithTitle:@"" + message:NSLocalizedString(@"SEND_SMS_INVITE_SUCCESS", @"") + delegate:nil + cancelButtonTitle:NSLocalizedString(@"OK", @"") + otherButtonTitles:nil]; [successAlert show]; break; } default: break; } - + [self dismissViewControllerAnimated:YES completion:nil]; } @@ -353,7 +395,6 @@ } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - if (self.searchController.active) { return (NSInteger)[searchResults count]; } else { @@ -363,23 +404,24 @@ - (ContactTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - ContactTableViewCell *cell = (ContactTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"ContactTableViewCell"]; - + ContactTableViewCell *cell = + (ContactTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"ContactTableViewCell"]; + if (cell == nil) { - cell = [[ContactTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"ContactTableViewCell"]; + cell = [[ContactTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault + reuseIdentifier:@"ContactTableViewCell"]; } - + cell.shouldShowContactButtons = NO; - + [cell configureWithContact:[self contactForIndexPath:indexPath]]; - + tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; - + return cell; } --(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath -{ +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 52.0f; } @@ -390,70 +432,70 @@ } --(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSString *identifier = [[[self contactForIndexPath:indexPath] textSecureIdentifiers] firstObject]; - - [self dismissViewControllerAnimated:YES completion:^(){ - [Environment messageIdentifier:identifier withCompose:YES]; - }]; + + [self dismissViewControllerAnimated:YES + completion:^() { + [Environment messageIdentifier:identifier withCompose:YES]; + }]; } --(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath -{ - ContactTableViewCell * cell = (ContactTableViewCell*)[tableView cellForRowAtIndexPath:indexPath]; - cell.accessoryType = UITableViewCellAccessoryNone; +- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { + ContactTableViewCell *cell = (ContactTableViewCell *)[tableView cellForRowAtIndexPath:indexPath]; + cell.accessoryType = UITableViewCellAccessoryNone; } --(Contact*)contactForIndexPath:(NSIndexPath*)indexPath -{ +- (Contact *)contactForIndexPath:(NSIndexPath *)indexPath { Contact *contact = nil; - + if (self.searchController.active) { contact = [searchResults objectAtIndex:(NSUInteger)indexPath.row]; } else { contact = [contacts objectAtIndex:(NSUInteger)indexPath.row]; } - + return contact; } #pragma mark Refresh controls -- (void) updateAfterRefreshTry { +- (void)updateAfterRefreshTry { [self.refreshControl endRefreshing]; - + [self showLoadingBackgroundView:NO]; - if([contacts count]==0) { + if ([contacts count] == 0) { [self showEmptyBackgroundView:YES]; - } - else { + } else { [self showEmptyBackgroundView:NO]; } } - (void)refreshContacts { - [[Environment getCurrent].contactsManager updateSignalContactIntersectionWithSuccess:^{ - contacts = [[Environment getCurrent] contactsManager].signalContacts; - dispatch_async(dispatch_get_main_queue(), ^{ + [[ContactsUpdater sharedUpdater] + updateSignalContactIntersectionWithABContacts:[Environment getCurrent].contactsManager.allContacts + success:^{ + contacts = [[Environment getCurrent] contactsManager].signalContacts; + dispatch_async(dispatch_get_main_queue(), ^{ [self updateSearchResultsForSearchController:self.searchController]; [self.tableView reloadData]; [self updateAfterRefreshTry]; - }); - } failure:^(NSError *error) { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:TIMEOUT - message:TIMEOUT_CONTACTS_DETAIL - delegate:nil - cancelButtonTitle:NSLocalizedString(@"OK", @"") - otherButtonTitles:nil]; - [alert show]; - dispatch_async(dispatch_get_main_queue(), ^{ + }); + } + failure:^(NSError *error) { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:TIMEOUT + message:TIMEOUT_CONTACTS_DETAIL + delegate:nil + cancelButtonTitle:NSLocalizedString(@"OK", @"") + otherButtonTitles:nil]; + [alert show]; + dispatch_async(dispatch_get_main_queue(), ^{ [self updateAfterRefreshTry]; - }); - }]; - - if([contacts count]==0) { + }); + }]; + + if ([contacts count] == 0) { [self showLoadingBackgroundView:YES]; } } @@ -465,13 +507,12 @@ self.searchController.active = NO; } -- (IBAction)closeAction:(id)sender -{ +- (IBAction)closeAction:(id)sender { [self dismissViewControllerAnimated:YES completion:nil]; } - (CGFloat)contentWidth { - return [UIScreen mainScreen].bounds.size.width - 2*[self marginSize]; + return [UIScreen mainScreen].bounds.size.width - 2 * [self marginSize]; } - (CGFloat)marginSize { diff --git a/Signal/src/view controllers/MessagesViewController.h b/Signal/src/view controllers/MessagesViewController.h index d669bdebd..059a3ff6d 100644 --- a/Signal/src/view controllers/MessagesViewController.h +++ b/Signal/src/view controllers/MessagesViewController.h @@ -6,35 +6,38 @@ // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // -#import "JSQMessagesViewController.h" -#import "JSQMessages.h" -#import "TSGroupModel.h" +#import #import #import "APNavigationController.h" -#import +#import "JSQMessages.h" +#import "JSQMessagesViewController.h" +#import "TSGroupModel.h" @class TSThread; -@interface MessagesViewController : JSQMessagesViewController +@interface MessagesViewController : JSQMessagesViewController @property (nonatomic, retain) APNavigationController *navController; -@property (nonatomic,strong) MPMoviePlayerController* videoPlayer; -@property (nonatomic,strong) AVAudioPlayer* audioPlayer; -@property (nonatomic,strong) AVAudioRecorder* audioRecorder; +@property (nonatomic, strong) MPMoviePlayerController *videoPlayer; +@property (nonatomic, strong) AVAudioPlayer *audioPlayer; +@property (nonatomic, strong) AVAudioRecorder *audioRecorder; -- (void)setupWithThread:(TSThread*)thread; -- (void)setupWithTSIdentifier:(NSString*)identifier; -- (void)setupWithTSGroup:(TSGroupModel*)model; +- (void)setupWithThread:(TSThread *)thread; +- (void)setupWithTSIdentifier:(NSString *)identifier; +- (void)setupWithTSGroup:(TSGroupModel *)model; - (void)peekSetup; - (void)popped; - (void)setComposeOnOpen:(BOOL)compose; -- (TSThread*)thread; +- (TSThread *)thread; - (void)popKeyBoard; @end diff --git a/Signal/src/view controllers/MessagesViewController.m b/Signal/src/view controllers/MessagesViewController.m index 5cf678f19..a4fe9940f 100644 --- a/Signal/src/view controllers/MessagesViewController.m +++ b/Signal/src/view controllers/MessagesViewController.m @@ -9,46 +9,35 @@ #import "AppDelegate.h" #import -#import - -#import "MessagesViewController.h" -#import "FullImageViewController.h" -#import "FingerprintViewController.h" -#import "NewGroupViewController.h" -#import "ShowGroupMembersViewController.h" - -#import "SignalKeyingStorage.h" - -#import "JSQCallCollectionViewCell.h" - -#import "UIUtil.h" -#import "DJWActionSheet+OWS.h" -#import - -#import "TSDatabaseView.h" -#import "UIButton+OWS.h" -#import - - -#import "TSMessageAdapter.h" -#import "TSErrorMessage.h" -#import "TSInvalidIdentityKeyErrorMessage.h" -#import "TSIncomingMessage.h" -#import "TSAttachmentPointer.h" -#import "TSAnimatedAdapter.h" -#import "TSVideoAttachmentAdapter.h" #import - -#import "TSMessagesManager+sendMessages.h" -#import "TSMessagesManager+attachments.h" -#import "NSDate+millisecondTimeStamp.h" - -#import "Environment.h" -#import "PhoneManager.h" +#import +#import +#import +#import #import "ContactsManager.h" +#import "DJWActionSheet+OWS.h" +#import "Environment.h" +#import "FingerprintViewController.h" +#import "FullImageViewController.h" +#import "JSQCallCollectionViewCell.h" +#import "MessagesViewController.h" +#import "NSDate+millisecondTimeStamp.h" +#import "NewGroupViewController.h" +#import "PhoneManager.h" #import "PreferencesUtil.h" - +#import "ShowGroupMembersViewController.h" +#import "SignalKeyingStorage.h" #import "TSAdapterCacheManager.h" +#import "TSAttachmentPointer.h" +#import "TSContentAdapters.h" +#import "TSDatabaseView.h" +#import "TSErrorMessage.h" +#import "TSIncomingMessage.h" +#import "TSInvalidIdentityKeyErrorMessage.h" +#import "TSMessagesManager+attachments.h" +#import "TSMessagesManager+sendMessages.h" +#import "UIButton+OWS.h" +#import "UIUtil.h" #define kYapDatabaseRangeLength 50 #define kYapDatabaseRangeMaxLength 300 @@ -58,9 +47,9 @@ #define JSQ_IMAGE_INSET 5 static NSTimeInterval const kTSMessageSentDateShowTimeInterval = 5 * 60; -static NSString *const kUpdateGroupSegueIdentifier = @"updateGroupSegue"; -static NSString *const kFingerprintSegueIdentifier = @"fingerprintSegue"; -static NSString *const kShowGroupMembersSegue = @"showGroupMembersSegue"; +static NSString *const kUpdateGroupSegueIdentifier = @"updateGroupSegue"; +static NSString *const kFingerprintSegueIdentifier = @"fingerprintSegue"; +static NSString *const kShowGroupMembersSegue = @"showGroupMembersSegue"; typedef enum : NSUInteger { kMediaTypePicture, @@ -68,24 +57,24 @@ typedef enum : NSUInteger { } kMediaTypes; @interface MessagesViewController () { - UIImage* tappedImage; + UIImage *tappedImage; BOOL isGroupConversation; - + UIView *_unreadContainer; UIImageView *_unreadBackground; UILabel *_unreadLabel; NSUInteger _unreadCount; } -@property (nonatomic, weak) UIView *navView; +@property (nonatomic, weak) UIView *navView; @property (nonatomic, retain) TSThread *thread; -@property (nonatomic, strong) YapDatabaseConnection *editingDatabaseConnection; -@property (nonatomic, strong) YapDatabaseConnection *uiDatabaseConnection; +@property (nonatomic, strong) YapDatabaseConnection *editingDatabaseConnection; +@property (nonatomic, strong) YapDatabaseConnection *uiDatabaseConnection; @property (nonatomic, strong) YapDatabaseViewMappings *messageMappings; -@property (nonatomic, retain) JSQMessagesBubbleImage *outgoingBubbleImageData; -@property (nonatomic, retain) JSQMessagesBubbleImage *incomingBubbleImageData; -@property (nonatomic, retain) JSQMessagesBubbleImage *currentlyOutgoingBubbleImageData; -@property (nonatomic, retain) JSQMessagesBubbleImage *outgoingMessageFailedImageData; +@property (nonatomic, retain) JSQMessagesBubbleImage *outgoingBubbleImageData; +@property (nonatomic, retain) JSQMessagesBubbleImage *incomingBubbleImageData; +@property (nonatomic, retain) JSQMessagesBubbleImage *currentlyOutgoingBubbleImageData; +@property (nonatomic, retain) JSQMessagesBubbleImage *outgoingMessageFailedImageData; @property (nonatomic, strong) NSTimer *audioPlayerPoller; @property (nonatomic, strong) TSVideoAttachmentAdapter *currentMediaAdapter; @@ -101,12 +90,12 @@ typedef enum : NSUInteger { @property NSUInteger page; @property BOOL isVisible; -@property (nonatomic) BOOL composeOnOpen; -@property (nonatomic) BOOL peek; +@property (nonatomic) BOOL composeOnOpen; +@property (nonatomic) BOOL peek; @end -@interface UINavigationItem(){ +@interface UINavigationItem () { UIView *backButtonView; } @end @@ -115,21 +104,26 @@ typedef enum : NSUInteger { - (void)setupWithTSIdentifier:(NSString *)identifier { [self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - self.thread = [TSContactThread getOrCreateThreadWithContactId:identifier transaction:transaction]; + self.thread = [TSContactThread getOrCreateThreadWithContactId:identifier transaction:transaction]; }]; } -- (void)setupWithTSGroup:(TSGroupModel*)model { +- (void)setupWithTSGroup:(TSGroupModel *)model { [self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - self.thread = [TSGroupThread getOrCreateThreadWithGroupModel:model transaction:transaction]; + self.thread = [TSGroupThread getOrCreateThreadWithGroupModel:model transaction:transaction]; }]; - - TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:self.thread messageBody:@"" attachments:[[NSMutableArray alloc] init]]; + + TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] + inThread:self.thread + messageBody:@"" + attachments:[[NSMutableArray alloc] init]]; message.groupMetaMessage = TSGroupMessageNew; - if(model.groupImage != nil) { - [[TSMessagesManager sharedManager] sendAttachment:UIImagePNGRepresentation(model.groupImage) contentType:@"image/png" inMessage:message thread:self.thread]; - } - else { + if (model.groupImage != nil) { + [[TSMessagesManager sharedManager] sendAttachment:UIImagePNGRepresentation(model.groupImage) + contentType:@"image/png" + inMessage:message + thread:self.thread]; + } else { [[TSMessagesManager sharedManager] sendMessage:message inThread:self.thread success:nil failure:nil]; } isGroupConversation = YES; @@ -150,7 +144,7 @@ typedef enum : NSUInteger { } - (void)setupWithThread:(TSThread *)thread { - self.thread = thread; + self.thread = thread; isGroupConversation = [self.thread isKindOfClass:[TSGroupThread class]]; } @@ -163,14 +157,15 @@ typedef enum : NSUInteger { [self inputToolbar].hidden = YES; return; } - - if([_thread isKindOfClass:[TSGroupThread class]] && ![((TSGroupThread*)_thread).groupModel.groupMemberIds containsObject:[SignalKeyingStorage.localNumber toE164]]) { - [self inputToolbar].hidden= YES; // user has requested they leave the group. further sends disallowed + + if ([_thread isKindOfClass:[TSGroupThread class]] && + ![((TSGroupThread *)_thread).groupModel.groupMemberIds containsObject:[TSAccountManager localNumber]]) { + [self inputToolbar].hidden = YES; // user has requested they leave the group. further sends disallowed self.navigationItem.rightBarButtonItem = nil; // further group action disallowed - } else if(![self isTextSecureReachable] ){ - [self inputToolbar].hidden= YES; // only RedPhone + } else if (![self isTextSecureReachable]) { + [self inputToolbar].hidden = YES; // only RedPhone } else { - [self inputToolbar].hidden= NO; + [self inputToolbar].hidden = NO; [self loadDraftInCompose]; } } @@ -179,73 +174,89 @@ typedef enum : NSUInteger { [super viewDidLoad]; _isVisible = NO; [self.navigationController.navigationBar setTranslucent:NO]; - - _showFingerprintDisplay = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(showFingerprint)]; - - _toggleContactPhoneDisplay = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(toggleContactPhone)]; + + _showFingerprintDisplay = + [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(showFingerprint)]; + + _toggleContactPhoneDisplay = + [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(toggleContactPhone)]; _toggleContactPhoneDisplay.numberOfTapsRequired = 1; - - _messageButton = [UIButton ows_blueButtonWithTitle:NSLocalizedString(@"SEND_BUTTON_TITLE", @"")]; + + _messageButton = [UIButton ows_blueButtonWithTitle:NSLocalizedString(@"SEND_BUTTON_TITLE", @"")]; _messageButton.enabled = FALSE; _messageButton.titleLabel.adjustsFontSizeToFitWidth = YES; - + _attachButton = [[UIButton alloc] init]; - [_attachButton setFrame:CGRectMake(0, 0, JSQ_TOOLBAR_ICON_WIDTH+JSQ_IMAGE_INSET*2, JSQ_TOOLBAR_ICON_HEIGHT+JSQ_IMAGE_INSET*2)]; - _attachButton.imageEdgeInsets = UIEdgeInsetsMake(JSQ_IMAGE_INSET, JSQ_IMAGE_INSET, JSQ_IMAGE_INSET, JSQ_IMAGE_INSET); + [_attachButton setFrame:CGRectMake(0, + 0, + JSQ_TOOLBAR_ICON_WIDTH + JSQ_IMAGE_INSET * 2, + JSQ_TOOLBAR_ICON_HEIGHT + JSQ_IMAGE_INSET * 2)]; + _attachButton.imageEdgeInsets = + UIEdgeInsetsMake(JSQ_IMAGE_INSET, JSQ_IMAGE_INSET, JSQ_IMAGE_INSET, JSQ_IMAGE_INSET); [_attachButton setImage:[UIImage imageNamed:@"btnAttachments--blue"] forState:UIControlStateNormal]; - + [self markAllMessagesAsRead]; - + [self initializeBubbles]; [self initializeTextView]; - self.messageMappings = [[YapDatabaseViewMappings alloc] initWithGroups:@[self.thread.uniqueId] + self.messageMappings = [[YapDatabaseViewMappings alloc] initWithGroups:@[ self.thread.uniqueId ] view:TSMessageDatabaseViewExtensionName]; - + self.page = 0; - + [self updateRangeOptionsForPage:self.page]; - + [self.uiDatabaseConnection beginLongLivedReadTransaction]; [self.uiDatabaseConnection asyncReadWithBlock:^(YapDatabaseReadTransaction *transaction) { - [self.messageMappings updateWithTransaction:transaction]; - [self.collectionView reloadData]; + [self.messageMappings updateWithTransaction:transaction]; + [self.collectionView reloadData]; }]; - + [self initializeCollectionViewLayout]; - - self.senderId = ME_MESSAGE_IDENTIFIER - self.senderDisplayName = ME_MESSAGE_IDENTIFIER - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startReadTimer) - name:UIApplicationWillEnterForegroundNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cancelReadTimer) - name:UIApplicationDidEnterBackgroundNotification object:nil]; - - self.navigationController.interactivePopGestureRecognizer.delegate = self; // Swipe back to inbox fix. See http://stackoverflow.com/questions/19054625/changing-back-button-in-ios-7-disables-swipe-to-navigate-back + + self.senderId = ME_MESSAGE_IDENTIFIER self.senderDisplayName = ME_MESSAGE_IDENTIFIER + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(startReadTimer) + name:UIApplicationWillEnterForegroundNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(cancelReadTimer) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; + + self.navigationController.interactivePopGestureRecognizer.delegate = self; // Swipe back to inbox fix. See + // http://stackoverflow.com/questions/19054625/changing-back-button-in-ios-7-disables-swipe-to-navigate-back } - (void)initializeTextView { - [self.inputToolbar.contentView.textView setFont:[UIFont ows_regularFontWithSize:17.f]]; - self.inputToolbar.contentView.leftBarButtonItem = _attachButton; - + [self.inputToolbar.contentView.textView setFont:[UIFont ows_regularFontWithSize:17.f]]; + self.inputToolbar.contentView.leftBarButtonItem = _attachButton; + self.inputToolbar.contentView.rightBarButtonItem = _messageButton; } --(void)viewWillAppear:(BOOL)animated { +- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self initializeToolbars]; - + [self.collectionView reloadData]; NSInteger numberOfMessages = (NSInteger)[self.messageMappings numberOfItemsInGroup:self.thread.uniqueId]; - + if (numberOfMessages > 0) { - NSIndexPath * lastCellIndexPath = [NSIndexPath indexPathForRow:numberOfMessages-1 inSection:0]; - [self.collectionView scrollToItemAtIndexPath:lastCellIndexPath atScrollPosition:UICollectionViewScrollPositionBottom animated:NO]; + NSIndexPath *lastCellIndexPath = [NSIndexPath indexPathForRow:numberOfMessages - 1 inSection:0]; + [self.collectionView scrollToItemAtIndexPath:lastCellIndexPath + atScrollPosition:UICollectionViewScrollPositionBottom + animated:NO]; } } - (void)startReadTimer { - self.readTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(markAllMessagesAsRead) userInfo:nil repeats:YES]; + self.readTimer = [NSTimer scheduledTimerWithTimeInterval:1 + target:self + selector:@selector(markAllMessagesAsRead) + userInfo:nil + repeats:YES]; } - (void)cancelReadTimer { @@ -258,9 +269,9 @@ typedef enum : NSUInteger { [self startReadTimer]; _isVisible = YES; [self initializeTitleLabelGestureRecognizer]; - + [self updateBackButtonAsync]; - + if (_composeOnOpen) { [self popKeyBoard]; } @@ -268,44 +279,46 @@ typedef enum : NSUInteger { - (void)updateBackButtonAsync { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - NSUInteger count = [[TSMessagesManager sharedManager] unreadMessagesCountExcept:self.thread]; - dispatch_async(dispatch_get_main_queue() , ^{ - if (self) { - [self setUnreadCount:count]; - } - }); + NSUInteger count = [[TSMessagesManager sharedManager] unreadMessagesCountExcept:self.thread]; + dispatch_async(dispatch_get_main_queue(), ^{ + if (self) { + [self setUnreadCount:count]; + } + }); }); } - (void)viewWillDisappear:(BOOL)animated { - if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) { + if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound) { // back button was pressed. [self.navController hideDropDown:self]; } [super viewWillDisappear:animated]; [_unreadContainer removeFromSuperview]; _unreadContainer = nil; - + [_audioPlayerPoller invalidate]; [_audioPlayer stop]; - + // reset all audio bars to 0 JSQMessagesCollectionView *collectionView = self.collectionView; - NSInteger num_bubbles = [self collectionView:collectionView numberOfItemsInSection:0]; - for (NSInteger i=0; i0) { + if ([textView.text length] > 0) { self.inputToolbar.contentView.rightBarButtonItem.enabled = YES; - } - else { + } else { self.inputToolbar.contentView.rightBarButtonItem.enabled = NO; } - } #pragma mark - JSQMessagesViewController method overrides @@ -625,13 +673,15 @@ typedef enum : NSUInteger { withMessageText:(NSString *)text senderId:(NSString *)senderId senderDisplayName:(NSString *)senderDisplayName - date:(NSDate *)date -{ + date:(NSDate *)date { if (text.length > 0) { [JSQSystemSoundPlayer jsq_playMessageSentSound]; - - TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:self.thread messageBody:text attachments:nil]; - + + TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] + inThread:self.thread + messageBody:text + attachments:nil]; + [[TSMessagesManager sharedManager] sendMessage:message inThread:self.thread success:nil failure:nil]; [self finishSendingMessage]; } @@ -639,15 +689,15 @@ typedef enum : NSUInteger { #pragma mark - JSQMessages CollectionView DataSource -- (id)collectionView:(JSQMessagesCollectionView *)collectionView messageDataForItemAtIndexPath:(NSIndexPath *)indexPath -{ +- (id)collectionView:(JSQMessagesCollectionView *)collectionView + messageDataForItemAtIndexPath:(NSIndexPath *)indexPath { return [self messageAtIndexPath:indexPath]; } -- (id)collectionView:(JSQMessagesCollectionView *)collectionView messageBubbleImageDataForItemAtIndexPath:(NSIndexPath *)indexPath -{ +- (id)collectionView:(JSQMessagesCollectionView *)collectionView + messageBubbleImageDataForItemAtIndexPath:(NSIndexPath *)indexPath { id message = [self messageAtIndexPath:indexPath]; - + if ([message.senderId isEqualToString:self.senderId]) { switch (message.messageState) { case TSOutgoingMessageStateUnsent: @@ -658,21 +708,21 @@ typedef enum : NSUInteger { return self.outgoingBubbleImageData; } } - + return self.incomingBubbleImageData; } -- (id)collectionView:(JSQMessagesCollectionView *)collectionView avatarImageDataForItemAtIndexPath:(NSIndexPath *)indexPath -{ +- (id)collectionView:(JSQMessagesCollectionView *)collectionView + avatarImageDataForItemAtIndexPath:(NSIndexPath *)indexPath { return nil; } #pragma mark - UICollectionView DataSource -- (UICollectionViewCell *)collectionView:(JSQMessagesCollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath -{ - TSMessageAdapter * msg = [self messageAtIndexPath:indexPath]; - +- (UICollectionViewCell *)collectionView:(JSQMessagesCollectionView *)collectionView + cellForItemAtIndexPath:(NSIndexPath *)indexPath { + TSMessageAdapter *msg = [self messageAtIndexPath:indexPath]; + switch (msg.messageType) { case TSIncomingMessageAdapter: return [self loadIncomingMessageCellForMessage:msg atIndexPath:indexPath]; @@ -684,7 +734,7 @@ typedef enum : NSUInteger { return [self loadInfoMessageCellForMessage:msg atIndexPath:indexPath]; case TSErrorMessageAdapter: return [self loadErrorMessageCellForMessage:msg atIndexPath:indexPath]; - + default: DDLogError(@"Something went wrong"); return nil; @@ -693,72 +743,80 @@ typedef enum : NSUInteger { #pragma mark - Loading message cells --(JSQMessagesCollectionViewCell*)loadIncomingMessageCellForMessage:(id)message atIndexPath:(NSIndexPath*)indexPath -{ - JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:self.collectionView cellForItemAtIndexPath:indexPath]; +- (JSQMessagesCollectionViewCell *)loadIncomingMessageCellForMessage:(id)message + atIndexPath:(NSIndexPath *)indexPath { + JSQMessagesCollectionViewCell *cell = + (JSQMessagesCollectionViewCell *)[super collectionView:self.collectionView cellForItemAtIndexPath:indexPath]; if (!message.isMediaMessage) { cell.textView.textColor = [UIColor ows_blackColor]; - cell.textView.linkTextAttributes = @{ NSForegroundColorAttributeName : cell.textView.textColor, - NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) }; + cell.textView.linkTextAttributes = @{ + NSForegroundColorAttributeName : cell.textView.textColor, + NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) + }; } - + return cell; } --(JSQMessagesCollectionViewCell*)loadOutgoingCellForMessage:(id)message atIndexPath:(NSIndexPath*)indexPath -{ - JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:self.collectionView cellForItemAtIndexPath:indexPath]; - if (!message.isMediaMessage) - { +- (JSQMessagesCollectionViewCell *)loadOutgoingCellForMessage:(id)message + atIndexPath:(NSIndexPath *)indexPath { + JSQMessagesCollectionViewCell *cell = + (JSQMessagesCollectionViewCell *)[super collectionView:self.collectionView cellForItemAtIndexPath:indexPath]; + if (!message.isMediaMessage) { cell.textView.textColor = [UIColor whiteColor]; - cell.textView.linkTextAttributes = @{ NSForegroundColorAttributeName : cell.textView.textColor, - NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) }; + cell.textView.linkTextAttributes = @{ + NSForegroundColorAttributeName : cell.textView.textColor, + NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) + }; } - + return cell; } --(JSQCallCollectionViewCell*)loadCallCellForCall:(id)call atIndexPath:(NSIndexPath*)indexPath -{ - JSQCallCollectionViewCell *cell = (JSQCallCollectionViewCell *)[super collectionView:self.collectionView cellForItemAtIndexPath:indexPath]; +- (JSQCallCollectionViewCell *)loadCallCellForCall:(id)call atIndexPath:(NSIndexPath *)indexPath { + JSQCallCollectionViewCell *cell = + (JSQCallCollectionViewCell *)[super collectionView:self.collectionView cellForItemAtIndexPath:indexPath]; return cell; } --(JSQDisplayedMessageCollectionViewCell *)loadInfoMessageCellForMessage:(id)message atIndexPath:(NSIndexPath*)indexPath -{ - JSQDisplayedMessageCollectionViewCell * cell = (JSQDisplayedMessageCollectionViewCell *)[super collectionView:self.collectionView cellForItemAtIndexPath:indexPath]; +- (JSQDisplayedMessageCollectionViewCell *)loadInfoMessageCellForMessage:(id)message + atIndexPath:(NSIndexPath *)indexPath { + JSQDisplayedMessageCollectionViewCell *cell = + (JSQDisplayedMessageCollectionViewCell *)[super collectionView:self.collectionView + cellForItemAtIndexPath:indexPath]; return cell; } --(JSQDisplayedMessageCollectionViewCell *)loadErrorMessageCellForMessage:(id)message atIndexPath:(NSIndexPath*)indexPath -{ - JSQDisplayedMessageCollectionViewCell * cell = (JSQDisplayedMessageCollectionViewCell *)[super collectionView:self.collectionView cellForItemAtIndexPath:indexPath]; +- (JSQDisplayedMessageCollectionViewCell *)loadErrorMessageCellForMessage:(id)message + atIndexPath:(NSIndexPath *)indexPath { + JSQDisplayedMessageCollectionViewCell *cell = + (JSQDisplayedMessageCollectionViewCell *)[super collectionView:self.collectionView + cellForItemAtIndexPath:indexPath]; return cell; } #pragma mark - Adjusting cell label heights - (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView - layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath -{ + layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout + heightForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath { if ([self showDateAtIndexPath:indexPath]) { return kJSQMessagesCollectionViewCellLabelHeightDefault; } - + return 0.0f; } -- (BOOL)showDateAtIndexPath:(NSIndexPath *)indexPath -{ +- (BOOL)showDateAtIndexPath:(NSIndexPath *)indexPath { BOOL showDate = NO; if (indexPath.row == 0) { showDate = YES; - } - else { - TSMessageAdapter *currentMessage = [self messageAtIndexPath:indexPath]; - - TSMessageAdapter *previousMessage = [self messageAtIndexPath:[NSIndexPath indexPathForItem:indexPath.row-1 inSection:indexPath.section]]; - + } else { + TSMessageAdapter *currentMessage = [self messageAtIndexPath:indexPath]; + + TSMessageAdapter *previousMessage = + [self messageAtIndexPath:[NSIndexPath indexPathForItem:indexPath.row - 1 inSection:indexPath.section]]; + NSTimeInterval timeDifference = [currentMessage.date timeIntervalSinceDate:previousMessage.date]; if (timeDifference > kTSMessageSentDateShowTimeInterval) { showDate = YES; @@ -767,94 +825,94 @@ typedef enum : NSUInteger { return showDate; } --(NSAttributedString*)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath -{ - +- (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView + attributedTextForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath { if ([self showDateAtIndexPath:indexPath]) { TSMessageAdapter *currentMessage = [self messageAtIndexPath:indexPath]; - + return [[JSQMessagesTimestampFormatter sharedFormatter] attributedTimestampForDate:currentMessage.date]; } - + return nil; } --(BOOL)shouldShowMessageStatusAtIndexPath:(NSIndexPath*)indexPath -{ +- (BOOL)shouldShowMessageStatusAtIndexPath:(NSIndexPath *)indexPath { TSMessageAdapter *currentMessage = [self messageAtIndexPath:indexPath]; - + // If message failed, say that message should be tapped to retry; - if (currentMessage.messageType == TSOutgoingMessageAdapter - && currentMessage.messageState == TSOutgoingMessageStateUnsent) { + if (currentMessage.messageType == TSOutgoingMessageAdapter && + currentMessage.messageState == TSOutgoingMessageStateUnsent) { return YES; } - - if([self.thread isKindOfClass:[TSGroupThread class]]) { + + if ([self.thread isKindOfClass:[TSGroupThread class]]) { return currentMessage.messageType == TSIncomingMessageAdapter; } else { - if (indexPath.item == [self.collectionView numberOfItemsInSection:indexPath.section]-1) { + if (indexPath.item == [self.collectionView numberOfItemsInSection:indexPath.section] - 1) { return [self isMessageOutgoingAndDelivered:currentMessage]; } - + if (![self isMessageOutgoingAndDelivered:currentMessage]) { return NO; } - + TSMessageAdapter *nextMessage = [self nextOutgoingMessage:indexPath]; return ![self isMessageOutgoingAndDelivered:nextMessage]; } } --(TSMessageAdapter*)nextOutgoingMessage:(NSIndexPath*)indexPath -{ - TSMessageAdapter * nextMessage = [self messageAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row+1 inSection:indexPath.section]]; +- (TSMessageAdapter *)nextOutgoingMessage:(NSIndexPath *)indexPath { + TSMessageAdapter *nextMessage = + [self messageAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row + 1 inSection:indexPath.section]]; int i = 1; - - while (indexPath.item+i < [self.collectionView numberOfItemsInSection:indexPath.section]-1 && ![self isMessageOutgoingAndDelivered:nextMessage]) { + + while (indexPath.item + i < [self.collectionView numberOfItemsInSection:indexPath.section] - 1 && + ![self isMessageOutgoingAndDelivered:nextMessage]) { i++; - nextMessage = [self messageAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row+i inSection:indexPath.section]]; + nextMessage = + [self messageAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row + i inSection:indexPath.section]]; } - + return nextMessage; } --(BOOL)isMessageOutgoingAndDelivered:(TSMessageAdapter*)message -{ +- (BOOL)isMessageOutgoingAndDelivered:(TSMessageAdapter *)message { return message.messageType == TSOutgoingMessageAdapter && message.messageState == TSOutgoingMessageStateDelivered; } --(NSAttributedString*)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellBottomLabelAtIndexPath:(NSIndexPath *)indexPath { - TSMessageAdapter *msg = [self messageAtIndexPath:indexPath]; +- (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView + attributedTextForCellBottomLabelAtIndexPath:(NSIndexPath *)indexPath { + TSMessageAdapter *msg = [self messageAtIndexPath:indexPath]; NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init]; - textAttachment.bounds = CGRectMake(0, 0, 11.0f, 10.0f); - + textAttachment.bounds = CGRectMake(0, 0, 11.0f, 10.0f); + if ([self shouldShowMessageStatusAtIndexPath:indexPath]) { - if (msg.messageType == TSOutgoingMessageAdapter - && msg.messageState == TSOutgoingMessageStateUnsent) { - NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc]initWithString:NSLocalizedString(@"FAILED_SENDING_TEXT", nil)]; + if (msg.messageType == TSOutgoingMessageAdapter && msg.messageState == TSOutgoingMessageStateUnsent) { + NSMutableAttributedString *attrStr = + [[NSMutableAttributedString alloc] initWithString:NSLocalizedString(@"FAILED_SENDING_TEXT", nil)]; [attrStr appendAttributedString:[NSAttributedString attributedStringWithAttachment:textAttachment]]; return attrStr; } - - if([self.thread isKindOfClass:[TSGroupThread class]]) { + + if ([self.thread isKindOfClass:[TSGroupThread class]]) { NSString *name = [[Environment getCurrent].contactsManager nameStringForPhoneIdentifier:msg.senderId]; - name = name ? name : msg.senderId; - + name = name ? name : msg.senderId; + if (!name) { name = @""; } - - NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc]initWithString:name]; + + NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:name]; [attrStr appendAttributedString:[NSAttributedString attributedStringWithAttachment:textAttachment]]; - + return attrStr; - } - else { + } else { _lastDeliveredMessageIndexPath = indexPath; - NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc]initWithString:NSLocalizedString(@"DELIVERED_MESSAGE_TEXT", @"")]; + NSMutableAttributedString *attrStr = + [[NSMutableAttributedString alloc] initWithString:NSLocalizedString(@"DELIVERED_MESSAGE_TEXT", @"")]; [attrStr appendAttributedString:[NSAttributedString attributedStringWithAttachment:textAttachment]]; - + return attrStr; } } @@ -862,131 +920,142 @@ typedef enum : NSUInteger { } - (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView - layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForCellBottomLabelAtIndexPath:(NSIndexPath *)indexPath -{ + layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout + heightForCellBottomLabelAtIndexPath:(NSIndexPath *)indexPath { if ([self shouldShowMessageStatusAtIndexPath:indexPath]) { return 16.0f; } - + return 0.0f; } #pragma mark - Actions -- (void)collectionView:(JSQMessagesCollectionView *)collectionView didTapMessageBubbleAtIndexPath:(NSIndexPath *)indexPath -{ - TSMessageAdapter *messageItem = [collectionView.dataSource collectionView:collectionView messageDataForItemAtIndexPath:indexPath]; - TSInteraction *interaction = [self interactionAtIndexPath:indexPath]; - +- (void)collectionView:(JSQMessagesCollectionView *)collectionView + didTapMessageBubbleAtIndexPath:(NSIndexPath *)indexPath { + TSMessageAdapter *messageItem = + [collectionView.dataSource collectionView:collectionView messageDataForItemAtIndexPath:indexPath]; + TSInteraction *interaction = [self interactionAtIndexPath:indexPath]; + switch (messageItem.messageType) { case TSOutgoingMessageAdapter: if (messageItem.messageState == TSOutgoingMessageStateUnsent) { - [self handleUnsentMessageTap:(TSOutgoingMessage*)interaction]; + [self handleUnsentMessageTap:(TSOutgoingMessage *)interaction]; } - case TSIncomingMessageAdapter:{ - + case TSIncomingMessageAdapter: { BOOL isMediaMessage = [messageItem isMediaMessage]; - + if (isMediaMessage) { - if([[messageItem media] isKindOfClass:[TSPhotoAdapter class]]) { - TSPhotoAdapter* messageMedia = (TSPhotoAdapter*)[messageItem media]; - + if ([[messageItem media] isKindOfClass:[TSPhotoAdapter class]]) { + TSPhotoAdapter *messageMedia = (TSPhotoAdapter *)[messageItem media]; + if ([messageMedia isImage]) { - tappedImage = ((UIImageView*)[messageMedia mediaView]).image; - CGRect convertedRect = [self.collectionView convertRect:[collectionView cellForItemAtIndexPath:indexPath].frame toView:nil]; + tappedImage = ((UIImageView *)[messageMedia mediaView]).image; + CGRect convertedRect = + [self.collectionView convertRect:[collectionView cellForItemAtIndexPath:indexPath].frame + toView:nil]; __block TSAttachment *attachment = nil; [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - attachment = [TSAttachment fetchObjectWithUniqueID:messageMedia.attachmentId transaction:transaction]; + attachment = + [TSAttachment fetchObjectWithUniqueID:messageMedia.attachmentId transaction:transaction]; }]; - + if ([attachment isKindOfClass:[TSAttachmentStream class]]) { - TSAttachmentStream *attStream = (TSAttachmentStream*)attachment; - FullImageViewController * vc = [[FullImageViewController alloc] initWithAttachment:attStream - fromRect:convertedRect - forInteraction:[self interactionAtIndexPath:indexPath] - isAnimated:NO]; - + TSAttachmentStream *attStream = (TSAttachmentStream *)attachment; + FullImageViewController *vc = [[FullImageViewController alloc] + initWithAttachment:attStream + fromRect:convertedRect + forInteraction:[self interactionAtIndexPath:indexPath] + isAnimated:NO]; + [vc presentFromViewController:self.navigationController]; } } else { DDLogWarn(@"Currently unsupported"); } - } - else if ([[messageItem media] isKindOfClass:[TSAnimatedAdapter class]]) { + } else if ([[messageItem media] isKindOfClass:[TSAnimatedAdapter class]]) { // Show animated image full-screen - TSAnimatedAdapter* messageMedia = (TSAnimatedAdapter*)[messageItem media]; - tappedImage = ((UIImageView*)[messageMedia mediaView]).image; - CGRect convertedRect = [self.collectionView convertRect:[collectionView cellForItemAtIndexPath:indexPath].frame toView:nil]; - __block TSAttachment* attachment = nil; - [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction* transaction) { - attachment = [TSAttachment fetchObjectWithUniqueID:messageMedia.attachmentId transaction:transaction]; - }]; - if ([attachment isKindOfClass:[TSAttachmentStream class]]) { - TSAttachmentStream* attStream = (TSAttachmentStream*)attachment; - FullImageViewController* vc = [[FullImageViewController alloc] initWithAttachment:attStream - fromRect:convertedRect - forInteraction:[self interactionAtIndexPath:indexPath] - isAnimated:YES]; - [vc presentFromViewController:self.navigationController]; - } - - } - else if([[messageItem media] isKindOfClass:[TSVideoAttachmentAdapter class]]){ - // fileurl disappeared should look up in db as before. will do refactor - // full screen, check this setup with a .mov - TSVideoAttachmentAdapter* messageMedia = (TSVideoAttachmentAdapter*)[messageItem media]; - _currentMediaAdapter = messageMedia; + TSAnimatedAdapter *messageMedia = (TSAnimatedAdapter *)[messageItem media]; + tappedImage = ((UIImageView *)[messageMedia mediaView]).image; + CGRect convertedRect = + [self.collectionView convertRect:[collectionView cellForItemAtIndexPath:indexPath].frame + toView:nil]; __block TSAttachment *attachment = nil; [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - attachment = [TSAttachment fetchObjectWithUniqueID:messageMedia.attachmentId transaction:transaction]; + attachment = + [TSAttachment fetchObjectWithUniqueID:messageMedia.attachmentId transaction:transaction]; }]; - if ([attachment isKindOfClass:[TSAttachmentStream class]]) { - TSAttachmentStream *attStream = (TSAttachmentStream*)attachment; - NSFileManager *fileManager = [NSFileManager defaultManager]; - if([messageMedia isVideo]) { + TSAttachmentStream *attStream = (TSAttachmentStream *)attachment; + FullImageViewController *vc = + [[FullImageViewController alloc] initWithAttachment:attStream + fromRect:convertedRect + forInteraction:[self interactionAtIndexPath:indexPath] + isAnimated:YES]; + [vc presentFromViewController:self.navigationController]; + } + } else if ([[messageItem media] isKindOfClass:[TSVideoAttachmentAdapter class]]) { + // fileurl disappeared should look up in db as before. will do refactor + // full screen, check this setup with a .mov + TSVideoAttachmentAdapter *messageMedia = (TSVideoAttachmentAdapter *)[messageItem media]; + _currentMediaAdapter = messageMedia; + __block TSAttachment *attachment = nil; + [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { + attachment = + [TSAttachment fetchObjectWithUniqueID:messageMedia.attachmentId transaction:transaction]; + }]; + + if ([attachment isKindOfClass:[TSAttachmentStream class]]) { + TSAttachmentStream *attStream = (TSAttachmentStream *)attachment; + NSFileManager *fileManager = [NSFileManager defaultManager]; + if ([messageMedia isVideo]) { if ([fileManager fileExistsAtPath:[attStream.mediaURL path]]) { [self dismissKeyBoard]; _videoPlayer = [[MPMoviePlayerController alloc] initWithContentURL:attStream.mediaURL]; [_videoPlayer prepareToPlay]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(moviePlayBackDidFinish:) - name:MPMoviePlayerPlaybackDidFinishNotification - object: _videoPlayer]; - - _videoPlayer.controlStyle = MPMovieControlStyleDefault; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(moviePlayBackDidFinish:) + name:MPMoviePlayerPlaybackDidFinishNotification + object:_videoPlayer]; + + _videoPlayer.controlStyle = MPMovieControlStyleDefault; _videoPlayer.shouldAutoplay = YES; - [self.view addSubview: _videoPlayer.view]; + [self.view addSubview:_videoPlayer.view]; [_videoPlayer setFullscreen:YES animated:YES]; } - } else if([messageMedia isAudio]){ + } else if ([messageMedia isAudio]) { if (messageMedia.isAudioPlaying) { // if you had started playing an audio msg and now you're tapping it to pause messageMedia.isAudioPlaying = NO; [_audioPlayer pause]; messageMedia.isPaused = YES; [_audioPlayerPoller invalidate]; - double current = [_audioPlayer currentTime]/[_audioPlayer duration]; + double current = [_audioPlayer currentTime] / [_audioPlayer duration]; [messageMedia setAudioProgressFromFloat:(float)current]; [messageMedia setAudioIconToPlay]; } else { BOOL isResuming = NO; [_audioPlayerPoller invalidate]; - + // loop through all the other bubbles and set their isPlaying to false NSInteger num_bubbles = [self collectionView:collectionView numberOfItemsInSection:0]; - for (NSInteger i=0; i= kYapDatabaseRangeLength; - - if (!canLoadFullRange) { - item = numberOfMessagesToLoad; - } + + NSUInteger numberOfVisibleMessages = [self.messageMappings numberOfItemsInGroup:self.thread.uniqueId]; + NSUInteger numberOfTotalMessages = + [[transaction ext:TSMessageDatabaseViewExtensionName] numberOfItemsInGroup:self.thread.uniqueId]; + NSUInteger numberOfMessagesToLoad = numberOfTotalMessages - numberOfVisibleMessages; + + BOOL canLoadFullRange = numberOfMessagesToLoad >= kYapDatabaseRangeLength; + + if (!canLoadFullRange) { + item = numberOfMessagesToLoad; + } }]; - + return item == 0 ? item : item - 1; } --(void)updateLoadEarlierVisible -{ +- (void)updateLoadEarlierVisible { [self setShowLoadEarlierMessagesHeader:[self shouldShowLoadEarlierMessages]]; } --(void)updateLayoutForEarlierMessagesWithOffset:(NSInteger)offset -{ - [self.collectionView.collectionViewLayout invalidateLayoutWithContext:[JSQMessagesCollectionViewFlowLayoutInvalidationContext context]]; +- (void)updateLayoutForEarlierMessagesWithOffset:(NSInteger)offset { + [self.collectionView.collectionViewLayout + invalidateLayoutWithContext:[JSQMessagesCollectionViewFlowLayoutInvalidationContext context]]; [self.collectionView reloadData]; - - [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:offset inSection:0] atScrollPosition:UICollectionViewScrollPositionTop animated:NO]; - + + [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:offset inSection:0] + atScrollPosition:UICollectionViewScrollPositionTop + animated:NO]; + [self updateLoadEarlierVisible]; } --(void)updateRangeOptionsForPage:(NSUInteger)page -{ - YapDatabaseViewRangeOptions *rangeOptions = [YapDatabaseViewRangeOptions flexibleRangeWithLength:kYapDatabaseRangeLength*(page+1) offset:0 from:YapDatabaseViewEnd]; - +- (void)updateRangeOptionsForPage:(NSUInteger)page { + YapDatabaseViewRangeOptions *rangeOptions = + [YapDatabaseViewRangeOptions flexibleRangeWithLength:kYapDatabaseRangeLength * (page + 1) + offset:0 + from:YapDatabaseViewEnd]; + rangeOptions.maxLength = kYapDatabaseRangeMaxLength; rangeOptions.minLength = kYapDatabaseRangeMinLength; - + [self.messageMappings setRangeOptions:rangeOptions forGroup:self.thread.uniqueId]; - } #pragma mark Bubble User Actions -- (void)handleUnsentMessageTap:(TSOutgoingMessage*)message{ +- (void)handleUnsentMessageTap:(TSOutgoingMessage *)message { [self dismissKeyBoard]; - [DJWActionSheet showInView:self.parentViewController.view withTitle:nil cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") destructiveButtonTitle:NSLocalizedString(@"TXT_DELETE_TITLE", @"") otherButtonTitles:@[NSLocalizedString(@"SEND_AGAIN_BUTTON", @"")] tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) { - if (tappedButtonIndex == actionSheet.cancelButtonIndex) { - DDLogDebug(@"User Cancelled"); - } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { - [self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction){ - [message removeWithTransaction:transaction]; - }]; - }else { - [[TSMessagesManager sharedManager] sendMessage:message inThread:self.thread success:nil failure:nil]; - [self finishSendingMessage]; - } - }]; + [DJWActionSheet showInView:self.parentViewController.view + withTitle:nil + cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") + destructiveButtonTitle:NSLocalizedString(@"TXT_DELETE_TITLE", @"") + otherButtonTitles:@[ NSLocalizedString(@"SEND_AGAIN_BUTTON", @"") ] + tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) { + if (tappedButtonIndex == actionSheet.cancelButtonIndex) { + DDLogDebug(@"User Cancelled"); + } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { + [self.editingDatabaseConnection + readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [message removeWithTransaction:transaction]; + }]; + } else { + [[TSMessagesManager sharedManager] sendMessage:message + inThread:self.thread + success:nil + failure:nil]; + [self finishSendingMessage]; + } + }]; } -- (void)deleteMessageAtIndexPath:(NSIndexPath*)indexPath { +- (void)deleteMessageAtIndexPath:(NSIndexPath *)indexPath { [self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - TSInteraction *interaction = [self interactionAtIndexPath:indexPath]; - [[TSAdapterCacheManager sharedManager] clearCacheEntryForInteractionId:interaction.uniqueId]; - [interaction removeWithTransaction:transaction]; + TSInteraction *interaction = [self interactionAtIndexPath:indexPath]; + [[TSAdapterCacheManager sharedManager] clearCacheEntryForInteractionId:interaction.uniqueId]; + [interaction removeWithTransaction:transaction]; }]; } -- (void)handleErrorMessageTap:(TSErrorMessage*)message { +- (void)handleErrorMessageTap:(TSErrorMessage *)message { if ([message isKindOfClass:[TSInvalidIdentityKeyErrorMessage class]]) { - TSInvalidIdentityKeyErrorMessage *errorMessage = (TSInvalidIdentityKeyErrorMessage*)message; - NSString *newKeyFingerprint = [errorMessage newIdentityKey]; - + TSInvalidIdentityKeyErrorMessage *errorMessage = (TSInvalidIdentityKeyErrorMessage *)message; + NSString *newKeyFingerprint = [errorMessage newIdentityKey]; + NSString *keyOwner; if ([message isKindOfClass:[TSInvalidIdentityKeySendingErrorMessage class]]) { - TSInvalidIdentityKeySendingErrorMessage *m = (TSInvalidIdentityKeySendingErrorMessage*)message; + TSInvalidIdentityKeySendingErrorMessage *m = (TSInvalidIdentityKeySendingErrorMessage *)message; keyOwner = [[[Environment getCurrent] contactsManager] nameStringForPhoneIdentifier:m.recipientId]; } else { keyOwner = [self.thread name]; } - - NSString *messageString = [NSString stringWithFormat:NSLocalizedString(@"ACCEPT_IDENTITYKEY_QUESTION", @""), keyOwner, newKeyFingerprint]; - NSArray *actions = @[NSLocalizedString(@"ACCEPT_IDENTITYKEY_BUTTON", @""), NSLocalizedString(@"COPY_IDENTITYKEY_BUTTON", @"")]; - + + NSString *messageString = [NSString + stringWithFormat:NSLocalizedString(@"ACCEPT_IDENTITYKEY_QUESTION", @""), keyOwner, newKeyFingerprint]; + NSArray *actions = @[ + NSLocalizedString(@"ACCEPT_IDENTITYKEY_BUTTON", @""), + NSLocalizedString(@"COPY_IDENTITYKEY_BUTTON", @"") + ]; + [self dismissKeyBoard]; - - [DJWActionSheet showInView:self.parentViewController.view withTitle:messageString cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") destructiveButtonTitle:NSLocalizedString(@"TXT_DELETE_TITLE", @"") otherButtonTitles:actions tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) { - if (tappedButtonIndex == actionSheet.cancelButtonIndex) { - DDLogDebug(@"User Cancelled"); - } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { - [self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction){ - [message removeWithTransaction:transaction]; - }]; - } else { - switch (tappedButtonIndex) { - case 0: - [errorMessage acceptNewIdentityKey]; - break; - case 1: - [[UIPasteboard generalPasteboard] setString:newKeyFingerprint]; - break; - default: - break; - } - } - }]; + + [DJWActionSheet showInView:self.parentViewController.view + withTitle:messageString + cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") + destructiveButtonTitle:NSLocalizedString(@"TXT_DELETE_TITLE", @"") + otherButtonTitles:actions + tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) { + if (tappedButtonIndex == actionSheet.cancelButtonIndex) { + DDLogDebug(@"User Cancelled"); + } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { + [self.editingDatabaseConnection + readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [message removeWithTransaction:transaction]; + }]; + } else { + switch (tappedButtonIndex) { + case 0: + [errorMessage acceptNewIdentityKey]; + break; + case 1: + [[UIPasteboard generalPasteboard] setString:newKeyFingerprint]; + break; + default: + break; + } + } + }]; } } #pragma mark - Navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - - if ([segue.identifier isEqualToString:kFingerprintSegueIdentifier]){ + if ([segue.identifier isEqualToString:kFingerprintSegueIdentifier]) { FingerprintViewController *vc = [segue destinationViewController]; [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - [vc configWithThread:self.thread]; + [vc configWithThread:self.thread]; }]; - } - else if ([segue.identifier isEqualToString:kUpdateGroupSegueIdentifier]) { + } else if ([segue.identifier isEqualToString:kUpdateGroupSegueIdentifier]) { NewGroupViewController *vc = [segue destinationViewController]; [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - [vc configWithThread:(TSGroupThread*)self.thread]; + [vc configWithThread:(TSGroupThread *)self.thread]; }]; - } - else if([segue.identifier isEqualToString:kShowGroupMembersSegue]) { + } else if ([segue.identifier isEqualToString:kShowGroupMembersSegue]) { ShowGroupMembersViewController *vc = [segue destinationViewController]; [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - [vc configWithThread:(TSGroupThread*)self.thread]; + [vc configWithThread:(TSGroupThread *)self.thread]; }]; } } @@ -1242,27 +1341,25 @@ typedef enum : NSUInteger { - (void)takePictureOrVideo { UIImagePickerController *picker = [[UIImagePickerController alloc] init]; - picker.delegate = self; - picker.allowsEditing = NO; - picker.sourceType = UIImagePickerControllerSourceTypeCamera; - - if ([UIImagePickerController isSourceTypeAvailable: - UIImagePickerControllerSourceTypeCamera]) { - picker.mediaTypes = @[(NSString*)kUTTypeImage,(NSString*)kUTTypeMovie]; + picker.delegate = self; + picker.allowsEditing = NO; + picker.sourceType = UIImagePickerControllerSourceTypeCamera; + + if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { + picker.mediaTypes = @[ (NSString *)kUTTypeImage, (NSString *)kUTTypeMovie ]; [self presentViewController:picker animated:YES completion:[UIUtil modalCompletionBlock]]; } - } - (void)chooseFromLibrary { UIImagePickerController *picker = [[UIImagePickerController alloc] init]; - picker.delegate = self; - picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; - + picker.delegate = self; + picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; + if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) { - - NSArray* photoOrVideoTypeArray = [[NSArray alloc] initWithObjects:(NSString *)kUTTypeImage,(NSString *)kUTTypeMovie, (NSString*)kUTTypeVideo, nil]; - + NSArray *photoOrVideoTypeArray = [[NSArray alloc] + initWithObjects:(NSString *)kUTTypeImage, (NSString *)kUTTypeMovie, (NSString *)kUTTypeVideo, nil]; + picker.mediaTypes = photoOrVideoTypeArray; [self presentViewController:picker animated:YES completion:[UIUtil modalCompletionBlock]]; } @@ -1279,7 +1376,7 @@ typedef enum : NSUInteger { - (void)resetFrame { // fixes bug on frame being off after this selection - CGRect frame = [UIScreen mainScreen].applicationFrame; + CGRect frame = [UIScreen mainScreen].applicationFrame; self.view.frame = frame; } @@ -1289,104 +1386,115 @@ typedef enum : NSUInteger { - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { [UIUtil modalCompletionBlock](); [self resetFrame]; - - NSString *mediaType = [info objectForKey: UIImagePickerControllerMediaType]; - if (CFStringCompare ((__bridge_retained CFStringRef)mediaType, kUTTypeMovie, 0) == kCFCompareEqualTo) { + + NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType]; + if (CFStringCompare((__bridge_retained CFStringRef)mediaType, kUTTypeMovie, 0) == kCFCompareEqualTo) { NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL]; [self sendQualityAdjustedAttachment:videoURL]; - } - else { + } else { // Send image as NSData to accommodate both static and animated images ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; [library assetForURL:[info objectForKey:UIImagePickerControllerReferenceURL] - resultBlock:^(ALAsset *asset) - { - ALAssetRepresentation *representation = [asset defaultRepresentation]; - Byte *img_buffer = (Byte*)malloc((unsigned long)representation.size); - NSUInteger length_buffered = [representation getBytes:img_buffer fromOffset:0 length:(unsigned long)representation.size error:nil]; - NSData *img_data = [NSData dataWithBytesNoCopy:img_buffer length:length_buffered]; - NSString *file_type; - switch (img_buffer[0]) - { - case 0x89: - file_type = @"image/png"; - break; - case 0x47: - file_type = @"image/gif"; - break; - case 0x49: - case 0x4D: - file_type = @"image/tiff"; - break; - case 0x42: - file_type = @"@image/bmp"; - break; - case 0xFF: - default: - file_type = @"image/jpeg"; - break; - } - DDLogVerbose(@"Sending image. Size in bytes: %lu; first byte: %02x (%c); detected filetype: %@", (unsigned long)length_buffered, img_buffer[0], img_buffer[0], file_type); - [self sendMessageAttachment:img_data ofType:file_type]; - } - failureBlock:^(NSError *error) - { - DDLogVerbose(@"Couldn't get image asset: %@", error); - } - ]; + resultBlock:^(ALAsset *asset) { + ALAssetRepresentation *representation = [asset defaultRepresentation]; + Byte *img_buffer = (Byte *)malloc((unsigned long)representation.size); + NSUInteger length_buffered = + [representation getBytes:img_buffer fromOffset:0 length:(unsigned long)representation.size error:nil]; + NSData *img_data = [NSData dataWithBytesNoCopy:img_buffer length:length_buffered]; + NSString *file_type; + switch (img_buffer[0]) { + case 0x89: + file_type = @"image/png"; + break; + case 0x47: + file_type = @"image/gif"; + break; + case 0x49: + case 0x4D: + file_type = @"image/tiff"; + break; + case 0x42: + file_type = @"@image/bmp"; + break; + case 0xFF: + default: + file_type = @"image/jpeg"; + break; + } + DDLogVerbose(@"Sending image. Size in bytes: %lu; first byte: %02x (%c); detected filetype: %@", + (unsigned long)length_buffered, + img_buffer[0], + img_buffer[0], + file_type); + [self sendMessageAttachment:img_data ofType:file_type]; + } + failureBlock:^(NSError *error) { + DDLogVerbose(@"Couldn't get image asset: %@", error); + }]; } - } -- (void) sendMessageAttachment:(NSData*)attachmentData ofType:(NSString*)attachmentType { - TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:self.thread messageBody:nil attachments:[NSMutableArray array]]; - - [self dismissViewControllerAnimated:YES completion:^{ - [[TSMessagesManager sharedManager] sendAttachment:attachmentData contentType:attachmentType inMessage:message thread:self.thread]; - }]; +- (void)sendMessageAttachment:(NSData *)attachmentData ofType:(NSString *)attachmentType { + TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] + inThread:self.thread + messageBody:nil + attachments:[NSMutableArray array]]; + + [self dismissViewControllerAnimated:YES + completion:^{ + [[TSMessagesManager sharedManager] sendAttachment:attachmentData + contentType:attachmentType + inMessage:message + thread:self.thread]; + }]; } -- (NSURL*)videoTempFolder { - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); +- (NSURL *)videoTempFolder { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil; - basePath = [basePath stringByAppendingPathComponent:@"videos"]; + basePath = [basePath stringByAppendingPathComponent:@"videos"]; if (![[NSFileManager defaultManager] fileExistsAtPath:basePath]) { - [[NSFileManager defaultManager] createDirectoryAtPath:basePath withIntermediateDirectories:YES attributes:nil error:nil]; + [[NSFileManager defaultManager] createDirectoryAtPath:basePath + withIntermediateDirectories:YES + attributes:nil + error:nil]; } return [NSURL fileURLWithPath:basePath]; } --(void)sendQualityAdjustedAttachment:(NSURL*)movieURL { +- (void)sendQualityAdjustedAttachment:(NSURL *)movieURL { AVAsset *video = [AVAsset assetWithURL:movieURL]; - AVAssetExportSession *exportSession = [AVAssetExportSession exportSessionWithAsset:video presetName:AVAssetExportPresetMediumQuality]; + AVAssetExportSession *exportSession = + [AVAssetExportSession exportSessionWithAsset:video presetName:AVAssetExportPresetMediumQuality]; exportSession.shouldOptimizeForNetworkUse = YES; - exportSession.outputFileType = AVFileTypeMPEG4; - - double currentTime = [[NSDate date] timeIntervalSince1970]; - NSString *strImageName = [NSString stringWithFormat:@"%f",currentTime]; - NSURL *compressedVideoUrl = [[self videoTempFolder] URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.mp4",strImageName]]; - + exportSession.outputFileType = AVFileTypeMPEG4; + + double currentTime = [[NSDate date] timeIntervalSince1970]; + NSString *strImageName = [NSString stringWithFormat:@"%f", currentTime]; + NSURL *compressedVideoUrl = + [[self videoTempFolder] URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.mp4", strImageName]]; + exportSession.outputURL = compressedVideoUrl; [exportSession exportAsynchronouslyWithCompletionHandler:^{ - NSError *error; - [self sendMessageAttachment:[NSData dataWithContentsOfURL:compressedVideoUrl] ofType:@"video/mp4"]; - [[NSFileManager defaultManager] removeItemAtURL:compressedVideoUrl error:&error]; - if (error) { - DDLogWarn(@"Failed to remove cached video file: %@", error.debugDescription); - } + NSError *error; + [self sendMessageAttachment:[NSData dataWithContentsOfURL:compressedVideoUrl] ofType:@"video/mp4"]; + [[NSFileManager defaultManager] removeItemAtURL:compressedVideoUrl error:&error]; + if (error) { + DDLogWarn(@"Failed to remove cached video file: %@", error.debugDescription); + } }]; } -- (NSData*)qualityAdjustedAttachmentForImage:(UIImage*)image { +- (NSData *)qualityAdjustedAttachmentForImage:(UIImage *)image { return UIImageJPEGRepresentation([self adjustedImageSizedForSending:image], [self compressionRate]); } -- (UIImage*)adjustedImageSizedForSending:(UIImage*)image { +- (UIImage *)adjustedImageSizedForSending:(UIImage *)image { CGFloat correctedWidth; switch ([Environment.preferences imageUploadQuality]) { case TSImageQualityUncropped: return image; - + case TSImageQualityHigh: correctedWidth = 2048; break; @@ -1399,28 +1507,27 @@ typedef enum : NSUInteger { default: break; } - + return [self imageScaled:image toMaxSize:correctedWidth]; } -- (UIImage*)imageScaled:(UIImage *)image toMaxSize:(CGFloat)size { +- (UIImage *)imageScaled:(UIImage *)image toMaxSize:(CGFloat)size { CGFloat scaleFactor; CGFloat aspectRatio = image.size.height / image.size.width; - - if( aspectRatio > 1 ) { + + if (aspectRatio > 1) { scaleFactor = size / image.size.width; - } - else { + } else { scaleFactor = size / image.size.height; } - + CGSize newSize = CGSizeMake(image.size.width * scaleFactor, image.size.height * scaleFactor); - + UIGraphicsBeginImageContext(newSize); [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; - UIImage* updatedImage = UIGraphicsGetImageFromCurrentImageContext(); + UIImage *updatedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); - + return updatedImage; } @@ -1441,7 +1548,7 @@ typedef enum : NSUInteger { #pragma mark Storage access -- (YapDatabaseConnection*)uiDatabaseConnection { +- (YapDatabaseConnection *)uiDatabaseConnection { NSAssert([NSThread isMainThread], @"Must access uiDatabaseConnection on main thread!"); if (!_uiDatabaseConnection) { _uiDatabaseConnection = [[TSStorageManager sharedManager] newDatabaseConnection]; @@ -1454,7 +1561,7 @@ typedef enum : NSUInteger { return _uiDatabaseConnection; } -- (YapDatabaseConnection*)editingDatabaseConnection { +- (YapDatabaseConnection *)editingDatabaseConnection { if (!_editingDatabaseConnection) { _editingDatabaseConnection = [[TSStorageManager sharedManager] newDatabaseConnection]; } @@ -1463,99 +1570,103 @@ typedef enum : NSUInteger { - (void)yapDatabaseModified:(NSNotification *)notification { - [self updateBackButtonAsync]; - - if(isGroupConversation) { + + if (isGroupConversation) { [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - TSGroupThread* gThread = (TSGroupThread*)self.thread; - self.thread = [TSGroupThread threadWithGroupModel:gThread.groupModel transaction:transaction]; + TSGroupThread *gThread = (TSGroupThread *)self.thread; + self.thread = [TSGroupThread threadWithGroupModel:gThread.groupModel transaction:transaction]; }]; } - + NSArray *notifications = [self.uiDatabaseConnection beginLongLivedReadTransaction]; - - if ( ![[self.uiDatabaseConnection ext:TSMessageDatabaseViewExtensionName] hasChangesForNotifications:notifications]) { - [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction){ - [self.messageMappings updateWithTransaction:transaction]; + + if (![[self.uiDatabaseConnection ext:TSMessageDatabaseViewExtensionName] + hasChangesForNotifications:notifications]) { + [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { + [self.messageMappings updateWithTransaction:transaction]; }]; return; } - + if (!_isVisible) { // Since we moved our databaseConnection to a new commit, // we need to update the mappings too. - [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction){ - [self.messageMappings updateWithTransaction:transaction]; + [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { + [self.messageMappings updateWithTransaction:transaction]; }]; return; } - + NSArray *messageRowChanges = nil; NSArray *sectionChanges = nil; - - + + [[self.uiDatabaseConnection ext:TSMessageDatabaseViewExtensionName] getSectionChanges:§ionChanges rowChanges:&messageRowChanges forNotifications:notifications withMappings:self.messageMappings]; - + __block BOOL scrollToBottom = NO; - + if ([sectionChanges count] == 0 & [messageRowChanges count] == 0) { return; } - + [self.collectionView performBatchUpdates:^{ - for (YapDatabaseViewRowChange *rowChange in messageRowChanges) { - switch (rowChange.type) { - case YapDatabaseViewChangeDelete : - { - [self.collectionView deleteItemsAtIndexPaths:@[ rowChange.indexPath ]]; - break; - } - case YapDatabaseViewChangeInsert : - { - TSInteraction * interaction = [self interactionAtIndexPath:rowChange.newIndexPath]; - [[TSAdapterCacheManager sharedManager] cacheAdapter:[TSMessageAdapter messageViewDataWithInteraction:interaction inThread:self.thread] forInteractionId:interaction.uniqueId]; - [self.collectionView insertItemsAtIndexPaths:@[ rowChange.newIndexPath ]]; - scrollToBottom = YES; - break; - } - case YapDatabaseViewChangeMove : - { - [self.collectionView deleteItemsAtIndexPaths:@[ rowChange.indexPath ]]; - [self.collectionView insertItemsAtIndexPaths:@[ rowChange.newIndexPath ]]; - break; - } - case YapDatabaseViewChangeUpdate : - { - NSMutableArray *rowsToUpdate = [@[rowChange.indexPath] mutableCopy]; - - if (_lastDeliveredMessageIndexPath) { - [rowsToUpdate addObject:_lastDeliveredMessageIndexPath]; - } - - for (NSIndexPath* indexPath in rowsToUpdate) { - TSInteraction * interaction = [self interactionAtIndexPath:indexPath]; - [[TSAdapterCacheManager sharedManager] cacheAdapter:[TSMessageAdapter messageViewDataWithInteraction:interaction inThread:self.thread] forInteractionId:interaction.uniqueId]; - } - - [self.collectionView reloadItemsAtIndexPaths:rowsToUpdate]; - scrollToBottom = YES; - break; - } - } - } - } completion:^(BOOL success) { - if (!success) { - [self.collectionView.collectionViewLayout invalidateLayoutWithContext:[JSQMessagesCollectionViewFlowLayoutInvalidationContext context]]; - [self.collectionView reloadData]; - } - if (scrollToBottom) { - [self scrollToBottomAnimated:YES]; - } - }]; + for (YapDatabaseViewRowChange *rowChange in messageRowChanges) { + switch (rowChange.type) { + case YapDatabaseViewChangeDelete: { + [self.collectionView deleteItemsAtIndexPaths:@[ rowChange.indexPath ]]; + break; + } + case YapDatabaseViewChangeInsert: { + TSInteraction *interaction = [self interactionAtIndexPath:rowChange.newIndexPath]; + [[TSAdapterCacheManager sharedManager] + cacheAdapter:[TSMessageAdapter messageViewDataWithInteraction:interaction + inThread:self.thread] + forInteractionId:interaction.uniqueId]; + [self.collectionView insertItemsAtIndexPaths:@[ rowChange.newIndexPath ]]; + scrollToBottom = YES; + break; + } + case YapDatabaseViewChangeMove: { + [self.collectionView deleteItemsAtIndexPaths:@[ rowChange.indexPath ]]; + [self.collectionView insertItemsAtIndexPaths:@[ rowChange.newIndexPath ]]; + break; + } + case YapDatabaseViewChangeUpdate: { + NSMutableArray *rowsToUpdate = [@[ rowChange.indexPath ] mutableCopy]; + + if (_lastDeliveredMessageIndexPath) { + [rowsToUpdate addObject:_lastDeliveredMessageIndexPath]; + } + + for (NSIndexPath *indexPath in rowsToUpdate) { + TSInteraction *interaction = [self interactionAtIndexPath:indexPath]; + [[TSAdapterCacheManager sharedManager] + cacheAdapter:[TSMessageAdapter messageViewDataWithInteraction:interaction + inThread:self.thread] + forInteractionId:interaction.uniqueId]; + } + + [self.collectionView reloadItemsAtIndexPaths:rowsToUpdate]; + scrollToBottom = YES; + break; + } + } + } + } + completion:^(BOOL success) { + if (!success) { + [self.collectionView.collectionViewLayout + invalidateLayoutWithContext:[JSQMessagesCollectionViewFlowLayoutInvalidationContext context]]; + [self.collectionView reloadData]; + } + if (scrollToBottom) { + [self scrollToBottomAnimated:YES]; + } + }]; } #pragma mark - UICollectionView DataSource @@ -1565,34 +1676,38 @@ typedef enum : NSUInteger { return numberOfMessages; } -- (TSInteraction*)interactionAtIndexPath:(NSIndexPath*)indexPath { +- (TSInteraction *)interactionAtIndexPath:(NSIndexPath *)indexPath { __block TSInteraction *message = nil; [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - YapDatabaseViewTransaction *viewTransaction = [transaction ext:TSMessageDatabaseViewExtensionName]; - NSParameterAssert(viewTransaction != nil); - NSParameterAssert(self.messageMappings != nil); - NSParameterAssert(indexPath != nil); - NSUInteger row = (NSUInteger)indexPath.row; - NSUInteger section = (NSUInteger)indexPath.section; - NSUInteger numberOfItemsInSection = [self.messageMappings numberOfItemsInSection:section]; - - NSAssert(row < numberOfItemsInSection, @"Cannot fetch message because row %d is >= numberOfItemsInSection %d", (int)row, (int)numberOfItemsInSection); - - message = [viewTransaction objectAtRow:row inSection:section withMappings:self.messageMappings]; - NSParameterAssert(message != nil); + YapDatabaseViewTransaction *viewTransaction = [transaction ext:TSMessageDatabaseViewExtensionName]; + NSParameterAssert(viewTransaction != nil); + NSParameterAssert(self.messageMappings != nil); + NSParameterAssert(indexPath != nil); + NSUInteger row = (NSUInteger)indexPath.row; + NSUInteger section = (NSUInteger)indexPath.section; + NSUInteger numberOfItemsInSection = [self.messageMappings numberOfItemsInSection:section]; + + NSAssert(row < numberOfItemsInSection, + @"Cannot fetch message because row %d is >= numberOfItemsInSection %d", + (int)row, + (int)numberOfItemsInSection); + + message = [viewTransaction objectAtRow:row inSection:section withMappings:self.messageMappings]; + NSParameterAssert(message != nil); }]; - + return message; } -- (TSMessageAdapter*)messageAtIndexPath:(NSIndexPath *)indexPath { - TSInteraction *interaction = [self interactionAtIndexPath:indexPath]; - TSAdapterCacheManager * manager = [TSAdapterCacheManager sharedManager]; - +- (TSMessageAdapter *)messageAtIndexPath:(NSIndexPath *)indexPath { + TSInteraction *interaction = [self interactionAtIndexPath:indexPath]; + TSAdapterCacheManager *manager = [TSAdapterCacheManager sharedManager]; + if (![manager containsCacheEntryForInteractionId:interaction.uniqueId]) { - [manager cacheAdapter:[TSMessageAdapter messageViewDataWithInteraction:interaction inThread:self.thread] forInteractionId:interaction.uniqueId]; + [manager cacheAdapter:[TSMessageAdapter messageViewDataWithInteraction:interaction inThread:self.thread] + forInteractionId:interaction.uniqueId]; } - + return [manager adapterForInteractionId:interaction.uniqueId]; } @@ -1602,47 +1717,46 @@ typedef enum : NSUInteger { #pragma mark - Audio --(void)recordAudio { +- (void)recordAudio { // Define the recorder setting - NSArray *pathComponents = [NSArray arrayWithObjects: - [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject], - [NSString stringWithFormat:@"%lld.m4a",[NSDate ows_millisecondTimeStamp]], - nil]; + NSArray *pathComponents = [NSArray + arrayWithObjects:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject], + [NSString stringWithFormat:@"%lld.m4a", [NSDate ows_millisecondTimeStamp]], + nil]; NSURL *outputFileURL = [NSURL fileURLWithPathComponents:pathComponents]; - + // Setup audio session AVAudioSession *session = [AVAudioSession sharedInstance]; [session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil]; - + NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init]; [recordSetting setValue:[NSNumber numberWithInt:kAudioFormatMPEG4AAC] forKey:AVFormatIDKey]; [recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey]; - [recordSetting setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey]; - + [recordSetting setValue:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey]; + // Initiate and prepare the recorder - _audioRecorder = [[AVAudioRecorder alloc] initWithURL:outputFileURL settings:recordSetting error:NULL]; + _audioRecorder = [[AVAudioRecorder alloc] initWithURL:outputFileURL settings:recordSetting error:NULL]; _audioRecorder.delegate = self; _audioRecorder.meteringEnabled = YES; [_audioRecorder prepareToRecord]; } -- (void)audioPlayerUpdated:(NSTimer*)timer { - double current = [_audioPlayer currentTime]/[_audioPlayer duration]; +- (void)audioPlayerUpdated:(NSTimer *)timer { + double current = [_audioPlayer currentTime] / [_audioPlayer duration]; double interval = [_audioPlayer duration] - [_audioPlayer currentTime]; [_currentMediaAdapter setDurationOfAudio:interval]; [_currentMediaAdapter setAudioProgressFromFloat:(float)current]; } -- (void) audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{ +- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { [_audioPlayerPoller invalidate]; [_currentMediaAdapter setAudioProgressFromFloat:0]; [_currentMediaAdapter setDurationOfAudio:_audioPlayer.duration]; [_currentMediaAdapter setAudioIconToPlay]; } -- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder - successfully:(BOOL)flag { - if(flag) { +- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag { + if (flag) { [self sendMessageAttachment:[NSData dataWithContentsOfURL:recorder.url] ofType:@"audio/m4a"]; } } @@ -1651,114 +1765,130 @@ typedef enum : NSUInteger { - (void)didPressAccessoryButton:(UIButton *)sender { [self dismissKeyBoard]; - + UIView *presenter = self.parentViewController.view; - + [DJWActionSheet showInView:presenter withTitle:nil cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") destructiveButtonTitle:nil - otherButtonTitles:@[NSLocalizedString(@"TAKE_MEDIA_BUTTON", @""), NSLocalizedString(@"CHOOSE_MEDIA_BUTTON", @"")]//,@"Record audio"] + otherButtonTitles:@[ + NSLocalizedString(@"TAKE_MEDIA_BUTTON", @""), + NSLocalizedString(@"CHOOSE_MEDIA_BUTTON", @"") + ] //,@"Record audio"] tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) { - if (tappedButtonIndex == actionSheet.cancelButtonIndex) { - DDLogVerbose(@"User Cancelled"); - } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { - DDLogVerbose(@"Destructive button tapped"); - } else { - switch (tappedButtonIndex) { - case 0: - [self takePictureOrVideo]; - break; - case 1: - [self chooseFromLibrary]; - break; - case 2: - [self recordAudio]; - break; - default: - break; - } - } + if (tappedButtonIndex == actionSheet.cancelButtonIndex) { + DDLogVerbose(@"User Cancelled"); + } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { + DDLogVerbose(@"Destructive button tapped"); + } else { + switch (tappedButtonIndex) { + case 0: + [self takePictureOrVideo]; + break; + case 1: + [self chooseFromLibrary]; + break; + case 2: + [self recordAudio]; + break; + default: + break; + } + } }]; } - (void)markAllMessagesAsRead { [self.editingDatabaseConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [self.thread markAllAsReadWithTransaction:transaction]; + [self.thread markAllAsReadWithTransaction:transaction]; }]; } -- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender -{ +- (BOOL)collectionView:(UICollectionView *)collectionView + canPerformAction:(SEL)action + forItemAtIndexPath:(NSIndexPath *)indexPath + withSender:(id)sender { if (action == @selector(delete:)) { return YES; } - + return [super collectionView:collectionView canPerformAction:action forItemAtIndexPath:indexPath withSender:sender]; } -- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { +- (void)collectionView:(UICollectionView *)collectionView + performAction:(SEL)action + forItemAtIndexPath:(NSIndexPath *)indexPath + withSender:(id)sender { if (action == @selector(delete:)) { [self deleteMessageAtIndexPath:indexPath]; - } - else { + } else { [super collectionView:collectionView performAction:action forItemAtIndexPath:indexPath withSender:sender]; } } - (void)updateGroup { [self.navController hideDropDown:self]; - + [self performSegueWithIdentifier:kUpdateGroupSegueIdentifier sender:self]; } - (void)leaveGroup { [self.navController hideDropDown:self]; - - TSGroupThread* gThread = (TSGroupThread*)_thread; - TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:gThread messageBody:@"" attachments:[[NSMutableArray alloc] init]]; + + TSGroupThread *gThread = (TSGroupThread *)_thread; + TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] + inThread:gThread + messageBody:@"" + attachments:[[NSMutableArray alloc] init]]; message.groupMetaMessage = TSGroupMessageQuit; [[TSMessagesManager sharedManager] sendMessage:message inThread:gThread success:nil failure:nil]; [self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - NSMutableArray *newGroupMemberIds = [NSMutableArray arrayWithArray:gThread.groupModel.groupMemberIds]; - [newGroupMemberIds removeObject:[SignalKeyingStorage.localNumber toE164]]; - gThread.groupModel.groupMemberIds = newGroupMemberIds; - [gThread saveWithTransaction:transaction]; + NSMutableArray *newGroupMemberIds = [NSMutableArray arrayWithArray:gThread.groupModel.groupMemberIds]; + [newGroupMemberIds removeObject:[TSAccountManager localNumber]]; + gThread.groupModel.groupMemberIds = newGroupMemberIds; + [gThread saveWithTransaction:transaction]; }]; [self hideInputIfNeeded]; } -- (void) updateGroupModelTo:(TSGroupModel*)newGroupModel { - __block TSGroupThread *groupThread; +- (void)updateGroupModelTo:(TSGroupModel *)newGroupModel { + __block TSGroupThread *groupThread; __block TSOutgoingMessage *message; - - + + [self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - groupThread = [TSGroupThread getOrCreateThreadWithGroupModel:newGroupModel transaction:transaction]; - groupThread.groupModel = newGroupModel; - [groupThread saveWithTransaction:transaction]; - message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:groupThread messageBody:@"" attachments:[[NSMutableArray alloc] init]]; - message.groupMetaMessage = TSGroupMessageUpdate; + groupThread = [TSGroupThread getOrCreateThreadWithGroupModel:newGroupModel transaction:transaction]; + groupThread.groupModel = newGroupModel; + [groupThread saveWithTransaction:transaction]; + message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] + inThread:groupThread + messageBody:@"" + attachments:[[NSMutableArray alloc] init]]; + message.groupMetaMessage = TSGroupMessageUpdate; }]; - - if(newGroupModel.groupImage!=nil) { - [[TSMessagesManager sharedManager] sendAttachment:UIImagePNGRepresentation(newGroupModel.groupImage) contentType:@"image/png" inMessage:message thread:groupThread]; - } - else { + + if (newGroupModel.groupImage != nil) { + [[TSMessagesManager sharedManager] sendAttachment:UIImagePNGRepresentation(newGroupModel.groupImage) + contentType:@"image/png" + inMessage:message + thread:groupThread]; + } else { [[TSMessagesManager sharedManager] sendMessage:message inThread:groupThread success:nil failure:nil]; } - + self.thread = groupThread; } - (IBAction)unwindGroupUpdated:(UIStoryboardSegue *)segue { - NewGroupViewController *ngc = [segue sourceViewController]; - TSGroupModel* newGroupModel = [ngc groupModel]; - NSMutableSet* groupMemberIds = [NSMutableSet setWithArray:newGroupModel.groupMemberIds]; - [groupMemberIds addObject:[SignalKeyingStorage.localNumber toE164]]; + NewGroupViewController *ngc = [segue sourceViewController]; + TSGroupModel *newGroupModel = [ngc groupModel]; + NSMutableSet *groupMemberIds = [NSMutableSet setWithArray:newGroupModel.groupMemberIds]; + [groupMemberIds addObject:[TSAccountManager localNumber]]; newGroupModel.groupMemberIds = [NSMutableArray arrayWithArray:[groupMemberIds allObjects]]; [self updateGroupModelTo:newGroupModel]; - [self.collectionView.collectionViewLayout invalidateLayoutWithContext:[JSQMessagesCollectionViewFlowLayoutInvalidationContext context]]; + [self.collectionView.collectionViewLayout + invalidateLayoutWithContext:[JSQMessagesCollectionViewFlowLayoutInvalidationContext context]]; [self.collectionView reloadData]; } @@ -1775,22 +1905,23 @@ typedef enum : NSUInteger { - (void)loadDraftInCompose { __block NSString *placeholder; [self.editingDatabaseConnection asyncReadWithBlock:^(YapDatabaseReadTransaction *transaction) { - placeholder = [_thread currentDraftWithTransaction:transaction]; - } completionBlock:^{ - dispatch_async(dispatch_get_main_queue(), ^{ + placeholder = [_thread currentDraftWithTransaction:transaction]; + } + completionBlock:^{ + dispatch_async(dispatch_get_main_queue(), ^{ [self.inputToolbar.contentView.textView setText:placeholder]; [self textViewDidChange:self.inputToolbar.contentView.textView]; - }); - }]; + }); + }]; } - (void)saveDraft { if (self.inputToolbar.hidden == NO) { __block TSThread *thread = _thread; __block NSString *currentDraft = self.inputToolbar.contentView.textView.text; - + [self.editingDatabaseConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [thread setDraft:currentDraft transaction:transaction]; + [thread setDraft:currentDraft transaction:transaction]; }]; } } @@ -1800,29 +1931,29 @@ typedef enum : NSUInteger { - (void)setUnreadCount:(NSUInteger)unreadCount { if (_unreadCount != unreadCount) { _unreadCount = unreadCount; - + if (_unreadCount > 0) { if (_unreadContainer == nil) { static UIImage *backgroundImage = nil; static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^ - { - UIGraphicsBeginImageContextWithOptions(CGSizeMake(17.0f, 17.0f), false, 0.0f); - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor); - CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, 17.0f, 17.0f)); - backgroundImage = [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:8 topCapHeight:8]; - UIGraphicsEndImageContext(); - }); - + dispatch_once(&onceToken, ^{ + UIGraphicsBeginImageContextWithOptions(CGSizeMake(17.0f, 17.0f), false, 0.0f); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor); + CGContextFillEllipseInRect(context, CGRectMake(0.0f, 0.0f, 17.0f, 17.0f)); + backgroundImage = + [UIGraphicsGetImageFromCurrentImageContext() stretchableImageWithLeftCapWidth:8 topCapHeight:8]; + UIGraphicsEndImageContext(); + }); + _unreadContainer = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 10.0f, 10.0f)]; _unreadContainer.userInteractionEnabled = NO; _unreadContainer.layer.zPosition = 2000; [self.navigationController.navigationBar addSubview:_unreadContainer]; - + _unreadBackground = [[UIImageView alloc] initWithImage:backgroundImage]; [_unreadContainer addSubview:_unreadBackground]; - + _unreadLabel = [[UILabel alloc] init]; _unreadLabel.backgroundColor = [UIColor clearColor]; _unreadLabel.textColor = [UIColor whiteColor]; @@ -1830,17 +1961,20 @@ typedef enum : NSUInteger { [_unreadContainer addSubview:_unreadLabel]; } _unreadContainer.hidden = false; - + _unreadLabel.text = [NSString stringWithFormat:@"%lu", (unsigned long)unreadCount]; [_unreadLabel sizeToFit]; - + CGPoint offset = CGPointMake(17.0f, 2.0f); - - _unreadBackground.frame = CGRectMake(offset.x, offset.y, - MAX(_unreadLabel.frame.size.width + 8.0f, 17.0f), 17.0f); - _unreadLabel.frame = CGRectMake(offset.x + floor((2.0f*(_unreadBackground.frame.size.width - _unreadLabel.frame.size.width)/ 2.0f)/2.0f), offset.y + 1.0f, - _unreadLabel.frame.size.width, _unreadLabel.frame.size.height); - + + _unreadBackground.frame = + CGRectMake(offset.x, offset.y, MAX(_unreadLabel.frame.size.width + 8.0f, 17.0f), 17.0f); + _unreadLabel.frame = CGRectMake( + offset.x + + floor((2.0f * (_unreadBackground.frame.size.width - _unreadLabel.frame.size.width) / 2.0f) / 2.0f), + offset.y + 1.0f, + _unreadLabel.frame.size.width, + _unreadLabel.frame.size.height); } else if (_unreadContainer != nil) { _unreadContainer.hidden = true; } diff --git a/Signal/src/view controllers/NewGroupViewController.h b/Signal/src/view controllers/NewGroupViewController.h index 6330205cc..868df113c 100644 --- a/Signal/src/view controllers/NewGroupViewController.h +++ b/Signal/src/view controllers/NewGroupViewController.h @@ -7,18 +7,22 @@ // #import -#import "TSGroupThread.h" #import "TSGroupModel.h" +#import "TSGroupThread.h" -@interface NewGroupViewController : UIViewController +@interface NewGroupViewController : UIViewController -- (void)configWithThread:(TSGroupThread*)thread; -@property(nonatomic, strong) IBOutlet UITableView* tableView; -@property(nonatomic, strong) IBOutlet UITextField* nameGroupTextField; -@property(nonatomic, strong) IBOutlet UIButton* groupImageButton; -@property(nonatomic, strong) IBOutlet UIView* tapToDismissView; -@property(nonatomic, strong) IBOutlet UILabel *addPeopleLabel; -@property(nonatomic, strong) UIImage* groupImage; -@property(nonatomic, strong) TSGroupModel* groupModel; +- (void)configWithThread:(TSGroupThread *)thread; +@property (nonatomic, strong) IBOutlet UITableView *tableView; +@property (nonatomic, strong) IBOutlet UITextField *nameGroupTextField; +@property (nonatomic, strong) IBOutlet UIButton *groupImageButton; +@property (nonatomic, strong) IBOutlet UIView *tapToDismissView; +@property (nonatomic, strong) IBOutlet UILabel *addPeopleLabel; +@property (nonatomic, strong) UIImage *groupImage; +@property (nonatomic, strong) TSGroupModel *groupModel; @end diff --git a/Signal/src/view controllers/NewGroupViewController.m b/Signal/src/view controllers/NewGroupViewController.m index 4e1134924..08c4d5704 100644 --- a/Signal/src/view controllers/NewGroupViewController.m +++ b/Signal/src/view controllers/NewGroupViewController.m @@ -6,33 +6,30 @@ // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // -#import "NewGroupViewController.h" -#import "SignalsViewController.h" +#import +#import #import "ContactsManager.h" +#import "DJWActionSheet+OWS.h" #import "Environment.h" #import "FunctionalUtil.h" - - +#import "NewGroupViewController.h" #import "SecurityUtils.h" #import "SignalKeyingStorage.h" - +#import "SignalsViewController.h" #import "UIImage+normalizeImage.h" - #import "UIUtil.h" -#import "DJWActionSheet+OWS.h" -#import -static NSString* const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue"; +static NSString *const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue"; @interface NewGroupViewController () { - NSArray* contacts; + NSArray *contacts; } -@property TSGroupThread* thread; +@property TSGroupThread *thread; @end @implementation NewGroupViewController -- (void)configWithThread:(TSGroupThread *)gThread{ +- (void)configWithThread:(TSGroupThread *)gThread { _thread = gThread; } @@ -42,44 +39,51 @@ static NSString* const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue" contacts = [Environment getCurrent].contactsManager.textSecureContacts; - + self.tableView.tableHeaderView.frame = CGRectMake(0, 0, 400, 44); - self.tableView.tableHeaderView = self.tableView.tableHeaderView; - - - contacts = [contacts filter:^int(Contact* contact) { - for(PhoneNumber* number in [contact parsedPhoneNumbers]) { - if([[number toE164] isEqualToString:[SignalKeyingStorage.localNumber toE164]]) { - // remove local number - return NO; - } - else if(_thread!=nil && _thread.groupModel.groupMemberIds){ - return ![_thread.groupModel.groupMemberIds containsObject:[number toE164]]; - } - } - return YES; + self.tableView.tableHeaderView = self.tableView.tableHeaderView; + + + contacts = [contacts filter:^int(Contact *contact) { + for (PhoneNumber *number in [contact parsedPhoneNumbers]) { + if ([[number toE164] isEqualToString:[TSAccountManager localNumber]]) { + // remove local number + return NO; + } else if (_thread != nil && _thread.groupModel.groupMemberIds) { + return ![_thread.groupModel.groupMemberIds containsObject:[number toE164]]; + } + } + return YES; }]; - + [self initializeDelegates]; [self initializeTableView]; [self initializeKeyboardHandlers]; - if(_thread==nil) { - self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithImage:[[UIImage imageNamed:@"add-conversation"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] style:UIBarButtonItemStylePlain target:self action:@selector(createGroup)]; + if (_thread == nil) { + self.navigationItem.rightBarButtonItem = + [[UIBarButtonItem alloc] initWithImage:[[UIImage imageNamed:@"add-conversation"] + imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] + style:UIBarButtonItemStylePlain + target:self + action:@selector(createGroup)]; self.navigationItem.rightBarButtonItem.imageInsets = UIEdgeInsetsMake(0, -10, 0, 10); - self.navigationItem.title = NSLocalizedString(@"NEW_GROUP_DEFAULT_TITLE", @""); - } - else { - self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:NSLocalizedString(@"UPDATE_BUTTON_TITLE", @"") style:UIBarButtonItemStylePlain target:self action:@selector(updateGroup)]; - self.navigationItem.title = _thread.groupModel.groupName; + self.navigationItem.title = NSLocalizedString(@"NEW_GROUP_DEFAULT_TITLE", @""); + } else { + self.navigationItem.rightBarButtonItem = + [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"UPDATE_BUTTON_TITLE", @"") + style:UIBarButtonItemStylePlain + target:self + action:@selector(updateGroup)]; + self.navigationItem.title = _thread.groupModel.groupName; self.nameGroupTextField.text = _thread.groupModel.groupName; - if(_thread.groupModel.groupImage!=nil) { + if (_thread.groupModel.groupImage != nil) { _groupImage = _thread.groupModel.groupImage; [self setupGroupImageButton:_thread.groupModel.groupImage]; } } _nameGroupTextField.placeholder = NSLocalizedString(@"NEW_GROUP_NAMEGROUP_REQUEST_DEFAULT", @""); - _addPeopleLabel.text = NSLocalizedString(@"NEW_GROUP_REQUEST_ADDPEOPLE", @""); + _addPeopleLabel.text = NSLocalizedString(@"NEW_GROUP_REQUEST_ADDPEOPLE", @""); } - (void)didReceiveMemoryWarning { @@ -88,123 +92,124 @@ static NSString* const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue" #pragma mark - Initializers --(void)initializeDelegates -{ +- (void)initializeDelegates { self.nameGroupTextField.delegate = self; } --(void)initializeTableView -{ - self.tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero]; +- (void)initializeTableView { + self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; } #pragma mark - Keyboard notifications -- (void)initializeKeyboardHandlers{ - UITapGestureRecognizer *outsideTabRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)]; +- (void)initializeKeyboardHandlers { + UITapGestureRecognizer *outsideTabRecognizer = + [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)]; [self.tapToDismissView addGestureRecognizer:outsideTabRecognizer]; } --(void) dismissKeyboardFromAppropriateSubView { +- (void)dismissKeyboardFromAppropriateSubView { [self.nameGroupTextField resignFirstResponder]; } - #pragma mark - Actions --(void)createGroup { - TSGroupModel* model = [self makeGroup]; +- (void)createGroup { + TSGroupModel *model = [self makeGroup]; [Environment messageGroupModel:model withCompose:YES]; } --(void)updateGroup { - NSMutableArray* mut = [[NSMutableArray alloc]init]; - for (NSIndexPath* idx in _tableView.indexPathsForSelectedRows) { +- (void)updateGroup { + NSMutableArray *mut = [[NSMutableArray alloc] init]; + for (NSIndexPath *idx in _tableView.indexPathsForSelectedRows) { [mut addObjectsFromArray:[[contacts objectAtIndex:(NSUInteger)idx.row] textSecureIdentifiers]]; } [mut addObjectsFromArray:_thread.groupModel.groupMemberIds]; - + _groupModel = [[TSGroupModel alloc] initWithTitle:_nameGroupTextField.text memberIds:[[[NSSet setWithArray:mut] allObjects] mutableCopy] image:_thread.groupModel.groupImage groupId:_thread.groupModel.groupId associatedAttachmentId:nil]; - + [self.nameGroupTextField resignFirstResponder]; - + [self performSegueWithIdentifier:kUnwindToMessagesViewSegue sender:self]; } --(TSGroupModel*)makeGroup { - NSString* title = _nameGroupTextField.text; - NSMutableArray* mut = [[NSMutableArray alloc]init]; - - for (NSIndexPath* idx in _tableView.indexPathsForSelectedRows) { +- (TSGroupModel *)makeGroup { + NSString *title = _nameGroupTextField.text; + NSMutableArray *mut = [[NSMutableArray alloc] init]; + + for (NSIndexPath *idx in _tableView.indexPathsForSelectedRows) { [mut addObjectsFromArray:[[contacts objectAtIndex:(NSUInteger)idx.row] textSecureIdentifiers]]; } - [mut addObject:[SignalKeyingStorage.localNumber toE164]]; - NSData* groupId = [SecurityUtils generateRandomBytes:16]; - - return [[TSGroupModel alloc] initWithTitle:title memberIds:mut image:_groupImage groupId:groupId associatedAttachmentId:nil]; + [mut addObject:[TSAccountManager localNumber]]; + NSData *groupId = [SecurityUtils generateRandomBytes:16]; + + return [[TSGroupModel alloc] initWithTitle:title + memberIds:mut + image:_groupImage + groupId:groupId + associatedAttachmentId:nil]; } --(IBAction)addGroupPhoto:(id)sender -{ +- (IBAction)addGroupPhoto:(id)sender { [self.nameGroupTextField resignFirstResponder]; - [DJWActionSheet showInView:self.parentViewController.view withTitle:nil cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") - destructiveButtonTitle:nil otherButtonTitles:@[NSLocalizedString(@"TAKE_PICTURE_BUTTON", @""),NSLocalizedString(@"CHOOSE_MEDIA_BUTTON", @"")] + [DJWActionSheet showInView:self.parentViewController.view + withTitle:nil + cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") + destructiveButtonTitle:nil + otherButtonTitles:@[ + NSLocalizedString(@"TAKE_PICTURE_BUTTON", @""), + NSLocalizedString(@"CHOOSE_MEDIA_BUTTON", @"") + ] tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) { - - if (tappedButtonIndex == actionSheet.cancelButtonIndex) { - DDLogDebug(@"User Cancelled"); - } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { - DDLogDebug(@"Destructive button tapped"); - }else { - switch (tappedButtonIndex) { - case 0: - [self takePicture]; - break; - case 1: - [self chooseFromLibrary]; - break; - default: - break; - } - } - }]; + + if (tappedButtonIndex == actionSheet.cancelButtonIndex) { + DDLogDebug(@"User Cancelled"); + } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { + DDLogDebug(@"Destructive button tapped"); + } else { + switch (tappedButtonIndex) { + case 0: + [self takePicture]; + break; + case 1: + [self chooseFromLibrary]; + break; + default: + break; + } + } + }]; } #pragma mark - Group Image --(void)takePicture -{ +- (void)takePicture { UIImagePickerController *picker = [[UIImagePickerController alloc] init]; - picker.delegate = self; - picker.allowsEditing = NO; - picker.sourceType = UIImagePickerControllerSourceTypeCamera; - - if ([UIImagePickerController isSourceTypeAvailable: - UIImagePickerControllerSourceTypeCamera]) - { - picker.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *)kUTTypeImage, nil]; + picker.delegate = self; + picker.allowsEditing = NO; + picker.sourceType = UIImagePickerControllerSourceTypeCamera; + + if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { + picker.mediaTypes = [[NSArray alloc] initWithObjects:(NSString *)kUTTypeImage, nil]; [self presentViewController:picker animated:YES completion:[UIUtil modalCompletionBlock]]; } } --(void)chooseFromLibrary -{ +- (void)chooseFromLibrary { UIImagePickerController *picker = [[UIImagePickerController alloc] init]; - picker.delegate = self; - picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; - - if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum]) - { + picker.delegate = self; + picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; + + if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum]) { picker.mediaTypes = [[NSArray alloc] initWithObjects:(NSString *)kUTTypeImage, nil]; [self presentViewController:picker animated:YES completion:[UIUtil modalCompletionBlock]]; } - } /* @@ -218,26 +223,24 @@ static NSString* const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue" /* * Fetch data from UIImagePickerController */ --(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info -{ +- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *picture_camera = [info objectForKey:UIImagePickerControllerOriginalImage]; - - if (picture_camera) { - UIImage *small = [picture_camera resizedImageToFitInSize:CGSizeMake(100.00,100.00) scaleIfSmaller:NO]; - _thread.groupModel.groupImage = small; - _groupImage = small; - [self setupGroupImageButton:small]; + if (picture_camera) { + UIImage *small = [picture_camera resizedImageToFitInSize:CGSizeMake(100.00, 100.00) scaleIfSmaller:NO]; + _thread.groupModel.groupImage = small; + _groupImage = small; + [self setupGroupImageButton:small]; } [self dismissViewControllerAnimated:YES completion:nil]; } --(void)setupGroupImageButton:(UIImage*)image { +- (void)setupGroupImageButton:(UIImage *)image { [_groupImageButton setImage:image forState:UIControlStateNormal]; - _groupImageButton.imageView.layer.cornerRadius = CGRectGetWidth([_groupImageButton.imageView frame])/2.0f; + _groupImageButton.imageView.layer.cornerRadius = CGRectGetWidth([_groupImageButton.imageView frame]) / 2.0f; _groupImageButton.imageView.layer.masksToBounds = YES; - _groupImageButton.imageView.layer.borderColor = [[UIColor lightGrayColor] CGColor]; - _groupImageButton.imageView.layer.borderWidth = 0.5f; + _groupImageButton.imageView.layer.borderColor = [[UIColor lightGrayColor] CGColor]; + _groupImageButton.imageView.layer.borderWidth = 0.5f; } #pragma mark - Table view data source @@ -248,81 +251,88 @@ static NSString* const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue" - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return (NSInteger)[contacts count]; - } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SearchCell"]; - + if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"GroupSearchCell"]; } - - NSUInteger row = (NSUInteger)indexPath.row; - Contact* contact = contacts[row]; - + + NSUInteger row = (NSUInteger)indexPath.row; + Contact *contact = contacts[row]; + cell.textLabel.attributedText = [self attributedStringForContact:contact inCell:cell]; - + tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; - + if ([[tableView indexPathsForSelectedRows] containsObject:indexPath]) { [self adjustSelected:cell]; } - + return cell; } #pragma mark - Table View delegate --(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ - UITableViewCell * cell = [tableView cellForRowAtIndexPath:indexPath]; +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; [self adjustSelected:cell]; } -- (void)adjustSelected:(UITableViewCell*)cell { +- (void)adjustSelected:(UITableViewCell *)cell { cell.accessoryType = UITableViewCellAccessoryCheckmark; } --(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath -{ - UITableViewCell * cell = [tableView cellForRowAtIndexPath:indexPath]; - cell.accessoryType = UITableViewCellAccessoryNone; +- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; + cell.accessoryType = UITableViewCellAccessoryNone; } #pragma mark - Text Field Delegate -- (BOOL)textFieldShouldReturn:(UITextField *)textField{ +- (BOOL)textFieldShouldReturn:(UITextField *)textField { [self.nameGroupTextField resignFirstResponder]; return NO; } #pragma mark - Cell Utility -- (NSAttributedString *)attributedStringForContact:(Contact *)contact inCell:(UITableViewCell*)cell { - NSMutableAttributedString *fullNameAttributedString = [[NSMutableAttributedString alloc] initWithString:contact.fullName]; - +- (NSAttributedString *)attributedStringForContact:(Contact *)contact inCell:(UITableViewCell *)cell { + NSMutableAttributedString *fullNameAttributedString = + [[NSMutableAttributedString alloc] initWithString:contact.fullName]; + UIFont *firstNameFont; UIFont *lastNameFont; - + if (ABPersonGetSortOrdering() == kABPersonCompositeNameFormatFirstNameFirst) { - firstNameFont = [UIFont ows_mediumFontWithSize:cell.textLabel.font.pointSize]; + firstNameFont = [UIFont ows_mediumFontWithSize:cell.textLabel.font.pointSize]; lastNameFont = [UIFont ows_regularFontWithSize:cell.textLabel.font.pointSize]; - } else{ + } else { firstNameFont = [UIFont ows_regularFontWithSize:cell.textLabel.font.pointSize]; lastNameFont = [UIFont ows_mediumFontWithSize:cell.textLabel.font.pointSize]; } - [fullNameAttributedString addAttribute:NSFontAttributeName value:firstNameFont range:NSMakeRange(0, contact.firstName.length)]; - [fullNameAttributedString addAttribute:NSFontAttributeName value:lastNameFont range:NSMakeRange(contact.firstName.length + 1, contact.lastName.length)]; - - [fullNameAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0, contact.fullName.length)]; - + [fullNameAttributedString addAttribute:NSFontAttributeName + value:firstNameFont + range:NSMakeRange(0, contact.firstName.length)]; + [fullNameAttributedString addAttribute:NSFontAttributeName + value:lastNameFont + range:NSMakeRange(contact.firstName.length + 1, contact.lastName.length)]; + + [fullNameAttributedString addAttribute:NSForegroundColorAttributeName + value:[UIColor blackColor] + range:NSMakeRange(0, contact.fullName.length)]; + if (ABPersonGetSortOrdering() == kABPersonCompositeNameFormatFirstNameFirst) { - [fullNameAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor ows_darkGrayColor] range:NSMakeRange(contact.firstName.length + 1, contact.lastName.length)]; + [fullNameAttributedString addAttribute:NSForegroundColorAttributeName + value:[UIColor ows_darkGrayColor] + range:NSMakeRange(contact.firstName.length + 1, contact.lastName.length)]; + } else { + [fullNameAttributedString addAttribute:NSForegroundColorAttributeName + value:[UIColor ows_darkGrayColor] + range:NSMakeRange(0, contact.firstName.length)]; } - else { - [fullNameAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor ows_darkGrayColor] range:NSMakeRange(0, contact.firstName.length)]; - } - + return fullNameAttributedString; } diff --git a/Signal/src/view controllers/NextResponderScrollView.m b/Signal/src/view controllers/NextResponderScrollView.m index bb1d905df..f130f96f5 100644 --- a/Signal/src/view controllers/NextResponderScrollView.m +++ b/Signal/src/view controllers/NextResponderScrollView.m @@ -3,24 +3,29 @@ @implementation NextResponderScrollView - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - if (!self.dragging){ - [self.nextResponder touchesBegan: touches withEvent:event]; + if (!self.dragging) { + [self.nextResponder touchesBegan:touches withEvent:event]; } else { - [super touchesBegan: touches withEvent: event]; + [self.nextResponder touchesBegan:touches withEvent:event]; + + [super touchesBegan:touches withEvent:event]; } } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - if (!self.dragging){ - [self.nextResponder touchesEnded: touches withEvent:event]; + if (!self.dragging) { + [self.nextResponder touchesEnded:touches withEvent:event]; } else { - [super touchesEnded: touches withEvent: event]; + [self.nextResponder touchesEnded:touches withEvent:event]; + [super touchesEnded:touches withEvent:event]; } } --(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { - if (!self.dragging){ +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { + if (!self.dragging) { [self.nextResponder touchesCancelled:touches withEvent:event]; } else { - [super touchesEnded: touches withEvent: event]; + [self.nextResponder touchesCancelled:touches withEvent:event]; + + [super touchesEnded:touches withEvent:event]; } } @end diff --git a/Signal/src/view controllers/NotificationSettingsOptionsViewController.m b/Signal/src/view controllers/NotificationSettingsOptionsViewController.m index b9cd6ae22..7a6e9ed3d 100644 --- a/Signal/src/view controllers/NotificationSettingsOptionsViewController.m +++ b/Signal/src/view controllers/NotificationSettingsOptionsViewController.m @@ -6,8 +6,8 @@ // Copyright (c) 2015 Open Whisper Systems. All rights reserved. // -#import "NotificationSettingsOptionsViewController.h" #import "Environment.h" +#import "NotificationSettingsOptionsViewController.h" #import "PreferencesUtil.h" @interface NotificationSettingsOptionsViewController () @@ -16,50 +16,45 @@ @implementation NotificationSettingsOptionsViewController -- (void)viewDidLoad -{ - self.options = @[@(NotificationNamePreview), - @(NotificationNameNoPreview), - @(NotificationNoNameNoPreview)]; - +- (void)viewDidLoad { + self.options = @[ @(NotificationNamePreview), @(NotificationNameNoPreview), @(NotificationNoNameNoPreview) ]; + [super viewDidLoad]; } #pragma mark - Table view data source -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView -{ +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section -{ +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return (NSInteger)[self.options count]; } -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ - UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"NotificationSettingsOption"]; +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 + reuseIdentifier:@"NotificationSettingsOption"]; PropertyListPreferences *prefs = [Environment preferences]; - NSUInteger notifType = [[self.options objectAtIndex:(NSUInteger)indexPath.row] unsignedIntegerValue]; + NSUInteger notifType = [[self.options objectAtIndex:(NSUInteger)indexPath.row] unsignedIntegerValue]; [[cell textLabel] setText:[prefs nameForNotificationPreviewType:notifType]]; - + NotificationType selectedNotifType = [prefs notificationPreviewType]; - + if (selectedNotifType == notifType) { cell.accessoryType = UITableViewCellAccessoryCheckmark; } - + return cell; } -- (NSString*)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { +- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { return NSLocalizedString(@"NOTIFICATIONS_FOOTER_WARNING", nil); } -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ - [Environment.preferences setNotificationPreviewType:[[self.options objectAtIndex:(NSUInteger)indexPath.row] unsignedIntegerValue]]; +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [Environment.preferences + setNotificationPreviewType:[[self.options objectAtIndex:(NSUInteger)indexPath.row] unsignedIntegerValue]]; [self.navigationController popViewControllerAnimated:YES]; } diff --git a/Signal/src/view controllers/NotificationSettingsViewController.m b/Signal/src/view controllers/NotificationSettingsViewController.m index 05b835f59..502e73436 100755 --- a/Signal/src/view controllers/NotificationSettingsViewController.m +++ b/Signal/src/view controllers/NotificationSettingsViewController.m @@ -9,8 +9,8 @@ #import "NotificationSettingsViewController.h" #import "Environment.h" -#import "PreferencesUtil.h" #import "NotificationSettingsOptionsViewController.h" +#import "PreferencesUtil.h" @interface NotificationSettingsViewController () @@ -24,86 +24,81 @@ return [super initWithStyle:UITableViewStyleGrouped]; } -- (void)viewDidLoad -{ +- (void)viewDidLoad { [super viewDidLoad]; [self setTitle:NSLocalizedString(@"SETTINGS_NOTIFICATIONS", nil)]; - - - self.notificationsSections = @[NSLocalizedString(@"NOTIFICATIONS_SECTION_BACKGROUND", nil), - NSLocalizedString(@"NOTIFICATIONS_SECTION_INAPP",nil)]; + + + self.notificationsSections = @[ + NSLocalizedString(@"NOTIFICATIONS_SECTION_BACKGROUND", nil), + NSLocalizedString(@"NOTIFICATIONS_SECTION_INAPP", nil) + ]; } -- (void)viewDidAppear:(BOOL)animated -{ +- (void)viewDidAppear:(BOOL)animated { [self.tableView reloadData]; } #pragma mark - Table view data source -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return [self.notificationsSections objectAtIndex:(NSUInteger)section]; } -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView -{ +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return (NSInteger)self.notificationsSections.count; } -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section -{ +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 1; } -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *cellIdentifier = @"SignalTableViewCellIdentifier"; - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; - + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; + if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier]; } - + PropertyListPreferences *prefs = Environment.preferences; if (indexPath.section == 0) { NotificationType notifType = [prefs notificationPreviewType]; NSString *detailString = [prefs nameForNotificationPreviewType:notifType]; - - [[cell textLabel]setText:NSLocalizedString(@"NOTIFICATIONS_SHOW", nil)]; + + [[cell textLabel] setText:NSLocalizedString(@"NOTIFICATIONS_SHOW", nil)]; [[cell detailTextLabel] setText:detailString]; [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; } else { BOOL soundEnabled = [prefs soundInForeground]; - - [[cell textLabel]setText:NSLocalizedString(@"NOTIFICATIONS_SOUND", nil)]; + + [[cell textLabel] setText:NSLocalizedString(@"NOTIFICATIONS_SOUND", nil)]; [[cell detailTextLabel] setText:nil]; UISwitch *switchv = [[UISwitch alloc] initWithFrame:CGRectZero]; switchv.on = soundEnabled; [switchv addTarget:self - action:@selector(didToggleSoundNotificationsSwitch:) - forControlEvents:UIControlEventValueChanged]; - + action:@selector(didToggleSoundNotificationsSwitch:) + forControlEvents:UIControlEventValueChanged]; + cell.accessoryView = switchv; } - + return cell; } -- (void)didToggleSoundNotificationsSwitch:(UISwitch*)sender -{ +- (void)didToggleSoundNotificationsSwitch:(UISwitch *)sender { [Environment.preferences setSoundInForeground:sender.on]; } -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ - NotificationSettingsOptionsViewController *vc = [[NotificationSettingsOptionsViewController alloc] initWithStyle:UITableViewStyleGrouped]; +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + NotificationSettingsOptionsViewController *vc = + [[NotificationSettingsOptionsViewController alloc] initWithStyle:UITableViewStyleGrouped]; [self.navigationController pushViewController:vc animated:YES]; } -- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath -{ +- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; - cell.accessoryType = UITableViewCellAccessoryNone; + cell.accessoryType = UITableViewCellAccessoryNone; } @end diff --git a/Signal/src/view controllers/PresentIdentityQRCodeViewController.h b/Signal/src/view controllers/PresentIdentityQRCodeViewController.h index f5242d0d1..7e2ca34f8 100644 --- a/Signal/src/view controllers/PresentIdentityQRCodeViewController.h +++ b/Signal/src/view controllers/PresentIdentityQRCodeViewController.h @@ -9,8 +9,8 @@ #import @interface PresentIdentityQRCodeViewController : UIViewController -@property(nonatomic,strong) IBOutlet UIImageView* qrCodeView; -@property(nonatomic,strong) IBOutlet UILabel *yourFingerprintLabel; -@property(nonatomic,strong) NSData* identityKey; +@property (nonatomic, strong) IBOutlet UIImageView *qrCodeView; +@property (nonatomic, strong) IBOutlet UILabel *yourFingerprintLabel; +@property (nonatomic, strong) NSData *identityKey; @end diff --git a/Signal/src/view controllers/PresentIdentityQRCodeViewController.m b/Signal/src/view controllers/PresentIdentityQRCodeViewController.m index 2f89d3627..7b6259dcc 100644 --- a/Signal/src/view controllers/PresentIdentityQRCodeViewController.m +++ b/Signal/src/view controllers/PresentIdentityQRCodeViewController.m @@ -6,12 +6,11 @@ // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // -#import "PresentIdentityQRCodeViewController.h" #import "NSData+Base64.h" +#import "PresentIdentityQRCodeViewController.h" #import "UIImage+normalizeImage.h" - @implementation PresentIdentityQRCodeViewController @@ -20,28 +19,28 @@ } - -- (void) viewDidLoad { +- (void)viewDidLoad { [super viewDidLoad]; CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"]; - + [filter setDefaults]; - [filter setValue:[[self.identityKey base64EncodedString] dataUsingEncoding:NSUTF8StringEncoding] forKey:@"inputMessage"]; - + [filter setValue:[[self.identityKey base64EncodedString] dataUsingEncoding:NSUTF8StringEncoding] + forKey:@"inputMessage"]; + CIImage *outputImage = [filter outputImage]; - + CIContext *context = [CIContext contextWithOptions:nil]; CGImageRef cgImage = [context createCGImage:outputImage fromRect:[outputImage extent]]; - + UIImage *image = [UIImage imageWithCGImage:cgImage scale:1. orientation:UIImageOrientationUp]; - + // Resize without interpolating UIImage *resized = [image resizedWithQuality:kCGInterpolationNone rate:5.0]; - - self.qrCodeView.image = resized; - _yourFingerprintLabel.text = NSLocalizedString(@"FINGERPRINT_YOURS",@""); + + self.qrCodeView.image = resized; + _yourFingerprintLabel.text = NSLocalizedString(@"FINGERPRINT_YOURS", @""); CGImageRelease(cgImage); } diff --git a/Signal/src/view controllers/PrivacySettingsTableViewController.m b/Signal/src/view controllers/PrivacySettingsTableViewController.m index ee67f569f..638b490d8 100644 --- a/Signal/src/view controllers/PrivacySettingsTableViewController.m +++ b/Signal/src/view controllers/PrivacySettingsTableViewController.m @@ -17,16 +17,16 @@ @interface PrivacySettingsTableViewController () -@property (nonatomic, strong) UITableViewCell * enableScreenSecurityCell; -@property (nonatomic, strong) UITableViewCell * clearHistoryLogCell; -@property (nonatomic, strong) UITableViewCell * fingerprintCell; -@property (nonatomic, strong) UITableViewCell * shareFingerprintCell; +@property (nonatomic, strong) UITableViewCell *enableScreenSecurityCell; +@property (nonatomic, strong) UITableViewCell *clearHistoryLogCell; +@property (nonatomic, strong) UITableViewCell *fingerprintCell; +@property (nonatomic, strong) UITableViewCell *shareFingerprintCell; -@property (nonatomic, strong) UISwitch * enableScreenSecuritySwitch; +@property (nonatomic, strong) UISwitch *enableScreenSecuritySwitch; -@property (nonatomic, strong) UILabel * fingerprintLabel; +@property (nonatomic, strong) UILabel *fingerprintLabel; -@property (nonatomic, strong) NSTimer * copiedTimer; +@property (nonatomic, strong) NSTimer *copiedTimer; @end @@ -36,61 +36,60 @@ [super viewDidLoad]; [self.navigationController.navigationBar setTranslucent:NO]; - self.tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero]; + self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; } --(instancetype)init -{ +- (instancetype)init { return [super initWithStyle:UITableViewStyleGrouped]; } --(void)loadView -{ +- (void)loadView { [super loadView]; - + self.title = NSLocalizedString(@"SETTINGS_PRIVACY_TITLE", @""); - - //Enable Screen Security Cell - self.enableScreenSecurityCell = [[UITableViewCell alloc]init]; + + // Enable Screen Security Cell + self.enableScreenSecurityCell = [[UITableViewCell alloc] init]; self.enableScreenSecurityCell.textLabel.text = NSLocalizedString(@"SETTINGS_SCREEN_SECURITY", @""); - - self.enableScreenSecuritySwitch = [[UISwitch alloc]initWithFrame:CGRectZero]; - - self.enableScreenSecurityCell.accessoryView = self.enableScreenSecuritySwitch; + + self.enableScreenSecuritySwitch = [[UISwitch alloc] initWithFrame:CGRectZero]; + + self.enableScreenSecurityCell.accessoryView = self.enableScreenSecuritySwitch; self.enableScreenSecurityCell.userInteractionEnabled = YES; - - //Clear History Log Cell - self.clearHistoryLogCell = [[UITableViewCell alloc]init]; + + // Clear History Log Cell + self.clearHistoryLogCell = [[UITableViewCell alloc] init]; self.clearHistoryLogCell.textLabel.text = NSLocalizedString(@"SETTINGS_CLEAR_HISTORY", @""); - self.clearHistoryLogCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - - //Fingerprint Cell - self.fingerprintCell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"Identifier"]; - self.fingerprintCell.textLabel.text = NSLocalizedString(@"SETTINGS_FINGERPRINT", @""); - self.fingerprintCell.detailTextLabel.text = NSLocalizedString(@"SETTINGS_FINGERPRINT_COPY",nil); + self.clearHistoryLogCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + + // Fingerprint Cell + self.fingerprintCell = + [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"Identifier"]; + self.fingerprintCell.textLabel.text = NSLocalizedString(@"SETTINGS_FINGERPRINT", @""); + self.fingerprintCell.detailTextLabel.text = NSLocalizedString(@"SETTINGS_FINGERPRINT_COPY", nil); self.fingerprintCell.detailTextLabel.textColor = [UIColor lightGrayColor]; - - self.fingerprintLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 150, 25)]; - self.fingerprintLabel.textColor = [UIColor lightGrayColor]; - self.fingerprintLabel.font = [UIFont ows_regularFontWithSize:16.0f]; + + self.fingerprintLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 150, 25)]; + self.fingerprintLabel.textColor = [UIColor lightGrayColor]; + self.fingerprintLabel.font = [UIFont ows_regularFontWithSize:16.0f]; self.fingerprintLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; - + self.fingerprintCell.accessoryView = self.fingerprintLabel; - + [self setValues]; [self subsribeToEvents]; - } --(void)subsribeToEvents -{ - [self.enableScreenSecuritySwitch addTarget:self action:@selector(didToggleSwitch:) forControlEvents:UIControlEventTouchUpInside]; +- (void)subsribeToEvents { + [self.enableScreenSecuritySwitch addTarget:self + action:@selector(didToggleSwitch:) + forControlEvents:UIControlEventTouchUpInside]; } --(void)setValues -{ +- (void)setValues { [self.enableScreenSecuritySwitch setOn:[Environment.preferences screenSecurityIsEnabled]]; - self.fingerprintLabel.text = [TSFingerprintGenerator getFingerprintForDisplay:[[TSStorageManager sharedManager]identityKeyPair].publicKey]; + self.fingerprintLabel.text = + [TSFingerprintGenerator getFingerprintForDisplay:[[TSStorageManager sharedManager] identityKeyPair].publicKey]; } #pragma mark - Table view data source @@ -101,79 +100,92 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { switch (section) { - case 0: return 1; - case 1: return 1; - case 2: return 1; - default: return 0; + case 0: + return 1; + case 1: + return 1; + case 2: + return 1; + default: + return 0; } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - switch (indexPath.section) { - case 0: return self.enableScreenSecurityCell; - case 1: return self.clearHistoryLogCell; + case 0: + return self.enableScreenSecurityCell; + case 1: + return self.clearHistoryLogCell; case 2: switch (indexPath.row) { - case 0: return self.fingerprintCell; - case 1: return self.shareFingerprintCell; + case 0: + return self.fingerprintCell; + case 1: + return self.shareFingerprintCell; } } - + return nil; } -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section -{ +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { switch (section) { - case 0: return NSLocalizedString(@"SETTINGS_SECURITY_TITLE", @""); - case 1: return NSLocalizedString(@"SETTINGS_HISTORYLOG_TITLE", @""); - case 2: return NSLocalizedString(@"SETTINGS_FINGERPRINT", @""); - default: return nil; + case 0: + return NSLocalizedString(@"SETTINGS_SECURITY_TITLE", @""); + case 1: + return NSLocalizedString(@"SETTINGS_HISTORYLOG_TITLE", @""); + case 2: + return NSLocalizedString(@"SETTINGS_FINGERPRINT", @""); + default: + return nil; } } --(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; switch (indexPath.section) { - case 1: - { + case 1: { [DJWActionSheet showInView:self.parentViewController.view withTitle:NSLocalizedString(@"SETTINGS_DELETE_HISTORYLOG_CONFIRMATION", @"") cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") destructiveButtonTitle:NSLocalizedString(@"SETTINGS_DELETE_HISTORYLOG_CONFIRMATION_BUTTON", @"") otherButtonTitles:@[] tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) { - [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; - if (tappedButtonIndex == actionSheet.cancelButtonIndex) { - DDLogDebug(@"User Cancelled"); - } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex){ - [[TSStorageManager sharedManager] deleteThreadsAndMessages]; - } else { - DDLogDebug(@"The user tapped button at index: %li", (long)tappedButtonIndex); - } + [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; + if (tappedButtonIndex == actionSheet.cancelButtonIndex) { + DDLogDebug(@"User Cancelled"); + } else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) { + [[TSStorageManager sharedManager] deleteThreadsAndMessages]; + } else { + DDLogDebug(@"The user tapped button at index: %li", (long)tappedButtonIndex); + } }]; break; } - + case 2: switch (indexPath.row) { - case 0: - { - //Timer to change label to copied (NSTextAttachment checkmark) + case 0: { + // Timer to change label to copied (NSTextAttachment checkmark) if (self.copiedTimer == nil) { - self.copiedTimer = [NSTimer scheduledTimerWithTimeInterval:2.0f target:self selector:@selector(endTimer:) userInfo:nil repeats:NO]; - self.fingerprintCell.detailTextLabel.text = NSLocalizedString(@"SETTINGS_FINGERPRINT_COPY_SUCCESS", @""); + self.copiedTimer = [NSTimer scheduledTimerWithTimeInterval:2.0f + target:self + selector:@selector(endTimer:) + userInfo:nil + repeats:NO]; + self.fingerprintCell.detailTextLabel.text = + NSLocalizedString(@"SETTINGS_FINGERPRINT_COPY_SUCCESS", @""); } else { - self.fingerprintCell.detailTextLabel.text = NSLocalizedString(@"SETTINGS_FINGERPRINT_COPY",nil); + self.fingerprintCell.detailTextLabel.text = + NSLocalizedString(@"SETTINGS_FINGERPRINT_COPY", nil); } [[UIPasteboard generalPasteboard] setString:self.fingerprintLabel.text]; break; } - + default: break; } @@ -185,16 +197,14 @@ #pragma mark - Toggle --(void)didToggleSwitch:(UISwitch*)sender -{ +- (void)didToggleSwitch:(UISwitch *)sender { [Environment.preferences setScreenSecurity:self.enableScreenSecuritySwitch.isOn]; } - + #pragma mark - Timer --(void)endTimer:(id)sender -{ - self.fingerprintCell.detailTextLabel.text = NSLocalizedString(@"SETTINGS_FINGERPRINT_COPY",nil); +- (void)endTimer:(id)sender { + self.fingerprintCell.detailTextLabel.text = NSLocalizedString(@"SETTINGS_FINGERPRINT_COPY", nil); [self.copiedTimer invalidate]; self.copiedTimer = nil; } diff --git a/Signal/src/view controllers/RegistrationViewController.h b/Signal/src/view controllers/RegistrationViewController.h index 0dc7364dc..f76279a3f 100644 --- a/Signal/src/view controllers/RegistrationViewController.h +++ b/Signal/src/view controllers/RegistrationViewController.h @@ -10,20 +10,20 @@ #import "CountryCodeViewController.h" -@interface RegistrationViewController : UIViewController +@interface RegistrationViewController : UIViewController // Country code -@property (nonatomic, strong) IBOutlet UIButton* countryNameButton; -@property (nonatomic, strong) IBOutlet UIButton* countryCodeButton; +@property (nonatomic, strong) IBOutlet UIButton *countryNameButton; +@property (nonatomic, strong) IBOutlet UIButton *countryCodeButton; -//Phone number -@property(nonatomic, strong) IBOutlet UITextField* phoneNumberTextField; -@property(nonatomic, strong) IBOutlet UIButton *phoneNumberButton; -@property(nonatomic, strong) IBOutlet UILabel* titleLabel; -//Button -@property(nonatomic, strong) IBOutlet UIButton* sendCodeButton; +// Phone number +@property (nonatomic, strong) IBOutlet UITextField *phoneNumberTextField; +@property (nonatomic, strong) IBOutlet UIButton *phoneNumberButton; +@property (nonatomic, strong) IBOutlet UILabel *titleLabel; +// Button +@property (nonatomic, strong) IBOutlet UIButton *sendCodeButton; -@property (nonatomic, strong) IBOutlet UIActivityIndicatorView* spinnerView; +@property (nonatomic, strong) IBOutlet UIActivityIndicatorView *spinnerView; @property (nonatomic) IBOutlet UIImageView *signalLogo; @property (nonatomic) IBOutlet UIView *registrationHeader; diff --git a/Signal/src/view controllers/RegistrationViewController.m b/Signal/src/view controllers/RegistrationViewController.m index 6ea26c64e..e3a4b2c81 100644 --- a/Signal/src/view controllers/RegistrationViewController.m +++ b/Signal/src/view controllers/RegistrationViewController.m @@ -9,13 +9,13 @@ #import "RegistrationViewController.h" +#import "CodeVerificationViewController.h" #import "Environment.h" #import "LocalizableText.h" #import "PhoneNumber.h" -#import "CodeVerificationViewController.h" #import "PhoneNumberUtil.h" -#import "RPServerRequestsManager.h" #import "SignalKeyingStorage.h" +#import "TSAccountManager.h" #import "Util.h" static NSString *const kCodeSentSegue = @"codeSent"; @@ -30,28 +30,29 @@ static NSString *const kCodeSentSegue = @"codeSent"; - (void)viewDidLoad { [super viewDidLoad]; - + // Do any additional setup after loading the view. _phoneNumberTextField.delegate = self; [self populateDefaultCountryNameAndCode]; [[Environment getCurrent] setSignUpFlowNavigationController:self.navigationController]; - - _titleLabel.text = NSLocalizedString(@"REGISTRATION_TITLE_LABEL", @""); - [_countryNameButton setTitle:NSLocalizedString(@"REGISTRATION_DEFAULT_COUNTRY_NAME", @"") forState:UIControlStateNormal]; - _phoneNumberTextField.placeholder = NSLocalizedString(@"REGISTRATION_ENTERNUMBER_DEFAULT_TEXT", @""); - [_phoneNumberButton setTitle:NSLocalizedString(@"REGISTRATION_PHONENUMBER_BUTTON",@"") forState:UIControlStateNormal]; + + _titleLabel.text = NSLocalizedString(@"REGISTRATION_TITLE_LABEL", @""); + [_countryNameButton setTitle:NSLocalizedString(@"REGISTRATION_DEFAULT_COUNTRY_NAME", @"") + forState:UIControlStateNormal]; + _phoneNumberTextField.placeholder = NSLocalizedString(@"REGISTRATION_ENTERNUMBER_DEFAULT_TEXT", @""); + [_phoneNumberButton setTitle:NSLocalizedString(@"REGISTRATION_PHONENUMBER_BUTTON", @"") + forState:UIControlStateNormal]; [_phoneNumberButton.titleLabel setAdjustsFontSizeToFitWidth:YES]; [_sendCodeButton setTitle:NSLocalizedString(@"REGISTRATION_VERIFY_DEVICE", @"") forState:UIControlStateNormal]; } --(void)viewWillAppear:(BOOL)animated{ +- (void)viewWillAppear:(BOOL)animated { [self adjustScreenSizes]; } --(void)viewDidAppear:(BOOL)animated -{ +- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; - + [_sendCodeButton setEnabled:YES]; [_spinnerView stopAnimating]; [_phoneNumberTextField becomeFirstResponder]; @@ -66,46 +67,45 @@ static NSString *const kCodeSentSegue = @"codeSent"; #pragma mark - Locale - (void)populateDefaultCountryNameAndCode { - NSLocale *locale = NSLocale.currentLocale; + NSLocale *locale = NSLocale.currentLocale; NSString *countryCode = [locale objectForKey:NSLocaleCountryCode]; - NSNumber *cc = [[PhoneNumberUtil sharedInstance].nbPhoneNumberUtil getCountryCodeForRegion:countryCode]; - - [_countryCodeButton setTitle:[NSString stringWithFormat:@"%@%@",COUNTRY_CODE_PREFIX, cc] forState:UIControlStateNormal]; - [_countryNameButton setTitle:[PhoneNumberUtil countryNameFromCountryCode:countryCode] forState:UIControlStateNormal]; + NSNumber *cc = [[PhoneNumberUtil sharedUtil].nbPhoneNumberUtil getCountryCodeForRegion:countryCode]; + + [_countryCodeButton setTitle:[NSString stringWithFormat:@"%@%@", COUNTRY_CODE_PREFIX, cc] + forState:UIControlStateNormal]; + [_countryNameButton setTitle:[PhoneNumberUtil countryNameFromCountryCode:countryCode] + forState:UIControlStateNormal]; } #pragma mark - Actions - (IBAction)sendCodeAction:(id)sender { - NSString *phoneNumber = [NSString stringWithFormat:@"%@%@", _countryCodeButton.titleLabel.text, _phoneNumberTextField.text]; - PhoneNumber* localNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:phoneNumber]; - if(localNumber==nil){ return; } - + NSString *phoneNumber = + [NSString stringWithFormat:@"%@%@", _countryCodeButton.titleLabel.text, _phoneNumberTextField.text]; + PhoneNumber *localNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:phoneNumber]; + [_sendCodeButton setEnabled:NO]; [_spinnerView startAnimating]; [_phoneNumberTextField resignFirstResponder]; - [SignalKeyingStorage setLocalNumberTo:localNumber]; - - [[RPServerRequestsManager sharedInstance]performRequest:[RPAPICall requestVerificationCode] success:^(NSURLSessionDataTask *task, id responseObject) { - [self performSegueWithIdentifier:@"codeSent" sender:self]; - [_spinnerView stopAnimating]; - } failure:^(NSURLSessionDataTask *task, NSError *error) { - - DDLogError(@"Registration failed with information %@", error.description); - - UIAlertView *registrationErrorAV = [[UIAlertView alloc]initWithTitle:REGISTER_ERROR_ALERT_VIEW_TITLE - message:REGISTER_ERROR_ALERT_VIEW_BODY - delegate:nil - cancelButtonTitle:REGISTER_ERROR_ALERT_VIEW_DISMISS - otherButtonTitles:nil, nil]; - - [registrationErrorAV show]; - - [_sendCodeButton setEnabled:YES]; - [_spinnerView stopAnimating]; - }]; - + + [TSAccountManager registerWithPhoneNumber:localNumber.toE164 + success:^{ + [self performSegueWithIdentifier:@"codeSent" sender:self]; + [_spinnerView stopAnimating]; + } + failure:^(NSError *error) { + if (error.code == 400) { + SignalAlertView(NSLocalizedString(@"REGISTRATION_ERROR", nil), + NSLocalizedString(@"REGISTRATION_NON_VALID_NUMBER", )); + } else { + SignalAlertView(error.localizedDescription, error.localizedRecoverySuggestion); + } + + [_sendCodeButton setEnabled:YES]; + [_spinnerView stopAnimating]; + } + smsVerification:YES]; } - (IBAction)changeCountryCodeTapped { @@ -124,88 +124,93 @@ static NSString *const kCodeSentSegue = @"codeSent"; #pragma mark - Keyboard notifications -- (void)initializeKeyboardHandlers{ - UITapGestureRecognizer *outsideTabRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)]; +- (void)initializeKeyboardHandlers { + UITapGestureRecognizer *outsideTabRecognizer = + [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)]; [self.view addGestureRecognizer:outsideTabRecognizer]; } --(void) dismissKeyboardFromAppropriateSubView { +- (void)dismissKeyboardFromAppropriateSubView { [self.view endEditing:NO]; } #pragma mark - UITextFieldDelegate --(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { - NSString* textBeforeChange = textField.text; - +- (BOOL)textField:(UITextField *)textField + shouldChangeCharactersInRange:(NSRange)range + replacementString:(NSString *)string { + NSString *textBeforeChange = textField.text; + // backspacing should skip over formatting characters UITextPosition *posIfBackspace = [textField positionFromPosition:textField.beginningOfDocument offset:(NSInteger)(range.location + range.length)]; UITextRange *rangeIfBackspace = [textField textRangeFromPosition:posIfBackspace toPosition:posIfBackspace]; - bool isBackspace = string.length == 0 && range.length == 1 && [rangeIfBackspace isEqual:textField.selectedTextRange]; + bool isBackspace = + string.length == 0 && range.length == 1 && [rangeIfBackspace isEqual:textField.selectedTextRange]; if (isBackspace) { - NSString* digits = textBeforeChange.digitsOnly; + NSString *digits = textBeforeChange.digitsOnly; NSUInteger correspondingDeletePosition = [PhoneNumberUtil translateCursorPosition:range.location + range.length from:textBeforeChange to:digits stickingRightward:true]; if (correspondingDeletePosition > 0) { textBeforeChange = digits; - range = NSMakeRange(correspondingDeletePosition - 1, 1); + range = NSMakeRange(correspondingDeletePosition - 1, 1); } } - + // make the proposed change - NSString* textAfterChange = [textBeforeChange withCharactersInRange:range replacedBy:string]; + NSString *textAfterChange = [textBeforeChange withCharactersInRange:range replacedBy:string]; NSUInteger cursorPositionAfterChange = range.location + string.length; - + // reformat the phone number, trying to keep the cursor beside the inserted or deleted digit bool isJustDeletion = string.length == 0; - NSString* textAfterReformat = [PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:textAfterChange.digitsOnly - withSpecifiedCountryCodeString:_countryCodeButton.titleLabel.text]; + NSString *textAfterReformat = + [PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:textAfterChange.digitsOnly + withSpecifiedCountryCodeString:_countryCodeButton.titleLabel.text]; NSUInteger cursorPositionAfterReformat = [PhoneNumberUtil translateCursorPosition:cursorPositionAfterChange from:textAfterChange to:textAfterReformat stickingRightward:isJustDeletion]; textField.text = textAfterReformat; - UITextPosition *pos = [textField positionFromPosition:textField.beginningOfDocument - offset:(NSInteger)cursorPositionAfterReformat]; + UITextPosition *pos = + [textField positionFromPosition:textField.beginningOfDocument offset:(NSInteger)cursorPositionAfterReformat]; [textField setSelectedTextRange:[textField textRangeFromPosition:pos toPosition:pos]]; - + return NO; // inform our caller that we took care of performing the change } #pragma mark - Unwind segue -- (IBAction)unwindToChangeNumber:(UIStoryboardSegue*)sender { - +- (IBAction)unwindToChangeNumber:(UIStoryboardSegue *)sender { } - (IBAction)unwindToCountryCodeSelectionCancelled:(UIStoryboardSegue *)segue { - } - (IBAction)unwindToCountryCodeWasSelected:(UIStoryboardSegue *)segue { CountryCodeViewController *vc = [segue sourceViewController]; [_countryCodeButton setTitle:vc.callingCodeSelected forState:UIControlStateNormal]; [_countryNameButton setTitle:vc.countryNameSelected forState:UIControlStateNormal]; - + // Reformat phone number - NSString* digits = _phoneNumberTextField.text.digitsOnly; - NSString* reformattedNumber = [PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:digits - withSpecifiedCountryCodeString:_countryCodeButton.titleLabel.text]; + NSString *digits = _phoneNumberTextField.text.digitsOnly; + NSString *reformattedNumber = + [PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:digits + withSpecifiedCountryCodeString:_countryCodeButton.titleLabel.text]; _phoneNumberTextField.text = reformattedNumber; - UITextPosition *pos = _phoneNumberTextField.endOfDocument; + UITextPosition *pos = _phoneNumberTextField.endOfDocument; [_phoneNumberTextField setSelectedTextRange:[_phoneNumberTextField textRangeFromPosition:pos toPosition:pos]]; - } #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - if([[segue identifier] isEqualToString:kCodeSentSegue]) { - CodeVerificationViewController* vc = [segue destinationViewController]; - vc.formattedPhoneNumber = [PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:_phoneNumberTextField.text withSpecifiedCountryCodeString:_countryCodeButton.titleLabel.text]; + if ([[segue identifier] isEqualToString:kCodeSentSegue]) { + CodeVerificationViewController *vc = [segue destinationViewController]; + vc.formattedPhoneNumber = [PhoneNumber + bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:_phoneNumberTextField.text + withSpecifiedCountryCodeString:_countryCodeButton.titleLabel.text]; } } @@ -214,14 +219,14 @@ static NSString *const kCodeSentSegue = @"codeSent"; - (void)adjustScreenSizes { CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height; CGFloat blueHeaderHeight; - + if (screenHeight < 667) { self.signalLogo.hidden = YES; - blueHeaderHeight = screenHeight - 408; + blueHeaderHeight = screenHeight - 408; } else { blueHeaderHeight = screenHeight - 420; } - + _headerHeightConstraint.constant = blueHeaderHeight; } diff --git a/Signal/src/view controllers/ScanIdentityBarcodeViewController.h b/Signal/src/view controllers/ScanIdentityBarcodeViewController.h index dfdd009f7..a1c085ead 100644 --- a/Signal/src/view controllers/ScanIdentityBarcodeViewController.h +++ b/Signal/src/view controllers/ScanIdentityBarcodeViewController.h @@ -6,16 +6,16 @@ // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // -#import #import -@interface ScanIdentityBarcodeViewController : UIViewController +#import +@interface ScanIdentityBarcodeViewController : UIViewController -@property(nonatomic,strong) AVCaptureSession *session; -@property(nonatomic,strong) AVCaptureDevice *device; -@property(nonatomic,strong) AVCaptureDeviceInput *input; -@property(nonatomic,strong) AVCaptureMetadataOutput *output; -@property(nonatomic,strong) AVCaptureVideoPreviewLayer *prevLayer; +@property (nonatomic, strong) AVCaptureSession *session; +@property (nonatomic, strong) AVCaptureDevice *device; +@property (nonatomic, strong) AVCaptureDeviceInput *input; +@property (nonatomic, strong) AVCaptureMetadataOutput *output; +@property (nonatomic, strong) AVCaptureVideoPreviewLayer *prevLayer; -@property(nonatomic,strong) UIView *highlightView; -@property(nonatomic,strong) NSData *identityKey; +@property (nonatomic, strong) UIView *highlightView; +@property (nonatomic, strong) NSData *identityKey; @end diff --git a/Signal/src/view controllers/ScanIdentityBarcodeViewController.m b/Signal/src/view controllers/ScanIdentityBarcodeViewController.m index 58355311e..4f1ffd30b 100644 --- a/Signal/src/view controllers/ScanIdentityBarcodeViewController.m +++ b/Signal/src/view controllers/ScanIdentityBarcodeViewController.m @@ -6,90 +6,99 @@ // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // -#import "ScanIdentityBarcodeViewController.h" #import "NSData+Base64.h" +#import "ScanIdentityBarcodeViewController.h" #import "UIColor+OWS.h" - @implementation ScanIdentityBarcodeViewController - (void)viewDidLoad { [super viewDidLoad]; self.title = NSLocalizedString(@"SCAN_KEY", @""); - - self.highlightView = [[UIView alloc] init]; - self.highlightView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin; + + self.highlightView = [[UIView alloc] init]; + self.highlightView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | + UIViewAutoresizingFlexibleRightMargin | + UIViewAutoresizingFlexibleBottomMargin; self.highlightView.layer.borderColor = [UIColor ows_greenColor].CGColor; self.highlightView.layer.borderWidth = 4; [self.view addSubview:self.highlightView]; - - self.session = [[AVCaptureSession alloc] init]; - self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; + + self.session = [[AVCaptureSession alloc] init]; + self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; NSError *error = nil; - + self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:&error]; if (self.input) { [self.session addInput:self.input]; } else { DDLogDebug(@"Error: %@", error); } - + self.output = [[AVCaptureMetadataOutput alloc] init]; [self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; [self.session addOutput:self.output]; - + self.output.metadataObjectTypes = [self.output availableMetadataObjectTypes]; - - self.prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session]; - self.prevLayer.frame = self.view.bounds; + + self.prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session]; + self.prevLayer.frame = self.view.bounds; self.prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; [self.view.layer insertSublayer:self.prevLayer atIndex:0]; - + [self.session startRunning]; - + [self.view bringSubviewToFront:self.highlightView]; } -- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection { +- (void)captureOutput:(AVCaptureOutput *)captureOutput + didOutputMetadataObjects:(NSArray *)metadataObjects + fromConnection:(AVCaptureConnection *)connection { CGRect highlightViewRect = CGRectZero; AVMetadataMachineReadableCodeObject *barCodeObject; NSString *detectionString = nil; - NSArray *barCodeTypes = @[AVMetadataObjectTypeQRCode]; - + NSArray *barCodeTypes = @[ AVMetadataObjectTypeQRCode ]; + for (AVMetadataObject *metadata in metadataObjects) { for (NSString *type in barCodeTypes) { if ([metadata.type isEqualToString:type]) { - barCodeObject = (AVMetadataMachineReadableCodeObject *)[self.prevLayer transformedMetadataObjectForMetadataObject:(AVMetadataMachineReadableCodeObject *)metadata]; + barCodeObject = (AVMetadataMachineReadableCodeObject *)[self.prevLayer + transformedMetadataObjectForMetadataObject:(AVMetadataMachineReadableCodeObject *)metadata]; highlightViewRect = barCodeObject.bounds; - detectionString = [(AVMetadataMachineReadableCodeObject *)metadata stringValue]; + detectionString = [(AVMetadataMachineReadableCodeObject *)metadata stringValue]; break; } } if (detectionString != nil) { - NSData* detectionData = [NSData dataFromBase64String:detectionString]; - + NSData *detectionData = [NSData dataFromBase64String:detectionString]; + NSString *dialogTitle; NSString *dialogDescription; - - if([detectionData isEqualToData:self.identityKey]) { - dialogTitle = NSLocalizedString(@"SCAN_KEY_VERIFIED_TITLE", @""); + + if ([detectionData isEqualToData:self.identityKey]) { + dialogTitle = NSLocalizedString(@"SCAN_KEY_VERIFIED_TITLE", @""); dialogDescription = NSLocalizedString(@"SCAN_KEY_VERIFIED_TEXT", @""); - } - else { - dialogTitle = NSLocalizedString(@"SCAN_KEY_CONFLICT_TITLE", @""); + } else { + dialogTitle = NSLocalizedString(@"SCAN_KEY_CONFLICT_TITLE", @""); dialogDescription = NSLocalizedString(@"SCAN_KEY_CONFLICT_TEXT", @""); } - + [self.session stopRunning]; - UIAlertController *controller = [UIAlertController alertControllerWithTitle:dialogTitle message:dialogDescription preferredStyle:UIAlertControllerStyleAlert]; - - [self presentViewController:controller animated:YES completion:^{ - [self performSelector:@selector(dismissScannerAfterSuccesfullScan) withObject:nil afterDelay:5]; - }]; - + UIAlertController *controller = [UIAlertController alertControllerWithTitle:dialogTitle + message:dialogDescription + preferredStyle:UIAlertControllerStyleAlert]; + + [self presentViewController:controller + animated:YES + completion:^{ + [self performSelector:@selector(dismissScannerAfterSuccesfullScan) + withObject:nil + afterDelay:5]; + }]; + break; } } @@ -100,18 +109,14 @@ #pragma mark - Action - (void)dismissScannerAfterSuccesfullScan { - [self dismissViewControllerAnimated:YES completion:^{ - [self closeButtonAction:nil]; - }]; + [self dismissViewControllerAnimated:YES + completion:^{ + [self closeButtonAction:nil]; + }]; } -- (IBAction)closeButtonAction:(id)sender -{ +- (IBAction)closeButtonAction:(id)sender { [self performSegueWithIdentifier:@"UnwindToIdentityKeyWasVerifiedSegue" sender:self]; } @end - - - - diff --git a/Signal/src/view controllers/SettingsTableViewCell.h b/Signal/src/view controllers/SettingsTableViewCell.h index 30222e092..0a05bb071 100644 --- a/Signal/src/view controllers/SettingsTableViewCell.h +++ b/Signal/src/view controllers/SettingsTableViewCell.h @@ -10,10 +10,10 @@ @interface SettingsTableViewCell : UITableViewCell --(void)updateImageQualityLabel; +- (void)updateImageQualityLabel; -//Optionals -@property(nonatomic, strong) IBOutlet UISwitch* toggle; -@property(nonatomic,strong) IBOutlet UILabel* detailLabel; +// Optionals +@property (nonatomic, strong) IBOutlet UISwitch *toggle; +@property (nonatomic, strong) IBOutlet UILabel *detailLabel; @end diff --git a/Signal/src/view controllers/SettingsTableViewCell.m b/Signal/src/view controllers/SettingsTableViewCell.m index da0d4aa16..33cddb221 100644 --- a/Signal/src/view controllers/SettingsTableViewCell.m +++ b/Signal/src/view controllers/SettingsTableViewCell.m @@ -14,12 +14,11 @@ @implementation SettingsTableViewCell - (void)awakeFromNib { - if (self.toggle) { [self.toggle setOn:[Environment.preferences screenSecurityIsEnabled]]; [self.toggle addTarget:self action:@selector(toggleSetting:) forControlEvents:UIControlEventValueChanged]; } - + if ([self.reuseIdentifier isEqualToString:@"imageUploadQuality"]) { [self updateImageQualityLabel]; } @@ -31,8 +30,7 @@ #pragma mark - UISwitch --(void)toggleSetting:(id)sender -{ +- (void)toggleSetting:(id)sender { if ([self.reuseIdentifier isEqualToString:@"enableScreenSecurity"]) { [Environment.preferences setScreenSecurity:self.toggle.isOn]; } @@ -40,9 +38,9 @@ #pragma mark - Detail Label --(void)updateImageQualityLabel -{ - /* this is currently unused, thus unlocalized. code should probably be excised as this will never be part of design */ +- (void)updateImageQualityLabel { + /* this is currently unused, thus unlocalized. code should probably be excised as this will never be part of design + */ switch ([Environment.preferences imageUploadQuality]) { case TSImageQualityUncropped: self.detailLabel.text = @"Full"; @@ -57,7 +55,9 @@ self.detailLabel.text = @"Low"; break; default: - DDLogWarn(@"Unknown Image Quality setting : %lu <%s>", [Environment.preferences imageUploadQuality], __PRETTY_FUNCTION__); + DDLogWarn(@"Unknown Image Quality setting : %lu <%s>", + [Environment.preferences imageUploadQuality], + __PRETTY_FUNCTION__); break; } } diff --git a/Signal/src/view controllers/SettingsTableViewController.h b/Signal/src/view controllers/SettingsTableViewController.h index b0d84d233..0ba9c49b4 100644 --- a/Signal/src/view controllers/SettingsTableViewController.h +++ b/Signal/src/view controllers/SettingsTableViewController.h @@ -21,6 +21,6 @@ @property IBOutlet UILabel *settingsAboutTitle; @property IBOutlet UIButton *destroyAccountButton; --(IBAction)unregisterUser:(id)sender; +- (IBAction)unregisterUser:(id)sender; - (IBAction)unwindToUserCancelledChangeNumber:(UIStoryboardSegue *)segue; @end diff --git a/Signal/src/view controllers/SettingsTableViewController.m b/Signal/src/view controllers/SettingsTableViewController.m index dd50a0058..f2a5798f2 100644 --- a/Signal/src/view controllers/SettingsTableViewController.m +++ b/Signal/src/view controllers/SettingsTableViewController.m @@ -8,9 +8,9 @@ #import "SettingsTableViewController.h" -#import "TSAccountManager.h" #import "Environment.h" #import "PreferencesUtil.h" +#import "TSAccountManager.h" #import "UIUtil.h" #import "RPServerRequestsManager.h" @@ -19,24 +19,24 @@ #import "ContactsManager.h" -#import "PrivacySettingsTableViewController.h" -#import "AdvancedSettingsTableViewController.h" #import "AboutTableViewController.h" -#import "PushManager.h" +#import "AdvancedSettingsTableViewController.h" #import "NotificationSettingsViewController.h" +#import "PrivacySettingsTableViewController.h" +#import "PushManager.h" -#define kProfileCellHeight 87.0f -#define kStandardCellHeight 44.0f +#define kProfileCellHeight 87.0f +#define kStandardCellHeight 44.0f -#define kNumberOfSections 4 +#define kNumberOfSections 4 #define kRegisteredNumberRow 0 -#define kPrivacyRow 0 -#define kNotificationRow 1 -#define kAdvancedRow 2 -#define kAboutRow 3 -#define kNetworkRow 0 -#define kUnregisterRow 0 +#define kPrivacyRow 0 +#define kNotificationRow 1 +#define kAdvancedRow 2 +#define kAboutRow 3 +#define kNetworkRow 0 +#define kUnregisterRow 0 typedef enum { kRegisteredRows = 1, @@ -46,10 +46,10 @@ typedef enum { } kRowsForSection; typedef enum { - kRegisteredNumberSection=0, - kNetworkStatusSection=1, - kGeneralSection=2, - kUnregisterSection=3, + kRegisteredNumberSection = 0, + kNetworkStatusSection = 1, + kGeneralSection = 2, + kUnregisterSection = 3, } kSection; @interface SettingsTableViewController () @@ -63,33 +63,35 @@ typedef enum { [self.navigationItem setHidesBackButton:YES]; [self.navigationController.navigationBar setTranslucent:NO]; - - self.tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero]; - self.registeredNumber.text = [PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:[TSAccountManager registeredNumber]]; + + self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; + self.registeredNumber.text = + [PhoneNumber bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:[TSAccountManager localNumber]]; [self findAndSetRegisteredName]; - + [self initializeObserver]; [TSSocketManager sendNotification]; - - self.title = NSLocalizedString(@"SETTINGS_NAV_BAR_TITLE",@""); - _networkStatusHeader.text = NSLocalizedString(@"NETWORK_STATUS_HEADER",@""); - _settingsPrivacyTitle.text = NSLocalizedString(@"SETTINGS_PRIVACY_TITLE",@""); - _settingsAdvancedTitle.text = NSLocalizedString(@"SETTINGS_ADVANCED_TITLE",@""); - _settingsAboutTitle.text = NSLocalizedString(@"SETTINGS_ABOUT",@""); + + self.title = NSLocalizedString(@"SETTINGS_NAV_BAR_TITLE", @""); + _networkStatusHeader.text = NSLocalizedString(@"NETWORK_STATUS_HEADER", @""); + _settingsPrivacyTitle.text = NSLocalizedString(@"SETTINGS_PRIVACY_TITLE", @""); + _settingsAdvancedTitle.text = NSLocalizedString(@"SETTINGS_ADVANCED_TITLE", @""); + _settingsAboutTitle.text = NSLocalizedString(@"SETTINGS_ABOUT", @""); _settingsNotifications.text = NSLocalizedString(@"SETTINGS_NOTIFICATIONS", nil); - [_destroyAccountButton setTitle:NSLocalizedString(@"SETTINGS_DELETE_ACCOUNT_BUTTON", @"") forState:UIControlStateNormal]; + [_destroyAccountButton setTitle:NSLocalizedString(@"SETTINGS_DELETE_ACCOUNT_BUTTON", @"") + forState:UIControlStateNormal]; } --(void)dealloc { +- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self name:SocketOpenedNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:SocketClosedNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:SocketConnectingNotification object:nil]; } --(void) findAndSetRegisteredName { - NSString *name = NSLocalizedString(@"REGISTERED_NUMBER_TEXT", @""); - PhoneNumber* myNumber = [PhoneNumber phoneNumberFromE164:[TSAccountManager registeredNumber]]; - Contact *me = [[Environment.getCurrent contactsManager] latestContactForPhoneNumber:myNumber]; +- (void)findAndSetRegisteredName { + NSString *name = NSLocalizedString(@"REGISTERED_NUMBER_TEXT", @""); + PhoneNumber *myNumber = [PhoneNumber phoneNumberFromE164:[TSAccountManager localNumber]]; + Contact *me = [[Environment.getCurrent contactsManager] latestContactForPhoneNumber:myNumber]; self.registeredName.text = [me fullName] ? [me fullName] : name; } #pragma mark - Table view data source @@ -99,7 +101,6 @@ typedef enum { } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - switch (section) { case kRegisteredNumberSection: return kRegisteredRows; @@ -115,39 +116,33 @@ typedef enum { } --(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; - + switch (indexPath.section) { - case kGeneralSection: - { + case kGeneralSection: { switch (indexPath.row) { - case kPrivacyRow: - { - PrivacySettingsTableViewController *vc = [[PrivacySettingsTableViewController alloc]init]; + case kPrivacyRow: { + PrivacySettingsTableViewController *vc = [[PrivacySettingsTableViewController alloc] init]; NSAssert(self.navigationController != nil, @"Navigation controller must not be nil"); NSAssert(vc != nil, @"Privacy Settings View Controller must not be nil"); [self.navigationController pushViewController:vc animated:YES]; break; } - case kNotificationRow: - { + case kNotificationRow: { NotificationSettingsViewController *vc = [[NotificationSettingsViewController alloc] init]; [self.navigationController pushViewController:vc animated:YES]; break; } - case kAdvancedRow: - { - AdvancedSettingsTableViewController *vc = [[AdvancedSettingsTableViewController alloc]init]; + case kAdvancedRow: { + AdvancedSettingsTableViewController *vc = [[AdvancedSettingsTableViewController alloc] init]; NSAssert(self.navigationController != nil, @"Navigation controller must not be nil"); NSAssert(vc != nil, @"Advanced Settings View Controller must not be nil"); [self.navigationController pushViewController:vc animated:YES]; break; } - case kAboutRow: - { - AboutTableViewController * vc = [[AboutTableViewController alloc]init]; + case kAboutRow: { + AboutTableViewController *vc = [[AboutTableViewController alloc] init]; NSAssert(self.navigationController != nil, @"Navigation controller must not be nil"); NSAssert(vc != nil, @"About View Controller must not be nil"); [self.navigationController pushViewController:vc animated:YES]; @@ -156,89 +151,95 @@ typedef enum { default: break; } - + break; } - - case kNetworkStatusSection: - { + + case kNetworkStatusSection: { break; } - - case kUnregisterSection: - { + + case kUnregisterSection: { [self unregisterUser:nil]; break; } - + default: break; } } --(IBAction)unregisterUser:(id)sender { +- (IBAction)unregisterUser:(id)sender { + UIAlertController *alertController = + [UIAlertController alertControllerWithTitle:NSLocalizedString(@"CONFIRM_ACCOUNT_DESTRUCTION_TITLE", @"") + message:NSLocalizedString(@"CONFIRM_ACCOUNT_DESTRUCTION_TEXT", @"") + preferredStyle:UIAlertControllerStyleAlert]; + [alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"PROCEED_BUTTON", @"") + style:UIAlertActionStyleDestructive + handler:^(UIAlertAction *action) { + [self proceedToUnregistration]; + }]]; + [alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") + style:UIAlertActionStyleCancel + handler:nil]]; - UIAlertController *alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"CONFIRM_ACCOUNT_DESTRUCTION_TITLE", @"") message:NSLocalizedString(@"CONFIRM_ACCOUNT_DESTRUCTION_TEXT", @"") preferredStyle:UIAlertControllerStyleAlert]; - [alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"PROCEED_BUTTON", @"") style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) { - [self proceedToUnregistration]; - }]]; - [alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") style:UIAlertActionStyleCancel handler:nil]]; - [self presentViewController:alertController animated:YES completion:nil]; } -- (void)proceedToUnregistration{ +- (void)proceedToUnregistration { [TSAccountManager unregisterTextSecureWithSuccess:^{ - [PushManager.sharedManager requestPushTokenWithSuccess:^(NSData* pushToken, NSData *voipToken){ - [[RPServerRequestsManager sharedInstance]performRequest:[RPAPICall unregisterWithPushToken:pushToken] success:^(NSURLSessionDataTask *task, id responseObject) { - [Environment resetAppData]; - exit(0); - } failure:^(NSURLSessionDataTask *task, NSError *error) { - SignalAlertView(NSLocalizedString(@"UNREGISTER_REDPHONE_FAIL", @""), @""); - }]; - } failure:^(NSError *error) { - SignalAlertView(NSLocalizedString(@"UNREGISTER_REDPHONE_FAIL", @""), @""); + [Environment resetAppData]; + } + failure:^(NSError *error) { + SignalAlertView(NSLocalizedString(@"UNREGISTER_SIGNAL_FAIL", @""), @""); }]; - } failure:^(NSError *error) { - SignalAlertView(NSLocalizedString(@"UNREGISTER_TEXTSECURE_FAIL", @""), @""); - }]; } --(void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath -{ +- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == kNetworkStatusSection) { - UIAlertView * info = [[UIAlertView alloc]initWithTitle:NSLocalizedString(@"NETWORK_STATUS_HEADER", @"") message:NSLocalizedString(@"NETWORK_STATUS_TEXT",@"") delegate:self cancelButtonTitle:NSLocalizedString(@"OK",@"") otherButtonTitles: nil]; + UIAlertView *info = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"NETWORK_STATUS_HEADER", @"") + message:NSLocalizedString(@"NETWORK_STATUS_TEXT", @"") + delegate:self + cancelButtonTitle:NSLocalizedString(@"OK", @"") + otherButtonTitles:nil]; [info show]; } } #pragma mark - Socket Status Notifications --(void)initializeObserver -{ - [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(socketDidOpen) name:SocketOpenedNotification object:nil]; - [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(socketDidClose) name:SocketClosedNotification object:nil]; - [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(socketIsConnecting) name:SocketConnectingNotification object:nil]; +- (void)initializeObserver { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(socketDidOpen) + name:SocketOpenedNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(socketDidClose) + name:SocketClosedNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(socketIsConnecting) + name:SocketConnectingNotification + object:nil]; } --(void)socketDidOpen { - self.networkStatusLabel.text = NSLocalizedString(@"NETWORK_STATUS_CONNECTED", @""); +- (void)socketDidOpen { + self.networkStatusLabel.text = NSLocalizedString(@"NETWORK_STATUS_CONNECTED", @""); self.networkStatusLabel.textColor = [UIColor ows_greenColor]; } --(void)socketDidClose { - self.networkStatusLabel.text = NSLocalizedString(@"NETWORK_STATUS_OFFLINE", @""); +- (void)socketDidClose { + self.networkStatusLabel.text = NSLocalizedString(@"NETWORK_STATUS_OFFLINE", @""); self.networkStatusLabel.textColor = [UIColor ows_redColor]; } --(void)socketIsConnecting { - self.networkStatusLabel.text = NSLocalizedString(@"NETWORK_STATUS_CONNECTING", @""); +- (void)socketIsConnecting { + self.networkStatusLabel.text = NSLocalizedString(@"NETWORK_STATUS_CONNECTING", @""); self.networkStatusLabel.textColor = [UIColor ows_yellowColor]; } - (IBAction)unwindToUserCancelledChangeNumber:(UIStoryboardSegue *)segue { - } @end diff --git a/Signal/src/view controllers/ShowGroupMembersViewController.h b/Signal/src/view controllers/ShowGroupMembersViewController.h index 12737d4ba..43c315461 100644 --- a/Signal/src/view controllers/ShowGroupMembersViewController.h +++ b/Signal/src/view controllers/ShowGroupMembersViewController.h @@ -7,11 +7,15 @@ // #import -#import "TSGroupThread.h" #import "TSGroupModel.h" +#import "TSGroupThread.h" -@interface ShowGroupMembersViewController : UITableViewController +@interface ShowGroupMembersViewController : UITableViewController -- (void)configWithThread:(TSGroupThread*)thread; +- (void)configWithThread:(TSGroupThread *)thread; @end diff --git a/Signal/src/view controllers/ShowGroupMembersViewController.m b/Signal/src/view controllers/ShowGroupMembersViewController.m index 8f27ffe65..3b2ac25ee 100644 --- a/Signal/src/view controllers/ShowGroupMembersViewController.m +++ b/Signal/src/view controllers/ShowGroupMembersViewController.m @@ -12,25 +12,25 @@ #import "SignalsViewController.h" #import "ContactsManager.h" -#import "GroupContactsResult.h" #import "Environment.h" +#import "GroupContactsResult.h" #import "UIUtil.h" #import -static NSString* const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue"; +static NSString *const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue"; @interface ShowGroupMembersViewController () @property GroupContactsResult *groupContacts; -@property TSGroupThread* thread; +@property TSGroupThread *thread; @end @implementation ShowGroupMembersViewController -- (void)configWithThread:(TSGroupThread *)gThread{ +- (void)configWithThread:(TSGroupThread *)gThread { _thread = gThread; } @@ -39,15 +39,20 @@ static NSString* const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue" [self.navigationController.navigationBar setTranslucent:NO]; self.title = _thread.groupModel.groupName; - + [self initializeTableView]; - - self.groupContacts = [[GroupContactsResult alloc] initWithMembersId:self.thread.groupModel.groupMemberIds without:nil]; - - [[Environment.getCurrent contactsManager].getObservableContacts watchLatestValue:^(id latestValue) { - self.groupContacts = [[GroupContactsResult alloc] initWithMembersId:self.thread.groupModel.groupMemberIds without:nil]; - [self.tableView reloadData]; - } onThread:[NSThread mainThread] untilCancelled:nil]; + + self.groupContacts = + [[GroupContactsResult alloc] initWithMembersId:self.thread.groupModel.groupMemberIds without:nil]; + + [[Environment.getCurrent contactsManager] + .getObservableContacts watchLatestValue:^(id latestValue) { + self.groupContacts = + [[GroupContactsResult alloc] initWithMembersId:self.thread.groupModel.groupMemberIds without:nil]; + [self.tableView reloadData]; + } + onThread:[NSThread mainThread] + untilCancelled:nil]; } - (void)didReceiveMemoryWarning { @@ -57,9 +62,8 @@ static NSString* const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue" #pragma mark - Initializers --(void)initializeTableView -{ - self.tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero]; +- (void)initializeTableView { + self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; } #pragma mark - Actions @@ -71,103 +75,116 @@ static NSString* const kUnwindToMessagesViewSegue = @"UnwindToMessagesViewSegue" } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return (NSInteger)[self.groupContacts numberOfMembers]+1; + return (NSInteger)[self.groupContacts numberOfMembers] + 1; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SearchCell"]; - + if (cell == nil) { - - cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: indexPath.row == 0 ? @"HeaderCell" : @"GroupSearchCell"]; + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault + reuseIdentifier:indexPath.row == 0 ? @"HeaderCell" : @"GroupSearchCell"]; } if (indexPath.row > 0) { - NSIndexPath *relativeIndexPath = [NSIndexPath indexPathForRow:indexPath.row-1 inSection:indexPath.section]; + NSIndexPath *relativeIndexPath = [NSIndexPath indexPathForRow:indexPath.row - 1 inSection:indexPath.section]; if ([self.groupContacts isContactAtIndexPath:relativeIndexPath]) { - Contact* contact = [self contactForIndexPath:relativeIndexPath]; + Contact *contact = [self contactForIndexPath:relativeIndexPath]; cell.textLabel.attributedText = [self attributedStringForContact:contact inCell:cell]; - } else{ + } else { cell.textLabel.text = [self.groupContacts identifierForIndexPath:relativeIndexPath]; } } else { - cell.textLabel.text = @"Group Members:"; + cell.textLabel.text = @"Group Members:"; cell.textLabel.textColor = [UIColor lightGrayColor]; - cell.selectionStyle = UITableViewCellSelectionStyleNone; + cell.selectionStyle = UITableViewCellSelectionStyleNone; } - + tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; - + return cell; } --(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ - NSIndexPath *relativeIndexPath = [NSIndexPath indexPathForRow:indexPath.row-1 inSection:indexPath.section]; - - if(indexPath.row >0 && [self.groupContacts isContactAtIndexPath:relativeIndexPath]) { +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + NSIndexPath *relativeIndexPath = [NSIndexPath indexPathForRow:indexPath.row - 1 inSection:indexPath.section]; + + if (indexPath.row > 0 && [self.groupContacts isContactAtIndexPath:relativeIndexPath]) { ABPersonViewController *view = [[ABPersonViewController alloc] init]; - - Contact *contact = [self.groupContacts contactForIndexPath:relativeIndexPath]; + + Contact *contact = [self.groupContacts contactForIndexPath:relativeIndexPath]; ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, nil); - view.displayedPerson = ABAddressBookGetPersonWithRecordID(addressBookRef, contact.recordID); // Assume person is already defined. - view.allowsActions = NO; - view.allowsEditing = YES; - + view.displayedPerson = + ABAddressBookGetPersonWithRecordID(addressBookRef, contact.recordID); // Assume person is already defined. + view.allowsActions = NO; + view.allowsEditing = YES; + [self.navigationController pushViewController:view animated:YES]; } else { ABUnknownPersonViewController *view = [[ABUnknownPersonViewController alloc] init]; - + ABRecordRef aContact = ABPersonCreate(); - CFErrorRef anError = NULL; - + CFErrorRef anError = NULL; + ABMultiValueRef phone = ABMultiValueCreateMutable(kABMultiStringPropertyType); - ABMultiValueAddValueAndLabel(phone, (__bridge CFTypeRef)[self.tableView cellForRowAtIndexPath:indexPath].textLabel.text, kABPersonPhoneMainLabel, NULL); - + ABMultiValueAddValueAndLabel( + phone, + (__bridge CFTypeRef)[self.tableView cellForRowAtIndexPath:indexPath].textLabel.text, + kABPersonPhoneMainLabel, + NULL); + ABRecordSetValue(aContact, kABPersonPhoneProperty, phone, &anError); CFRelease(phone); - + if (!anError && aContact) { - view.displayedPerson = aContact; // Assume person is already defined. + view.displayedPerson = aContact; // Assume person is already defined. view.allowsAddingToAddressBook = YES; [self.navigationController pushViewController:view animated:YES]; } } - + [tableView deselectRowAtIndexPath:indexPath animated:YES]; } --(Contact*)contactForIndexPath:(NSIndexPath*)indexPath -{ +- (Contact *)contactForIndexPath:(NSIndexPath *)indexPath { Contact *contact = [self.groupContacts contactForIndexPath:indexPath]; return contact; } #pragma mark - Cell Utility -- (NSAttributedString *)attributedStringForContact:(Contact *)contact inCell:(UITableViewCell*)cell { - NSMutableAttributedString *fullNameAttributedString = [[NSMutableAttributedString alloc] initWithString:contact.fullName]; - +- (NSAttributedString *)attributedStringForContact:(Contact *)contact inCell:(UITableViewCell *)cell { + NSMutableAttributedString *fullNameAttributedString = + [[NSMutableAttributedString alloc] initWithString:contact.fullName]; + UIFont *firstNameFont; UIFont *lastNameFont; - + if (ABPersonGetSortOrdering() == kABPersonCompositeNameFormatFirstNameFirst) { firstNameFont = [UIFont ows_mediumFontWithSize:cell.textLabel.font.pointSize]; lastNameFont = [UIFont ows_regularFontWithSize:cell.textLabel.font.pointSize]; - } else{ + } else { firstNameFont = [UIFont ows_regularFontWithSize:cell.textLabel.font.pointSize]; lastNameFont = [UIFont ows_mediumFontWithSize:cell.textLabel.font.pointSize]; } - [fullNameAttributedString addAttribute:NSFontAttributeName value:firstNameFont range:NSMakeRange(0, contact.firstName.length)]; - [fullNameAttributedString addAttribute:NSFontAttributeName value:lastNameFont range:NSMakeRange(contact.firstName.length + 1, contact.lastName.length)]; - - [fullNameAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0, contact.fullName.length)]; - + [fullNameAttributedString addAttribute:NSFontAttributeName + value:firstNameFont + range:NSMakeRange(0, contact.firstName.length)]; + [fullNameAttributedString addAttribute:NSFontAttributeName + value:lastNameFont + range:NSMakeRange(contact.firstName.length + 1, contact.lastName.length)]; + + [fullNameAttributedString addAttribute:NSForegroundColorAttributeName + value:[UIColor blackColor] + range:NSMakeRange(0, contact.fullName.length)]; + if (ABPersonGetSortOrdering() == kABPersonCompositeNameFormatFirstNameFirst) { - [fullNameAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor ows_darkGrayColor] range:NSMakeRange(contact.firstName.length + 1, contact.lastName.length)]; - } - else { - [fullNameAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor ows_darkGrayColor] range:NSMakeRange(0, contact.firstName.length)]; + [fullNameAttributedString addAttribute:NSForegroundColorAttributeName + value:[UIColor ows_darkGrayColor] + range:NSMakeRange(contact.firstName.length + 1, contact.lastName.length)]; + } else { + [fullNameAttributedString addAttribute:NSForegroundColorAttributeName + value:[UIColor ows_darkGrayColor] + range:NSMakeRange(0, contact.firstName.length)]; } return fullNameAttributedString; } diff --git a/Signal/src/view controllers/Signal-Bridging-Header.h b/Signal/src/view controllers/Signal-Bridging-Header.h new file mode 100644 index 000000000..1b2cb5d6d --- /dev/null +++ b/Signal/src/view controllers/Signal-Bridging-Header.h @@ -0,0 +1,4 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + diff --git a/Signal/src/view controllers/SignalsNavigationController.h b/Signal/src/view controllers/SignalsNavigationController.h index b6524d77a..8d44dbf58 100644 --- a/Signal/src/view controllers/SignalsNavigationController.h +++ b/Signal/src/view controllers/SignalsNavigationController.h @@ -7,9 +7,9 @@ // #import -#import "TSSocketManager.h" #import "APNavigationController.h" +#import "TSSocketManager.h" @interface SignalsNavigationController : APNavigationController -@property (nonatomic, strong) UIProgressView* socketStatusView; +@property (nonatomic, strong) UIProgressView *socketStatusView; @property (nonatomic, strong) NSTimer *updateStatusTimer; @end diff --git a/Signal/src/view controllers/SignalsNavigationController.m b/Signal/src/view controllers/SignalsNavigationController.m index a11cef458..b4bede9a5 100644 --- a/Signal/src/view controllers/SignalsNavigationController.m +++ b/Signal/src/view controllers/SignalsNavigationController.m @@ -30,68 +30,74 @@ static double const STALLED_PROGRESS = 0.9; // Dispose of any resources that can be recreated. } --(void)initializeSocketStatusBar -{ +- (void)initializeSocketStatusBar { if (!_socketStatusView) { - _socketStatusView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleDefault]; + _socketStatusView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault]; } - - CGRect bar = self.navigationBar.frame; - _socketStatusView.frame = CGRectMake(0, bar.size.height-1.0f, self.view.frame.size.width, 1.0f); - _socketStatusView.progress = 0.0f; + + CGRect bar = self.navigationBar.frame; + _socketStatusView.frame = CGRectMake(0, bar.size.height - 1.0f, self.view.frame.size.width, 1.0f); + _socketStatusView.progress = 0.0f; _socketStatusView.progressTintColor = [UIColor ows_fadedBlueColor]; - + if (![_socketStatusView superview]) { [self.navigationBar addSubview:_socketStatusView]; } } --(void)dealloc -{ -[[NSNotificationCenter defaultCenter] removeObserver:self]; +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; } #pragma mark - Socket Status Notifications --(void)initializeObserver -{ - [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(socketDidOpen) name:SocketOpenedNotification object:nil]; - [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(socketDidClose) name:SocketClosedNotification object:nil]; - [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(socketIsConnecting) name:SocketConnectingNotification object:nil]; +- (void)initializeObserver { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(socketDidOpen) + name:SocketOpenedNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(socketDidClose) + name:SocketClosedNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(socketIsConnecting) + name:SocketConnectingNotification + object:nil]; } --(void)socketDidOpen -{ +- (void)socketDidOpen { [_updateStatusTimer invalidate]; - for(UIView* view in self.navigationBar.subviews) { - if([view isKindOfClass:[UIProgressView class]]) { + for (UIView *view in self.navigationBar.subviews) { + if ([view isKindOfClass:[UIProgressView class]]) { [view removeFromSuperview]; _socketStatusView = nil; } } } --(void)socketDidClose -{ - if(_socketStatusView==nil) { +- (void)socketDidClose { + if (_socketStatusView == nil) { [self initializeSocketStatusBar]; - _updateStatusTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateSocketConnecting) userInfo:nil repeats:YES]; - - } - else if(_socketStatusView.progress >= STALLED_PROGRESS) { - [ _updateStatusTimer invalidate]; + _updateStatusTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 + target:self + selector:@selector(updateSocketConnecting) + userInfo:nil + repeats:YES]; + + } else if (_socketStatusView.progress >= STALLED_PROGRESS) { + [_updateStatusTimer invalidate]; } } --(void ) updateSocketConnecting { - double progress = _socketStatusView.progress + 0.05; +- (void)updateSocketConnecting { + double progress = _socketStatusView.progress + 0.05; _socketStatusView.progress = (float)MIN(progress, STALLED_PROGRESS); } --(void)socketIsConnecting{ +- (void)socketIsConnecting { // Nothing to see here currently } - @end diff --git a/Signal/src/view controllers/TSAnimatedAdapter.h b/Signal/src/view controllers/TSAnimatedAdapter.h index bd8c7c0e7..1cd5fba7c 100644 --- a/Signal/src/view controllers/TSAnimatedAdapter.h +++ b/Signal/src/view controllers/TSAnimatedAdapter.h @@ -6,13 +6,13 @@ // Copyright (c) 2015 Open Whisper Systems. All rights reserved. // +#import #import #import "TSAttachmentStream.h" -#import @interface TSAnimatedAdapter : JSQMediaItem -- (instancetype)initWithAttachment:(TSAttachmentStream*)attachment; +- (instancetype)initWithAttachment:(TSAttachmentStream *)attachment; - (BOOL)isImage; - (BOOL)isAudio; diff --git a/Signal/src/view controllers/TSAnimatedAdapter.m b/Signal/src/view controllers/TSAnimatedAdapter.m index 3c8ce8029..68d885176 100644 --- a/Signal/src/view controllers/TSAnimatedAdapter.m +++ b/Signal/src/view controllers/TSAnimatedAdapter.m @@ -8,9 +8,9 @@ #import "TSAnimatedAdapter.h" -#import "UIDevice+TSHardwareVersion.h" -#import "JSQMessagesMediaViewBubbleImageMasker.h" #import "FLAnimatedImage.h" +#import "JSQMessagesMediaViewBubbleImageMasker.h" +#import "UIDevice+TSHardwareVersion.h" @interface TSAnimatedAdapter () @@ -37,107 +37,95 @@ return self; } -- (void)dealloc -{ +- (void)dealloc { _cachedImageView = nil; - _attachment = nil; - _attachmentId = nil; - _image = nil; - _fileData = nil; + _attachment = nil; + _attachmentId = nil; + _image = nil; + _fileData = nil; } -- (void)clearCachedMediaViews -{ +- (void)clearCachedMediaViews { [super clearCachedMediaViews]; _cachedImageView = nil; } -- (void)setAppliesMediaViewMaskAsOutgoing:(BOOL)appliesMediaViewMaskAsOutgoing -{ +- (void)setAppliesMediaViewMaskAsOutgoing:(BOOL)appliesMediaViewMaskAsOutgoing { [super setAppliesMediaViewMaskAsOutgoing:appliesMediaViewMaskAsOutgoing]; _cachedImageView = nil; } #pragma mark - JSQMessageMediaData protocol -- (UIView *)mediaView -{ +- (UIView *)mediaView { if (self.cachedImageView == nil) { // Use Flipboard FLAnimatedImage library to display gifs - FLAnimatedImage *animatedGif = [FLAnimatedImage animatedImageWithGIFData:self.fileData]; + FLAnimatedImage *animatedGif = [FLAnimatedImage animatedImageWithGIFData:self.fileData]; FLAnimatedImageView *imageView = [[FLAnimatedImageView alloc] init]; - imageView.animatedImage = animatedGif; - CGSize size = [self mediaViewDisplaySize]; - imageView.frame = CGRectMake(0.0, 0.0, size.width, size.height); - imageView.contentMode = UIViewContentModeScaleAspectFill; - imageView.clipsToBounds = YES; - [JSQMessagesMediaViewBubbleImageMasker applyBubbleImageMaskToMediaView:imageView isOutgoing:self.appliesMediaViewMaskAsOutgoing]; + imageView.animatedImage = animatedGif; + CGSize size = [self mediaViewDisplaySize]; + imageView.frame = CGRectMake(0.0, 0.0, size.width, size.height); + imageView.contentMode = UIViewContentModeScaleAspectFill; + imageView.clipsToBounds = YES; + [JSQMessagesMediaViewBubbleImageMasker applyBubbleImageMaskToMediaView:imageView + isOutgoing:self.appliesMediaViewMaskAsOutgoing]; self.cachedImageView = imageView; } return self.cachedImageView; } -- (CGSize)mediaViewDisplaySize -{ +- (CGSize)mediaViewDisplaySize { return [self getBubbleSizeForImage:self.image]; } --(BOOL)isImage { +- (BOOL)isImage { return YES; } --(BOOL) isAudio { +- (BOOL)isAudio { return NO; } --(BOOL) isVideo { +- (BOOL)isVideo { return NO; } #pragma mark - Utility --(CGSize)getBubbleSizeForImage:(UIImage*)image -{ - CGFloat aspectRatio = image.size.height / image.size.width ; +- (CGSize)getBubbleSizeForImage:(UIImage *)image { + CGFloat aspectRatio = image.size.height / image.size.width; - if ([[UIDevice currentDevice] isiPhoneVersionSixOrMore]) - { + if ([[UIDevice currentDevice] isiPhoneVersionSixOrMore]) { return [self getLargeSizeForAspectRatio:aspectRatio]; } else { return [self getSmallSizeForAspectRatio:aspectRatio]; } } --(CGSize)getLargeSizeForAspectRatio:(CGFloat)ratio -{ +- (CGSize)getLargeSizeForAspectRatio:(CGFloat)ratio { return ratio > 1.0f ? [self largePortraitSize] : [self largeLandscapeSize]; } --(CGSize)getSmallSizeForAspectRatio:(CGFloat)ratio -{ +- (CGSize)getSmallSizeForAspectRatio:(CGFloat)ratio { return ratio > 1.0f ? [self smallPortraitSize] : [self smallLandscapeSize]; } -- (CGSize)largePortraitSize -{ +- (CGSize)largePortraitSize { return CGSizeMake(220.0f, 310.0f); } -- (CGSize)smallPortraitSize -{ +- (CGSize)smallPortraitSize { return CGSizeMake(150.0f, 210.0f); } -- (CGSize)largeLandscapeSize -{ +- (CGSize)largeLandscapeSize { return CGSizeMake(310.0f, 220.0f); } -- (CGSize)smallLandscapeSize -{ +- (CGSize)smallLandscapeSize { return CGSizeMake(210.0f, 150.0f); } diff --git a/Signal/src/view controllers/TSContentAdapters.h b/Signal/src/view controllers/TSContentAdapters.h new file mode 100644 index 000000000..ca82aced0 --- /dev/null +++ b/Signal/src/view controllers/TSContentAdapters.h @@ -0,0 +1,17 @@ +// +// TSContentAdapters.h +// Signal +// +// Created by Frederic Jacobs on 05/12/15. +// Copyright © 2015 Open Whisper Systems. All rights reserved. +// + +#ifndef TSContentAdapters_h +#define TSContentAdapters_h + +#import "TSAnimatedAdapter.h" +#import "TSMessageAdapter.h" +#import "TSPhotoAdapter.h" +#import "TSVideoAttachmentAdapter.h" + +#endif /* TSContentAdapters_h */ diff --git a/Signal/src/view controllers/TSGroupModel.h b/Signal/src/view controllers/TSGroupModel.h deleted file mode 100644 index 4ce610392..000000000 --- a/Signal/src/view controllers/TSGroupModel.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// GroupModel.h -// Signal -// -// Created by Frederic Jacobs. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import -#import "TSYapDatabaseObject.h" - -#import "TSPhotoAdapter.h" - - -@interface TSGroupModel : TSYapDatabaseObject - -@property (nonatomic, strong) NSMutableArray *groupMemberIds; -@property (nonatomic, strong) UIImage *groupImage; -@property (nonatomic, strong) NSString *associatedAttachmentId; -@property (nonatomic, strong) NSString *groupName; -@property (nonatomic, strong) NSData* groupId; - --(instancetype)initWithTitle:(NSString*)title memberIds:(NSMutableArray*)memberIds image:(UIImage*)image groupId:(NSData *)groupId associatedAttachmentId:(NSString*)attachmentId; -- (BOOL)isEqual:(id)other; -- (BOOL)isEqualToGroupModel:(TSGroupModel *)model; -- (NSString*) getInfoStringAboutUpdateTo:(TSGroupModel*)model; - -@end diff --git a/Signal/src/view controllers/TSGroupModel.m b/Signal/src/view controllers/TSGroupModel.m deleted file mode 100644 index 157e8f292..000000000 --- a/Signal/src/view controllers/TSGroupModel.m +++ /dev/null @@ -1,90 +0,0 @@ -// -// GroupModel.m -// Signal -// -// Created by Frederic Jacobs on 13/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSGroupModel.h" - -NSString * const TSAttachementGroupAvatarFileRelationshipEdge = @"TSAttachementGroupAvatarFileEdge"; - -@implementation TSGroupModel - --(instancetype)initWithTitle:(NSString*)title memberIds:(NSMutableArray*)memberIds image:(UIImage*)image groupId:(NSData *)groupId associatedAttachmentId:(NSString*)attachmentId { - _groupName = title; - _groupMemberIds = [memberIds copy]; - _groupImage = image; - _associatedAttachmentId = attachmentId; - _groupId = groupId; - - return self; -} - -- (BOOL)isEqual:(id)other { - if (other == self) { - return YES; - } - if (!other || ![other isKindOfClass:[self class]]) { - return NO; - } - return [self isEqualToGroupModel:other]; -} - -- (BOOL)isEqualToGroupModel:(TSGroupModel *)other { - if (self == other) - return YES; - if(![_groupId isEqualToData:other.groupId] ) { - return NO; - } - if (![_groupName isEqual:other.groupName]) { - return NO; - } - if( !(_groupImage!=nil && other.groupImage!=nil && [UIImagePNGRepresentation(_groupImage) isEqualToData:UIImagePNGRepresentation(other.groupImage)])) { - return NO; - } - NSMutableArray* compareMyGroupMemberIds = [NSMutableArray arrayWithArray:_groupMemberIds]; - [compareMyGroupMemberIds removeObjectsInArray:other.groupMemberIds]; - if([compareMyGroupMemberIds count] > 0 ) { - return NO; - } - return YES; -} - -- (NSString*) getInfoStringAboutUpdateTo:(TSGroupModel*)newModel { - NSString* updatedGroupInfoString = @""; - if (self == newModel) { - return NSLocalizedString(@"GROUP_UPDATED", @""); - } - if (![_groupName isEqual:newModel.groupName]) { - updatedGroupInfoString = [updatedGroupInfoString stringByAppendingString:[NSString stringWithFormat:NSLocalizedString(@"GROUP_TITLE_CHANGED", @""),newModel.groupName]]; - } - if(_groupImage!=nil && newModel.groupImage!=nil && !([UIImagePNGRepresentation(_groupImage) isEqualToData:UIImagePNGRepresentation(newModel.groupImage)])) { - updatedGroupInfoString = [updatedGroupInfoString stringByAppendingString:NSLocalizedString(@"GROUP_AVATAR_CHANGED", @"")]; - } - if([updatedGroupInfoString length]==0) { - updatedGroupInfoString = NSLocalizedString(@"GROUP_UPDATED", @""); - } - NSSet* oldMembers = [NSSet setWithArray:_groupMemberIds]; - NSSet* newMembers = [NSSet setWithArray:newModel.groupMemberIds]; - - NSMutableSet *membersWhoJoined = [NSMutableSet setWithSet:newMembers]; - [membersWhoJoined minusSet:oldMembers]; - - NSMutableSet *membersWhoLeft = [NSMutableSet setWithSet:oldMembers]; - [membersWhoLeft minusSet:newMembers]; - - - if([membersWhoLeft count] > 0 ) { - updatedGroupInfoString = [updatedGroupInfoString stringByAppendingString:[NSString stringWithFormat:NSLocalizedString(@"GROUP_MEMBER_LEFT", @""),[[membersWhoLeft allObjects] componentsJoinedByString:@", "]]]; - } - - if([membersWhoJoined count] > 0 ) { - updatedGroupInfoString = [updatedGroupInfoString stringByAppendingString:[NSString stringWithFormat:NSLocalizedString(@"GROUP_MEMBER_JOINED", @""),[[membersWhoJoined allObjects] componentsJoinedByString:@", "]]]; - } - - return updatedGroupInfoString; -} - -@end diff --git a/Signal/src/view controllers/TSMessageAdapter.h b/Signal/src/view controllers/TSMessageAdapter.h index 4297ef7c9..c1ccdefa0 100644 --- a/Signal/src/view controllers/TSMessageAdapter.h +++ b/Signal/src/view controllers/TSMessageAdapter.h @@ -9,15 +9,15 @@ #import #import -#import "TSMessageAdapter.h" #import "TSInteraction.h" +#import "TSMessageAdapter.h" #import "TSThread.h" #define ME_MESSAGE_IDENTIFIER @"Me"; @interface TSMessageAdapter : NSObject -+ (id)messageViewDataWithInteraction:(TSInteraction*)interaction inThread:(TSThread*)thread; ++ (id)messageViewDataWithInteraction:(TSInteraction *)interaction inThread:(TSThread *)thread; @property TSMessageAdapterType messageType; diff --git a/Signal/src/view controllers/TSMessageAdapter.m b/Signal/src/view controllers/TSMessageAdapter.m index 8346059a4..8a7c051c0 100644 --- a/Signal/src/view controllers/TSMessageAdapter.m +++ b/Signal/src/view controllers/TSMessageAdapter.m @@ -7,16 +7,13 @@ // #import "JSQCall.h" - -#import "TSMessageAdapter.h" -#import "TSIncomingMessage.h" -#import "TSOutgoingMessage.h" -#import "TSCall.h" -#import "TSInfoMessage.h" -#import "TSErrorMessage.h" #import "TSAttachmentPointer.h" -#import "TSVideoAttachmentAdapter.h" -#import "TSAnimatedAdapter.h" +#import "TSCall.h" +#import "TSContentAdapters.h" +#import "TSErrorMessage.h" +#import "TSIncomingMessage.h" +#import "TSInfoMessage.h" +#import "TSOutgoingMessage.h" @interface TSMessageAdapter () @@ -48,7 +45,7 @@ // --- -@property (nonatomic, copy) NSDate *messageDate; +@property (nonatomic, copy) NSDate *messageDate; @property (nonatomic, retain) NSString *messageBody; @property NSUInteger identifier; @@ -58,68 +55,69 @@ @implementation TSMessageAdapter -+ (id)messageViewDataWithInteraction:(TSInteraction*)interaction inThread:(TSThread*)thread{ - ++ (id)messageViewDataWithInteraction:(TSInteraction *)interaction inThread:(TSThread *)thread { TSMessageAdapter *adapter = [[TSMessageAdapter alloc] init]; adapter.messageDate = interaction.date; adapter.identifier = (NSUInteger)interaction.uniqueId; - + if ([thread isKindOfClass:[TSContactThread class]]) { - adapter.thread = (TSContactThread*)thread; + adapter.thread = (TSContactThread *)thread; if ([interaction isKindOfClass:[TSIncomingMessage class]]) { - NSString *contactId = ((TSContactThread*)thread).contactIdentifier; + NSString *contactId = ((TSContactThread *)thread).contactIdentifier; adapter.senderId = contactId; adapter.senderDisplayName = contactId; adapter.messageType = TSIncomingMessageAdapter; } else { - adapter.senderId = ME_MESSAGE_IDENTIFIER; + adapter.senderId = ME_MESSAGE_IDENTIFIER; adapter.senderDisplayName = NSLocalizedString(@"ME_STRING", @""); - adapter.messageType = TSOutgoingMessageAdapter; + adapter.messageType = TSOutgoingMessageAdapter; } - } else if ([thread isKindOfClass:[TSGroupThread class]]){ + } else if ([thread isKindOfClass:[TSGroupThread class]]) { if ([interaction isKindOfClass:[TSIncomingMessage class]]) { - TSIncomingMessage *message = (TSIncomingMessage*)interaction; - adapter.senderId = message.authorId; - adapter.senderDisplayName = message.authorId; - adapter.messageType = TSIncomingMessageAdapter; + TSIncomingMessage *message = (TSIncomingMessage *)interaction; + adapter.senderId = message.authorId; + adapter.senderDisplayName = message.authorId; + adapter.messageType = TSIncomingMessageAdapter; } else { - adapter.senderId = ME_MESSAGE_IDENTIFIER; - adapter.senderDisplayName = NSLocalizedString(@"ME_STRING", @""); - adapter.messageType = TSOutgoingMessageAdapter; + adapter.senderId = ME_MESSAGE_IDENTIFIER; + adapter.senderDisplayName = NSLocalizedString(@"ME_STRING", @""); + adapter.messageType = TSOutgoingMessageAdapter; } } - - if ([interaction isKindOfClass:[TSIncomingMessage class]] || [interaction isKindOfClass:[TSOutgoingMessage class]]) { - TSMessage *message = (TSMessage*)interaction; + + if ([interaction isKindOfClass:[TSIncomingMessage class]] || + [interaction isKindOfClass:[TSOutgoingMessage class]]) { + TSMessage *message = (TSMessage *)interaction; adapter.messageBody = message.body; - + if ([message.attachments count] > 0) { - for (NSString *attachmentID in message.attachments) { TSAttachment *attachment = [TSAttachment fetchObjectWithUniqueID:attachmentID]; - + if ([attachment isKindOfClass:[TSAttachmentStream class]]) { - TSAttachmentStream *stream = (TSAttachmentStream*)attachment; + TSAttachmentStream *stream = (TSAttachmentStream *)attachment; if ([stream isAnimated]) { adapter.mediaItem = [[TSAnimatedAdapter alloc] initWithAttachment:stream]; - adapter.mediaItem.appliesMediaViewMaskAsOutgoing = [interaction isKindOfClass:[TSOutgoingMessage class]]; + adapter.mediaItem.appliesMediaViewMaskAsOutgoing = + [interaction isKindOfClass:[TSOutgoingMessage class]]; break; - } - else if ([stream isImage]) { + } else if ([stream isImage]) { adapter.mediaItem = [[TSPhotoAdapter alloc] initWithAttachment:stream]; - adapter.mediaItem.appliesMediaViewMaskAsOutgoing = [interaction isKindOfClass:[TSOutgoingMessage class]]; + adapter.mediaItem.appliesMediaViewMaskAsOutgoing = + [interaction isKindOfClass:[TSOutgoingMessage class]]; + break; + } else { + adapter.mediaItem = [[TSVideoAttachmentAdapter alloc] + initWithAttachment:stream + incoming:[interaction isKindOfClass:[TSIncomingMessage class]]]; + adapter.mediaItem.appliesMediaViewMaskAsOutgoing = + [interaction isKindOfClass:[TSOutgoingMessage class]]; break; } - else { - adapter.mediaItem = [[TSVideoAttachmentAdapter alloc] initWithAttachment:stream incoming:[interaction isKindOfClass:[TSIncomingMessage class]]]; - adapter.mediaItem.appliesMediaViewMaskAsOutgoing = [interaction isKindOfClass:[TSOutgoingMessage class]]; - break; - } - } - else if ([attachment isKindOfClass:[TSAttachmentPointer class]]){ - TSAttachmentPointer *pointer = (TSAttachmentPointer*)attachment; - adapter.messageType = TSInfoMessageAdapter; - + } else if ([attachment isKindOfClass:[TSAttachmentPointer class]]) { + TSAttachmentPointer *pointer = (TSAttachmentPointer *)attachment; + adapter.messageType = TSInfoMessageAdapter; + if (pointer.isDownloading) { adapter.messageBody = NSLocalizedString(@"ATTACHMENT_DOWNLOADING", nil); } else { @@ -129,56 +127,60 @@ adapter.messageBody = NSLocalizedString(@"ATTACHMENT_DOWNLOAD_FAILED", nil); } } - } else { - DDLogError(@"We retrieved an attachment that doesn't have a known type : %@", NSStringFromClass([attachment class])); + DDLogError(@"We retrieved an attachment that doesn't have a known type : %@", + NSStringFromClass([attachment class])); } } } - - } else if ([interaction isKindOfClass:[TSCall class]]){ + } else if ([interaction isKindOfClass:[TSCall class]]) { adapter.messageBody = @"Placeholder for TSCalls"; adapter.messageType = TSCallAdapter; - JSQCall *call = [self jsqCallForTSCall:(TSCall*)interaction thread:(TSContactThread*)thread]; - call.useThumbnail = NO; // disables use of iconography to represent group update actions + JSQCall *call = [self jsqCallForTSCall:(TSCall *)interaction thread:(TSContactThread *)thread]; + call.useThumbnail = NO; // disables use of iconography to represent group update actions return call; - } else if ([interaction isKindOfClass:[TSInfoMessage class]]){ - TSInfoMessage * infoMessage = (TSInfoMessage*)interaction; - adapter.infoMessageType = infoMessage.messageType; - adapter.messageBody = infoMessage.description; - adapter.messageType = TSInfoMessageAdapter; - if(adapter.infoMessageType == TSInfoMessageTypeGroupQuit || adapter.infoMessageType == TSInfoMessageTypeGroupUpdate) { - // repurposing call display for info message stuff for group updates, ! adapter will know because the date is nil + } else if ([interaction isKindOfClass:[TSInfoMessage class]]) { + TSInfoMessage *infoMessage = (TSInfoMessage *)interaction; + adapter.infoMessageType = infoMessage.messageType; + adapter.messageBody = infoMessage.description; + adapter.messageType = TSInfoMessageAdapter; + if (adapter.infoMessageType == TSInfoMessageTypeGroupQuit || + adapter.infoMessageType == TSInfoMessageTypeGroupUpdate) { + // repurposing call display for info message stuff for group updates, ! adapter will know because the date + // is nil CallStatus status = 0; - if(adapter.infoMessageType==TSInfoMessageTypeGroupQuit) { + if (adapter.infoMessageType == TSInfoMessageTypeGroupQuit) { status = kGroupUpdateLeft; - } - else if(adapter.infoMessageType == TSInfoMessageTypeGroupUpdate) { + } else if (adapter.infoMessageType == TSInfoMessageTypeGroupUpdate) { status = kGroupUpdate; } - JSQCall* call = [[JSQCall alloc] initWithCallerId:@"" callerDisplayName:adapter.messageBody date:nil status:status displayString:@""]; + JSQCall *call = [[JSQCall alloc] initWithCallerId:@"" + callerDisplayName:adapter.messageBody + date:nil + status:status + displayString:@""]; call.useThumbnail = NO; // disables use of iconography to represent group update actions return call; } } else { - TSErrorMessage * errorMessage = (TSErrorMessage*)interaction; - adapter.infoMessageType = errorMessage.errorType; - adapter.messageBody = errorMessage.description; - adapter.messageType = TSErrorMessageAdapter; + TSErrorMessage *errorMessage = (TSErrorMessage *)interaction; + adapter.infoMessageType = errorMessage.errorType; + adapter.messageBody = errorMessage.description; + adapter.messageType = TSErrorMessageAdapter; } - + if ([interaction isKindOfClass:[TSOutgoingMessage class]]) { - adapter.outgoingMessageStatus = ((TSOutgoingMessage*)interaction).messageState; + adapter.outgoingMessageStatus = ((TSOutgoingMessage *)interaction).messageState; } - + return adapter; } -+ (JSQCall*)jsqCallForTSCall:(TSCall*)call thread:(TSContactThread*)thread{ - CallStatus status = 0; - NSString *name = thread.name; ++ (JSQCall *)jsqCallForTSCall:(TSCall *)call thread:(TSContactThread *)thread { + CallStatus status = 0; + NSString *name = thread.name; NSString *detailString = @""; - + switch (call.callType) { case RPRecentCallTypeOutgoing: status = kCallOutgoing; @@ -193,7 +195,7 @@ status = kCallIncoming; break; } - + switch (status) { case kCallMissed: detailString = [NSString stringWithFormat:NSLocalizedString(@"MSGVIEW_MISSED_CALL", nil), name]; @@ -207,7 +209,7 @@ default: break; } - + JSQCall *jsqCall = [[JSQCall alloc] initWithCallerId:thread.contactIdentifier callerDisplayName:thread.name date:call.date @@ -216,43 +218,42 @@ return jsqCall; } -- (NSString*)senderId{ +- (NSString *)senderId { if (_senderId) { return _senderId; - } - else{ + } else { return ME_MESSAGE_IDENTIFIER; } } -- (NSString *)senderDisplayName{ +- (NSString *)senderDisplayName { if (self.thread) { return _thread.name; } return self.senderDisplayName; } -- (NSDate *)date{ +- (NSDate *)date { return self.messageDate; } -- (BOOL)isMediaMessage{ - return _mediaItem?YES:NO; +- (BOOL)isMediaMessage { + return _mediaItem ? YES : NO; } -- (id)media{ +- (id)media { return _mediaItem; } -- (NSString *)text{ +- (NSString *)text { return self.messageBody; } -- (NSUInteger)messageHash{ +- (NSUInteger)messageHash { return self.identifier; } -- (NSInteger)messageState{ +- (NSInteger)messageState { return self.outgoingMessageStatus; } diff --git a/Signal/src/view controllers/TSPhotoAdapter.h b/Signal/src/view controllers/TSPhotoAdapter.h index 5f54eeadc..3f7da68f5 100644 --- a/Signal/src/view controllers/TSPhotoAdapter.h +++ b/Signal/src/view controllers/TSPhotoAdapter.h @@ -6,13 +6,13 @@ // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // +#import #import #import "TSAttachmentStream.h" -#import @interface TSPhotoAdapter : JSQPhotoMediaItem -- (instancetype)initWithAttachment:(TSAttachmentStream*)attachment; +- (instancetype)initWithAttachment:(TSAttachmentStream *)attachment; - (BOOL)isImage; - (BOOL)isAudio; diff --git a/Signal/src/view controllers/TSPhotoAdapter.m b/Signal/src/view controllers/TSPhotoAdapter.m index 314053006..001613217 100644 --- a/Signal/src/view controllers/TSPhotoAdapter.m +++ b/Signal/src/view controllers/TSPhotoAdapter.m @@ -8,8 +8,8 @@ #import "TSPhotoAdapter.h" -#import "UIDevice+TSHardwareVersion.h" #import "JSQMessagesMediaViewBubbleImageMasker.h" +#import "UIDevice+TSHardwareVersion.h" @interface TSPhotoAdapter () @@ -18,111 +18,98 @@ @implementation TSPhotoAdapter -- (instancetype)initWithAttachment:(TSAttachmentStream*)attachment{ +- (instancetype)initWithAttachment:(TSAttachmentStream *)attachment { self = [super initWithImage:attachment.image]; - + if (self) { _cachedImageView = nil; _attachmentId = attachment.uniqueId; - } return self; } -- (void)dealloc -{ - self.image = nil; +- (void)dealloc { + self.image = nil; _cachedImageView = nil; } -- (void)setAppliesMediaViewMaskAsOutgoing:(BOOL)appliesMediaViewMaskAsOutgoing -{ +- (void)setAppliesMediaViewMaskAsOutgoing:(BOOL)appliesMediaViewMaskAsOutgoing { [super setAppliesMediaViewMaskAsOutgoing:appliesMediaViewMaskAsOutgoing]; _cachedImageView = nil; } #pragma mark - JSQMessageMediaData protocol -- (UIView *)mediaView -{ +- (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; + 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]; + [JSQMessagesMediaViewBubbleImageMasker applyBubbleImageMaskToMediaView:imageView + isOutgoing:self.appliesMediaViewMaskAsOutgoing]; self.cachedImageView = imageView; } - + return self.cachedImageView; } -- (CGSize)mediaViewDisplaySize -{ +- (CGSize)mediaViewDisplaySize { return [self getBubbleSizeForImage:self.image]; } --(BOOL)isImage -{ +- (BOOL)isImage { return YES; } --(BOOL) isAudio { +- (BOOL)isAudio { return NO; } --(BOOL) isVideo { +- (BOOL)isVideo { return NO; } #pragma mark - Utility --(CGSize)getBubbleSizeForImage:(UIImage*)image -{ - CGFloat aspectRatio = image.size.height / image.size.width ; - - if ([[UIDevice currentDevice] isiPhoneVersionSixOrMore]) - { +- (CGSize)getBubbleSizeForImage:(UIImage *)image { + CGFloat aspectRatio = image.size.height / image.size.width; + + if ([[UIDevice currentDevice] isiPhoneVersionSixOrMore]) { return [self getLargeSizeForAspectRatio:aspectRatio]; } else { return [self getSmallSizeForAspectRatio:aspectRatio]; } } --(CGSize)getLargeSizeForAspectRatio:(CGFloat)ratio -{ +- (CGSize)getLargeSizeForAspectRatio:(CGFloat)ratio { return ratio > 1.0f ? [self largePortraitSize] : [self largeLandscapeSize]; } --(CGSize)getSmallSizeForAspectRatio:(CGFloat)ratio -{ +- (CGSize)getSmallSizeForAspectRatio:(CGFloat)ratio { return ratio > 1.0f ? [self smallPortraitSize] : [self smallLandscapeSize]; } -- (CGSize)largePortraitSize -{ +- (CGSize)largePortraitSize { return CGSizeMake(220.0f, 310.0f); } -- (CGSize)smallPortraitSize -{ +- (CGSize)smallPortraitSize { return CGSizeMake(150.0f, 210.0f); } -- (CGSize)largeLandscapeSize -{ +- (CGSize)largeLandscapeSize { return CGSizeMake(310.0f, 220.0f); } -- (CGSize)smallLandscapeSize -{ +- (CGSize)smallLandscapeSize { return CGSizeMake(210.0f, 150.0f); } diff --git a/Signal/src/view controllers/TSVideoAttachmentAdapter.h b/Signal/src/view controllers/TSVideoAttachmentAdapter.h index 18252fa55..e9a8e7736 100644 --- a/Signal/src/view controllers/TSVideoAttachmentAdapter.h +++ b/Signal/src/view controllers/TSVideoAttachmentAdapter.h @@ -6,18 +6,18 @@ // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // +#import #import #import "TSAttachmentStream.h" -#import @interface TSVideoAttachmentAdapter : JSQVideoMediaItem @property NSString *attachmentId; -@property (nonatomic,strong) NSString* contentType; +@property (nonatomic, strong) NSString *contentType; @property (nonatomic) BOOL isAudioPlaying; @property (nonatomic) BOOL isPaused; -- (instancetype)initWithAttachment:(TSAttachmentStream*)attachment incoming:(BOOL)incoming; +- (instancetype)initWithAttachment:(TSAttachmentStream *)attachment incoming:(BOOL)incoming; - (BOOL)isImage; - (BOOL)isAudio; diff --git a/Signal/src/view controllers/TSVideoAttachmentAdapter.m b/Signal/src/view controllers/TSVideoAttachmentAdapter.m index e377056f6..12bd014a7 100644 --- a/Signal/src/view controllers/TSVideoAttachmentAdapter.m +++ b/Signal/src/view controllers/TSVideoAttachmentAdapter.m @@ -6,14 +6,14 @@ // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // -#import "TSVideoAttachmentAdapter.h" #import "TSMessagesManager.h" +#import "TSVideoAttachmentAdapter.h" -#import "JSQMessagesMediaViewBubbleImageMasker.h" #import "FFCircularProgressView.h" -#import "TSStorageManager+keyingMaterial.h" -#import "SCWaveformView.h" +#import "JSQMessagesMediaViewBubbleImageMasker.h" #import "MIMETypeUtil.h" +#import "SCWaveformView.h" +#import "TSStorageManager+keyingMaterial.h" #define AUDIO_BAR_HEIGHT 36 @interface TSVideoAttachmentAdapter () @@ -35,58 +35,58 @@ @implementation TSVideoAttachmentAdapter -- (instancetype)initWithAttachment:(TSAttachmentStream*)attachment incoming:(BOOL)incoming { +- (instancetype)initWithAttachment:(TSAttachmentStream *)attachment incoming:(BOOL)incoming { self = [super initWithFileURL:[attachment mediaURL] isReadyToPlay:YES]; - if (self) {; + if (self) { + ; _image = attachment.image; _cachedImageView = nil; _attachmentId = attachment.uniqueId; _contentType = attachment.contentType; _attachment = attachment; _incoming = incoming; - } return self; } --(BOOL) isImage{ +- (BOOL)isImage { return NO; } --(BOOL) isAudio { +- (BOOL)isAudio { return [MIMETypeUtil isSupportedAudioMIMEType:_contentType]; } --(BOOL) isVideo { +- (BOOL)isVideo { return [MIMETypeUtil isSupportedVideoMIMEType:_contentType]; } --(NSString*)formatDuration:(NSTimeInterval)duration { - double dur = duration; - int minutes = (int) (dur/60); - int seconds = (int) (dur - minutes*60); +- (NSString *)formatDuration:(NSTimeInterval)duration { + double dur = duration; + int minutes = (int)(dur / 60); + int seconds = (int)(dur - minutes * 60); NSString *minutes_str = [NSString stringWithFormat:@"%01d", minutes]; NSString *seconds_str = [NSString stringWithFormat:@"%02d", seconds]; - NSString *label_text = [NSString stringWithFormat:@"%@:%@", minutes_str, seconds_str]; + NSString *label_text = [NSString stringWithFormat:@"%@:%@", minutes_str, seconds_str]; return label_text; } - (void)setAudioProgressFromFloat:(float)progress { dispatch_async(dispatch_get_main_queue(), ^{ - if(!isnan(progress)) { - [_waveform setProgress:progress]; - [_waveform generateWaveforms]; - [_waveform setNeedsDisplay]; - } + if (!isnan(progress)) { + [_waveform setProgress:progress]; + [_waveform generateWaveforms]; + [_waveform setNeedsDisplay]; + } }); } - (void)resetAudioDuration { NSError *err; AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:_attachment.mediaURL error:&err]; - _durationLabel.text = [self formatDuration:player.duration]; + _durationLabel.text = [self formatDuration:player.duration]; } - (void)setDurationOfAudio:(NSTimeInterval)duration { @@ -94,149 +94,161 @@ } - (void)setAudioIconToPlay { - [_audioPlayPauseButton setBackgroundImage:[UIImage imageNamed:@"audio_play_button_blue"] forState:UIControlStateNormal]; + [_audioPlayPauseButton setBackgroundImage:[UIImage imageNamed:@"audio_play_button_blue"] + forState:UIControlStateNormal]; } - (void)setAudioIconToPause { - [_audioPlayPauseButton setBackgroundImage:[UIImage imageNamed:@"audio_pause_button_blue"] forState:UIControlStateNormal]; + [_audioPlayPauseButton setBackgroundImage:[UIImage imageNamed:@"audio_pause_button_blue"] + forState:UIControlStateNormal]; } --(void) removeDurationLabel { +- (void)removeDurationLabel { [_durationLabel removeFromSuperview]; } #pragma mark - JSQMessageMediaData protocol -- (UIView *)mediaView -{ +- (UIView *)mediaView { CGSize size = [self mediaViewDisplaySize]; if ([self isVideo]) { if (self.cachedImageView == nil) { - UIImageView *imageView = [[UIImageView alloc] initWithImage:self.image]; - imageView.frame = CGRectMake(0.0f, 0.0f, size.width, size.height); - imageView.contentMode = UIViewContentModeScaleAspectFill; + 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; - UIImage *img = [UIImage imageNamed:@"play_button"]; - _videoPlayButton = [[UIImageView alloc] initWithImage:img]; - _videoPlayButton.frame = CGRectMake((size.width/2)-18, (size.height/2)-18, 37, 37); + [JSQMessagesMediaViewBubbleImageMasker applyBubbleImageMaskToMediaView:imageView + isOutgoing:self.appliesMediaViewMaskAsOutgoing]; + self.cachedImageView = imageView; + UIImage *img = [UIImage imageNamed:@"play_button"]; + _videoPlayButton = [[UIImageView alloc] initWithImage:img]; + _videoPlayButton.frame = CGRectMake((size.width / 2) - 18, (size.height / 2) - 18, 37, 37); [self.cachedImageView addSubview:_videoPlayButton]; _videoPlayButton.hidden = YES; - _maskLayer = [CALayer layer]; + _maskLayer = [CALayer layer]; [_maskLayer setBackgroundColor:[UIColor blackColor].CGColor]; [_maskLayer setOpacity:0.4f]; [_maskLayer setFrame:self.cachedImageView.frame]; [self.cachedImageView.layer addSublayer:_maskLayer]; - _progressView = [[FFCircularProgressView alloc] initWithFrame:CGRectMake((size.width/2)-18, (size.height/2)-18, 37, 37)]; + _progressView = [[FFCircularProgressView alloc] + initWithFrame:CGRectMake((size.width / 2) - 18, (size.height / 2) - 18, 37, 37)]; [_cachedImageView addSubview:_progressView]; if (_attachment.isDownloaded) { _videoPlayButton.hidden = NO; - _maskLayer.hidden = YES; - _progressView.hidden = YES; + _maskLayer.hidden = YES; + _progressView.hidden = YES; } - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(attachmentUploadProgress:) name:@"attachmentUploadProgress" object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(attachmentUploadProgress:) + name:@"attachmentUploadProgress" + object:nil]; } } else if ([self isAudio]) { - NSError * err = NULL; - NSURL* url = [MIMETypeUtil simLinkCorrectExtensionOfFile:_attachment.mediaURL ofMIMEType:_attachment.contentType]; - - AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:url options:nil]; - _waveform = [[SCWaveformView alloc] init]; - _waveform.frame = CGRectMake(42.0, 0.0, size.width-84, size.height); - _waveform.asset = asset; - _waveform.progressColor = [UIColor whiteColor]; - _waveform.backgroundColor = [UIColor colorWithRed:229/255.0f green:228/255.0f blue:234/255.0f alpha:1.0f]; + NSError *err = NULL; + NSURL *url = + [MIMETypeUtil simLinkCorrectExtensionOfFile:_attachment.mediaURL ofMIMEType:_attachment.contentType]; + + AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:url options:nil]; + _waveform = [[SCWaveformView alloc] init]; + _waveform.frame = CGRectMake(42.0, 0.0, size.width - 84, size.height); + _waveform.asset = asset; + _waveform.progressColor = [UIColor whiteColor]; + _waveform.backgroundColor = [UIColor colorWithRed:229 / 255.0f green:228 / 255.0f blue:234 / 255.0f alpha:1.0f]; [_waveform generateWaveforms]; _waveform.progress = 0.0; - + _audioBubble = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, size.width, size.height)]; - _audioBubble.backgroundColor = [UIColor colorWithRed:10/255.0f green:130/255.0f blue:253/255.0f alpha:1.0f]; - _audioBubble.layer.cornerRadius = 18; + _audioBubble.backgroundColor = + [UIColor colorWithRed:10 / 255.0f green:130 / 255.0f blue:253 / 255.0f alpha:1.0f]; + _audioBubble.layer.cornerRadius = 18; _audioBubble.layer.masksToBounds = YES; _audioPlayPauseButton = [[UIButton alloc] initWithFrame:CGRectMake(3, 3, 30, 30)]; - [_audioPlayPauseButton setBackgroundImage:[UIImage imageNamed:@"audio_play_button"] forState:UIControlStateNormal]; - + [_audioPlayPauseButton setBackgroundImage:[UIImage imageNamed:@"audio_play_button"] + forState:UIControlStateNormal]; + AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&err]; - _durationLabel = [[UILabel alloc] init]; - _durationLabel.text = [self formatDuration:player.duration]; - _durationLabel.font = [UIFont systemFontOfSize:14]; + _durationLabel = [[UILabel alloc] init]; + _durationLabel.text = [self formatDuration:player.duration]; + _durationLabel.font = [UIFont systemFontOfSize:14]; [_durationLabel sizeToFit]; - _durationLabel.frame = CGRectMake((size.width - _durationLabel.frame.size.width) - 10, _durationLabel.frame.origin.y, _durationLabel.frame.size.width, AUDIO_BAR_HEIGHT); + _durationLabel.frame = CGRectMake((size.width - _durationLabel.frame.size.width) - 10, + _durationLabel.frame.origin.y, + _durationLabel.frame.size.width, + AUDIO_BAR_HEIGHT); _durationLabel.backgroundColor = [UIColor clearColor]; - _durationLabel.textColor = [UIColor whiteColor]; - + _durationLabel.textColor = [UIColor whiteColor]; + if (_incoming) { - _audioBubble.backgroundColor = [UIColor colorWithRed:229/255.0f green:228/255.0f blue:234/255.0f alpha:1.0f]; + _audioBubble.backgroundColor = + [UIColor colorWithRed:229 / 255.0f green:228 / 255.0f blue:234 / 255.0f alpha:1.0f]; _waveform.normalColor = [UIColor whiteColor]; - _waveform.progressColor = [UIColor colorWithRed:107/255.0f green:185/255.0f blue:254/255.0f alpha:1.0f]; - [_audioPlayPauseButton setBackgroundImage:[UIImage imageNamed:@"audio_play_button_blue"] forState:UIControlStateNormal]; + _waveform.progressColor = + [UIColor colorWithRed:107 / 255.0f green:185 / 255.0f blue:254 / 255.0f alpha:1.0f]; + [_audioPlayPauseButton setBackgroundImage:[UIImage imageNamed:@"audio_play_button_blue"] + forState:UIControlStateNormal]; _durationLabel.textColor = [UIColor darkTextColor]; } - + [_audioBubble addSubview:_waveform]; [_audioBubble addSubview:_audioPlayPauseButton]; [_audioBubble addSubview:_durationLabel]; - + return _audioBubble; } return self.cachedImageView; } -- (CGSize)mediaViewDisplaySize -{ +- (CGSize)mediaViewDisplaySize { CGSize mediaDisplaySize; if ([self isVideo]) { mediaDisplaySize = [super mediaViewDisplaySize]; } else if ([self isAudio]) { - CGSize size = [super mediaViewDisplaySize]; - size.height = AUDIO_BAR_HEIGHT; + CGSize size = [super mediaViewDisplaySize]; + size.height = AUDIO_BAR_HEIGHT; mediaDisplaySize = size; } return mediaDisplaySize; } -- (UIView *)mediaPlaceholderView -{ +- (UIView *)mediaPlaceholderView { return [self mediaView]; } -- (NSUInteger)hash -{ +- (NSUInteger)hash { return [super hash]; } -- (void)attachmentUploadProgress:(NSNotification*)notification { +- (void)attachmentUploadProgress:(NSNotification *)notification { NSDictionary *userinfo = [notification userInfo]; - double progress = [[userinfo objectForKey:@"progress"] doubleValue]; + double progress = [[userinfo objectForKey:@"progress"] doubleValue]; NSString *attachmentID = [userinfo objectForKey:@"attachmentID"]; if ([_attachmentId isEqualToString:attachmentID]) { NSLog(@"is downloaded: %d", _attachment.isDownloaded); - if(!isnan(progress)) { - [_progressView setProgress: (float)progress]; + if (!isnan(progress)) { + [_progressView setProgress:(float)progress]; } if (progress >= 1) { - _maskLayer.hidden = YES; - _progressView.hidden = YES; - _videoPlayButton.hidden = NO; + _maskLayer.hidden = YES; + _progressView.hidden = YES; + _videoPlayButton.hidden = NO; _attachment.isDownloaded = YES; - [[TSMessagesManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [_attachment saveWithTransaction:transaction]; + [[TSMessagesManager sharedManager] + .dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [_attachment saveWithTransaction:transaction]; }]; } } - //set progress on bar + // set progress on bar } - (void)dealloc { - _image = nil; + _image = nil; _cachedImageView = nil; [[NSNotificationCenter defaultCenter] removeObserver:self]; } -- (void)setAppliesMediaViewMaskAsOutgoing:(BOOL)appliesMediaViewMaskAsOutgoing -{ +- (void)setAppliesMediaViewMaskAsOutgoing:(BOOL)appliesMediaViewMaskAsOutgoing { [super setAppliesMediaViewMaskAsOutgoing:appliesMediaViewMaskAsOutgoing]; _cachedImageView = nil; } diff --git a/Signal/src/view controllers/UITests/SignalsViewController.h b/Signal/src/view controllers/UITests/SignalsViewController.h index 8cb3469c5..85588f7b6 100644 --- a/Signal/src/view controllers/UITests/SignalsViewController.h +++ b/Signal/src/view controllers/UITests/SignalsViewController.h @@ -6,25 +6,28 @@ // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // -#include "InboxTableViewCell.h" #import +#include "InboxTableViewCell.h" +#import "CallState.h" #import "Contact.h" #import "TSGroupModel.h" -#import "CallState.h" -@interface SignalsViewController : UIViewController +@interface SignalsViewController : UIViewController -@property (nonatomic) NSString *contactIdentifierFromCompose; -@property (nonatomic) TSGroupModel *groupFromCompose; -@property (nonatomic) BOOL composeMessage; +@property (nonatomic) NSString *contactIdentifierFromCompose; +@property (nonatomic) TSGroupModel *groupFromCompose; +@property (nonatomic) BOOL composeMessage; @property (nonatomic, retain) IBOutlet UITableView *tableView; @property (nonatomic, strong) IBOutlet UILabel *emptyBoxLabel; -@property (nonatomic, retain) CallState* latestCall; +@property (nonatomic, retain) CallState *latestCall; -- (NSNumber*)updateInboxCountLabel; +- (NSNumber *)updateInboxCountLabel; - (void)composeNew; @end diff --git a/Signal/src/view controllers/UITests/SignalsViewController.m b/Signal/src/view controllers/UITests/SignalsViewController.m index d052851cd..00ec77645 100644 --- a/Signal/src/view controllers/UITests/SignalsViewController.m +++ b/Signal/src/view controllers/UITests/SignalsViewController.m @@ -6,20 +6,20 @@ // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // -#import "UIUtil.h" #import "InboxTableViewCell.h" +#import "UIUtil.h" #import "ContactsManager.h" -#import "MessagesViewController.h" -#import "SignalsViewController.h" #import "InCallViewController.h" -#import "TSStorageManager.h" +#import "MessagesViewController.h" +#import "NSDate+millisecondTimeStamp.h" +#import "PreferencesUtil.h" +#import "SignalsViewController.h" #import "TSAccountManager.h" #import "TSDatabaseView.h" #import "TSMessagesManager+sendMessages.h" +#import "TSStorageManager.h" #import "VersionMigrations.h" -#import "PreferencesUtil.h" -#import "NSDate+millisecondTimeStamp.h" #import #import "YapDatabaseViewConnection.h" @@ -28,7 +28,7 @@ #define HEADER_HEIGHT 44.0f static NSString *const kSegueIndentifier = @"showSegue"; -static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; +static NSString *const kShowSignupFlowSegue = @"showSignupFlow"; @interface SignalsViewController () @@ -38,74 +38,74 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; @property (nonatomic) CellState viewingThreadsIn; @property (nonatomic) long inboxCount; @property (nonatomic, retain) UISegmentedControl *segmentedControl; -@property (nonatomic) NSArray> *previewActions; +@property (nonatomic) NSArray> *previewActions; @end @implementation SignalsViewController -- (void)awakeFromNib{ +- (void)awakeFromNib { [[Environment getCurrent] setSignalsViewController:self]; } - (void)viewDidLoad { [super viewDidLoad]; [self.navigationController.navigationBar setTranslucent:NO]; - + [self tableViewSetUp]; - + self.editingDbConnection = TSStorageManager.sharedManager.newDatabaseConnection; - + [self.uiDatabaseConnection beginLongLivedReadTransaction]; - + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(yapDatabaseModified:) name:TSUIDatabaseConnectionDidUpdateNotification object:nil]; [self selectedInbox:self]; - - [[[Environment getCurrent] contactsManager].getObservableContacts watchLatestValue:^(id latestValue) { - [self.tableView reloadData]; - } onThread:[NSThread mainThread] untilCancelled:nil]; - - self.segmentedControl = [[UISegmentedControl alloc] initWithItems:@[NSLocalizedString(@"WHISPER_NAV_BAR_TITLE", nil), - NSLocalizedString(@"ARCHIVE_NAV_BAR_TITLE", nil)]]; - - [self.segmentedControl addTarget:self action:@selector(swappedSegmentedControl) forControlEvents:UIControlEventValueChanged]; + + [[[Environment getCurrent] contactsManager] + .getObservableContacts watchLatestValue:^(id latestValue) { + [self.tableView reloadData]; + } + onThread:[NSThread mainThread] + untilCancelled:nil]; + + self.segmentedControl = [[UISegmentedControl alloc] initWithItems:@[ + NSLocalizedString(@"WHISPER_NAV_BAR_TITLE", nil), + NSLocalizedString(@"ARCHIVE_NAV_BAR_TITLE", nil) + ]]; + + [self.segmentedControl addTarget:self + action:@selector(swappedSegmentedControl) + forControlEvents:UIControlEventValueChanged]; self.navigationItem.titleView = self.segmentedControl; [self.segmentedControl setSelectedSegmentIndex:0]; - - if ([self.traitCollection - respondsToSelector:@selector(forceTouchCapability)] && - (self.traitCollection.forceTouchCapability == - UIForceTouchCapabilityAvailable)) - { + + if ([self.traitCollection respondsToSelector:@selector(forceTouchCapability)] && + (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)) { [self registerForPreviewingWithDelegate:self sourceView:self.view]; } } -- (UIViewController *)previewingContext: -(id)previewingContext +- (UIViewController *)previewingContext:(id)previewingContext viewControllerForLocation:(CGPoint)location { - NSIndexPath *indexPath = [self.tableView - indexPathForRowAtPoint:location]; - - MessagesViewController * vc = [[MessagesViewController alloc] initWithNibName:nil bundle:nil]; - TSThread *thread = [self threadForIndexPath:indexPath]; + NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location]; + + MessagesViewController *vc = [[MessagesViewController alloc] initWithNibName:nil bundle:nil]; + TSThread *thread = [self threadForIndexPath:indexPath]; [vc setupWithThread:thread]; [vc peekSetup]; - + return vc; } - (void)previewingContext:(id)previewingContext commitViewController:(UIViewController *)viewControllerToCommit { - - MessagesViewController *vc = (MessagesViewController*)viewControllerToCommit; + MessagesViewController *vc = (MessagesViewController *)viewControllerToCommit; [vc popped]; - - [self.navigationController pushViewController:vc - animated:NO]; + + [self.navigationController pushViewController:vc animated:NO]; } - (NSArray> *)previewActionItems { @@ -115,13 +115,12 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; - (NSArray> *)previewActions { if (_previewActions == nil) { UIPreviewAction *printAction = [UIPreviewAction - actionWithTitle:@"Print" - style:UIPreviewActionStyleDefault - handler:^(UIPreviewAction * _Nonnull action, - UIViewController * _Nonnull previewViewController) { - // ... code to handle action here - }]; - _previewActions = @[printAction]; + actionWithTitle:@"Print" + style:UIPreviewActionStyleDefault + handler:^(UIPreviewAction *_Nonnull action, UIViewController *_Nonnull previewViewController){ + // ... code to handle action here + }]; + _previewActions = @[ printAction ]; } return _previewActions; } @@ -130,9 +129,9 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; if (self.presentedViewController) { [self dismissViewControllerAnimated:YES completion:nil]; } - + [self.navigationController popToRootViewControllerAnimated:YES]; - + [self performSegueWithIdentifier:@"composeNew" sender:self]; } @@ -144,26 +143,23 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; } } --(void)viewWillAppear:(BOOL)animated -{ +- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - [self checkIfEmptyView]; - - if (![TSAccountManager isRegistered]){ + [self checkIfEmptyView]; + + if (![TSAccountManager isRegistered]) { [self performSegueWithIdentifier:kShowSignupFlowSegue sender:self]; return; } - + [self updateInboxCountLabel]; [[self tableView] reloadData]; } --(void)tableViewSetUp -{ +- (void)tableViewSetUp { self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; } - #pragma mark - Table View Data Source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { @@ -174,35 +170,35 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; return (NSInteger)[self.threadMappings numberOfItemsInSection:(NSUInteger)section]; } -- (InboxTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath { - - InboxTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:NSStringFromClass([InboxTableViewCell class])]; - TSThread *thread = [self threadForIndexPath:indexPath]; - +- (InboxTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + InboxTableViewCell *cell = + [self.tableView dequeueReusableCellWithIdentifier:NSStringFromClass([InboxTableViewCell class])]; + TSThread *thread = [self threadForIndexPath:indexPath]; + if (!cell) { - cell = [InboxTableViewCell inboxTableViewCell]; + cell = [InboxTableViewCell inboxTableViewCell]; cell.delegate = self; } - + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - [cell configureWithThread:thread]; - [cell configureForState:self.viewingThreadsIn == kInboxState ? kInboxState : kArchiveState]; + [cell configureWithThread:thread]; + [cell configureForState:self.viewingThreadsIn == kInboxState ? kInboxState : kArchiveState]; }); - - if ((unsigned long)indexPath.row == [self.threadMappings numberOfItemsInSection:0]-1) { + + if ((unsigned long)indexPath.row == [self.threadMappings numberOfItemsInSection:0] - 1) { cell.separatorInset = UIEdgeInsetsMake(0.f, cell.bounds.size.width, 0.f, 0.f); } - + return cell; } -- (TSThread*)threadForIndexPath:(NSIndexPath*)indexPath { - +- (TSThread *)threadForIndexPath:(NSIndexPath *)indexPath { __block TSThread *thread = nil; [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - thread = [[transaction extension:TSThreadDatabaseViewExtensionName] objectAtIndexPath:indexPath withMappings:self.threadMappings]; + thread = [[transaction extension:TSThreadDatabaseViewExtensionName] objectAtIndexPath:indexPath + withMappings:self.threadMappings]; }]; - + return thread; } @@ -212,25 +208,29 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; #pragma mark Table Swipe to Delete -- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { +- (void)tableView:(UITableView *)tableView + commitEditingStyle:(UITableViewCellEditingStyle)editingStyle + forRowAtIndexPath:(NSIndexPath *)indexPath { return; } -- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath -{ +- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath { // add the ability to delete the cell - UITableViewRowAction *deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@" " handler:^(UITableViewRowAction *action, NSIndexPath *swipedIndexPath){ - - [self tableViewCellTappedDelete:swipedIndexPath]; - }]; - - - UIImage* buttonImage = [[UIImage imageNamed:@"cellBtnDelete"] resizedImageToSize:CGSizeMake(82.0f, 72.0f)]; - + UITableViewRowAction *deleteAction = + [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault + title:@" " + handler:^(UITableViewRowAction *action, NSIndexPath *swipedIndexPath) { + + [self tableViewCellTappedDelete:swipedIndexPath]; + }]; + + + UIImage *buttonImage = [[UIImage imageNamed:@"cellBtnDelete"] resizedImageToSize:CGSizeMake(82.0f, 72.0f)]; + deleteAction.backgroundColor = [[UIColor alloc] initWithPatternImage:buttonImage]; - - return @[deleteAction]; + + return @[ deleteAction ]; } - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { @@ -239,50 +239,54 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; #pragma mark - HomeFeedTableViewCellDelegate -- (void)tableViewCellTappedDelete:(NSIndexPath*)indexPath { - TSThread *thread = [self threadForIndexPath:indexPath]; - if([thread isKindOfClass:[TSGroupThread class]]) { - TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:thread messageBody:@"" attachments:[[NSMutableArray alloc] init]]; +- (void)tableViewCellTappedDelete:(NSIndexPath *)indexPath { + TSThread *thread = [self threadForIndexPath:indexPath]; + if ([thread isKindOfClass:[TSGroupThread class]]) { + TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] + inThread:thread + messageBody:@"" + attachments:[[NSMutableArray alloc] init]]; message.groupMetaMessage = TSGroupMessageQuit; [[TSMessagesManager sharedManager] sendMessage:message inThread:thread success:nil failure:nil]; } [self.editingDbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [thread removeWithTransaction:transaction]; + [thread removeWithTransaction:transaction]; }]; _inboxCount -= (self.viewingThreadsIn == kArchiveState) ? 1 : 0; [self checkIfEmptyView]; } -- (void)tableViewCellTappedArchive:(InboxTableViewCell*)cell { +- (void)tableViewCellTappedArchive:(InboxTableViewCell *)cell { NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; - TSThread *thread = [self threadForIndexPath:indexPath]; - + TSThread *thread = [self threadForIndexPath:indexPath]; + BOOL viewingThreadsIn = self.viewingThreadsIn; [self.editingDbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - viewingThreadsIn == kInboxState ? [thread archiveThreadWithTransaction:transaction] : [thread unarchiveThreadWithTransaction:transaction]; - + viewingThreadsIn == kInboxState ? [thread archiveThreadWithTransaction:transaction] + : [thread unarchiveThreadWithTransaction:transaction]; + }]; [self checkIfEmptyView]; } -- (NSNumber*)updateInboxCountLabel { +- (NSNumber *)updateInboxCountLabel { NSUInteger numberOfItems = [[TSMessagesManager sharedManager] unreadMessagesCount]; NSNumber *badgeNumber = [NSNumber numberWithUnsignedInteger:numberOfItems]; NSString *unreadString = NSLocalizedString(@"WHISPER_NAV_BAR_TITLE", nil); - + if (![badgeNumber isEqualToNumber:@0]) { - NSString *badgeValue = [badgeNumber stringValue]; - unreadString = [unreadString stringByAppendingFormat:@" (%@)", badgeValue]; + NSString *badgeValue = [badgeNumber stringValue]; + unreadString = [unreadString stringByAppendingFormat:@" (%@)", badgeValue]; } - + [_segmentedControl setTitle:unreadString forSegmentAtIndex:0]; [_segmentedControl reloadInputViews]; [[UIApplication sharedApplication] setApplicationIconBadgeNumber:badgeNumber.integerValue]; - + return badgeNumber; } --(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath{ +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [self performSegueWithIdentifier:kSegueIndentifier sender:self]; [tableView deselectRowAtIndexPath:indexPath animated:NO]; } @@ -290,33 +294,29 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; #pragma mark - Navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - if ([segue.identifier isEqualToString:kSegueIndentifier]){ - MessagesViewController * vc = [segue destinationViewController]; + if ([segue.identifier isEqualToString:kSegueIndentifier]) { + MessagesViewController *vc = [segue destinationViewController]; NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow]; TSThread *thread = [self threadForIndexPath:selectedIndexPath]; - if (self.contactIdentifierFromCompose){ + if (self.contactIdentifierFromCompose) { [vc setupWithTSIdentifier:self.contactIdentifierFromCompose]; [vc setComposeOnOpen:self.composeMessage]; self.contactIdentifierFromCompose = nil; - self.composeMessage = NO; - } - else if (self.groupFromCompose) { + self.composeMessage = NO; + } else if (self.groupFromCompose) { [vc setupWithTSGroup:self.groupFromCompose]; [vc setComposeOnOpen:self.composeMessage]; self.groupFromCompose = nil; - self.composeMessage = NO; - } - else if (thread) { + self.composeMessage = NO; + } else if (thread) { [vc setupWithThread:thread]; [vc setComposeOnOpen:NO]; - } - else if([sender isKindOfClass:[TSGroupThread class]]){ + } else if ([sender isKindOfClass:[TSGroupThread class]]) { [vc setupWithThread:sender]; [vc setComposeOnOpen:YES]; } - } - else if ([segue.identifier isEqualToString:kCallSegue]) { - InCallViewController* vc = [segue destinationViewController]; + } else if ([segue.identifier isEqualToString:kCallSegue]) { + InCallViewController *vc = [segue destinationViewController]; [vc configureWithLatestCall:_latestCall]; _latestCall = nil; } @@ -324,28 +324,28 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; #pragma mark - IBAction --(IBAction)selectedInbox:(id)sender { +- (IBAction)selectedInbox:(id)sender { self.viewingThreadsIn = kInboxState; [self changeToGrouping:TSInboxGroup]; } --(IBAction)selectedArchive:(id)sender { +- (IBAction)selectedArchive:(id)sender { self.viewingThreadsIn = kArchiveState; [self changeToGrouping:TSArchiveGroup]; } --(void) changeToGrouping:(NSString*)grouping { - self.threadMappings = [[YapDatabaseViewMappings alloc] initWithGroups:@[grouping] - view:TSThreadDatabaseViewExtensionName]; +- (void)changeToGrouping:(NSString *)grouping { + self.threadMappings = + [[YapDatabaseViewMappings alloc] initWithGroups:@[ grouping ] view:TSThreadDatabaseViewExtensionName]; [self.threadMappings setIsReversed:YES forGroup:grouping]; - - [self.uiDatabaseConnection asyncReadWithBlock:^(YapDatabaseReadTransaction *transaction){ - [self.threadMappings updateWithTransaction:transaction]; - - dispatch_async(dispatch_get_main_queue(), ^{ - [self.tableView reloadData]; - [self checkIfEmptyView]; - }); + + [self.uiDatabaseConnection asyncReadWithBlock:^(YapDatabaseReadTransaction *transaction) { + [self.threadMappings updateWithTransaction:transaction]; + + dispatch_async(dispatch_get_main_queue(), ^{ + [self.tableView reloadData]; + [self checkIfEmptyView]; + }); }]; } @@ -369,30 +369,26 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; NSArray *notifications = [self.uiDatabaseConnection beginLongLivedReadTransaction]; NSArray *sectionChanges = nil; NSArray *rowChanges = nil; - + [[self.uiDatabaseConnection ext:TSThreadDatabaseViewExtensionName] getSectionChanges:§ionChanges rowChanges:&rowChanges forNotifications:notifications withMappings:self.threadMappings]; - - if ([sectionChanges count] == 0 && [rowChanges count] == 0){ + + if ([sectionChanges count] == 0 && [rowChanges count] == 0) { return; } - + [self.tableView beginUpdates]; - - for (YapDatabaseViewSectionChange *sectionChange in sectionChanges) - { - switch (sectionChange.type) - { - case YapDatabaseViewChangeDelete : - { + + for (YapDatabaseViewSectionChange *sectionChange in sectionChanges) { + switch (sectionChange.type) { + case YapDatabaseViewChangeDelete: { [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionChange.index] withRowAnimation:UITableViewRowAnimationAutomatic]; break; } - case YapDatabaseViewChangeInsert : - { + case YapDatabaseViewChangeInsert: { [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionChange.index] withRowAnimation:UITableViewRowAnimationAutomatic]; break; @@ -402,42 +398,36 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; break; } } - - for (YapDatabaseViewRowChange *rowChange in rowChanges) - { - switch (rowChange.type) - { - case YapDatabaseViewChangeDelete : - { + + for (YapDatabaseViewRowChange *rowChange in rowChanges) { + switch (rowChange.type) { + case YapDatabaseViewChangeDelete: { [self.tableView deleteRowsAtIndexPaths:@[ rowChange.indexPath ] withRowAnimation:UITableViewRowAnimationAutomatic]; _inboxCount += (self.viewingThreadsIn == kArchiveState) ? 1 : 0; break; } - case YapDatabaseViewChangeInsert : - { + case YapDatabaseViewChangeInsert: { [self.tableView insertRowsAtIndexPaths:@[ rowChange.newIndexPath ] withRowAnimation:UITableViewRowAnimationAutomatic]; _inboxCount -= (self.viewingThreadsIn == kArchiveState) ? 1 : 0; break; } - case YapDatabaseViewChangeMove : - { + case YapDatabaseViewChangeMove: { [self.tableView deleteRowsAtIndexPaths:@[ rowChange.indexPath ] withRowAnimation:UITableViewRowAnimationAutomatic]; [self.tableView insertRowsAtIndexPaths:@[ rowChange.newIndexPath ] withRowAnimation:UITableViewRowAnimationAutomatic]; break; } - case YapDatabaseViewChangeUpdate : - { + case YapDatabaseViewChangeUpdate: { [self.tableView reloadRowsAtIndexPaths:@[ rowChange.indexPath ] withRowAnimation:UITableViewRowAnimationNone]; break; } } } - + [self.tableView endUpdates]; [self updateInboxCountLabel]; [self checkIfEmptyView]; @@ -445,60 +435,64 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; - (IBAction)unwindSettingsDone:(UIStoryboardSegue *)segue { - } - (IBAction)unwindMessagesView:(UIStoryboardSegue *)segue { - } -- (void)checkIfEmptyView{ +- (void)checkIfEmptyView { [_tableView setHidden:NO]; - if (self.viewingThreadsIn == kInboxState && [self.threadMappings numberOfItemsInGroup:TSInboxGroup]==0) { + if (self.viewingThreadsIn == kInboxState && [self.threadMappings numberOfItemsInGroup:TSInboxGroup] == 0) { [self setEmptyBoxText]; [_tableView setHidden:YES]; - } - else if (self.viewingThreadsIn == kArchiveState && [self.threadMappings numberOfItemsInGroup:TSArchiveGroup]==0) { + } else if (self.viewingThreadsIn == kArchiveState && + [self.threadMappings numberOfItemsInGroup:TSArchiveGroup] == 0) { [self setEmptyBoxText]; [_tableView setHidden:YES]; } } --(void) setEmptyBoxText { - _emptyBoxLabel.textColor = [UIColor grayColor]; - _emptyBoxLabel.font = [UIFont ows_regularFontWithSize:18.f]; +- (void)setEmptyBoxText { + _emptyBoxLabel.textColor = [UIColor grayColor]; + _emptyBoxLabel.font = [UIFont ows_regularFontWithSize:18.f]; _emptyBoxLabel.textAlignment = NSTextAlignmentCenter; _emptyBoxLabel.numberOfLines = 4; - - NSString* firstLine = @""; - NSString* secondLine = @""; - - if(self.viewingThreadsIn == kInboxState) { - if([Environment.preferences getHasSentAMessage]) { - firstLine = NSLocalizedString(@"EMPTY_INBOX_FIRST_TITLE", @""); + + NSString *firstLine = @""; + NSString *secondLine = @""; + + if (self.viewingThreadsIn == kInboxState) { + if ([Environment.preferences getHasSentAMessage]) { + firstLine = NSLocalizedString(@"EMPTY_INBOX_FIRST_TITLE", @""); secondLine = NSLocalizedString(@"EMPTY_INBOX_FIRST_TEXT", @""); - } - else { - firstLine = NSLocalizedString(@"EMPTY_ARCHIVE_FIRST_TITLE", @""); + } else { + firstLine = NSLocalizedString(@"EMPTY_ARCHIVE_FIRST_TITLE", @""); secondLine = NSLocalizedString(@"EMPTY_ARCHIVE_FIRST_TEXT", @""); } - } - else { - if([Environment.preferences getHasArchivedAMessage]) { - firstLine = NSLocalizedString(@"EMPTY_INBOX_TITLE", @""); - secondLine = NSLocalizedString(@"EMPTY_INBOX_TEXT", @""); - } - else { - firstLine = NSLocalizedString(@"EMPTY_ARCHIVE_TITLE", @""); - secondLine = NSLocalizedString(@"EMPTY_ARCHIVE_TEXT", @""); + } else { + if ([Environment.preferences getHasArchivedAMessage]) { + firstLine = NSLocalizedString(@"EMPTY_INBOX_TITLE", @""); + secondLine = NSLocalizedString(@"EMPTY_INBOX_TEXT", @""); + } else { + firstLine = NSLocalizedString(@"EMPTY_ARCHIVE_TITLE", @""); + secondLine = NSLocalizedString(@"EMPTY_ARCHIVE_TEXT", @""); } } - NSMutableAttributedString *fullLabelString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@\n%@",firstLine,secondLine]]; - - [fullLabelString addAttribute:NSFontAttributeName value:[UIFont ows_boldFontWithSize:15.f] range:NSMakeRange(0,firstLine.length)]; - [fullLabelString addAttribute:NSFontAttributeName value:[UIFont ows_regularFontWithSize:14.f] range:NSMakeRange(firstLine.length + 1, secondLine.length)]; - [fullLabelString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0,firstLine.length)]; - [fullLabelString addAttribute:NSForegroundColorAttributeName value:[UIColor ows_darkGrayColor] range:NSMakeRange(firstLine.length + 1, secondLine.length)]; + NSMutableAttributedString *fullLabelString = + [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@\n%@", firstLine, secondLine]]; + + [fullLabelString addAttribute:NSFontAttributeName + value:[UIFont ows_boldFontWithSize:15.f] + range:NSMakeRange(0, firstLine.length)]; + [fullLabelString addAttribute:NSFontAttributeName + value:[UIFont ows_regularFontWithSize:14.f] + range:NSMakeRange(firstLine.length + 1, secondLine.length)]; + [fullLabelString addAttribute:NSForegroundColorAttributeName + value:[UIColor blackColor] + range:NSMakeRange(0, firstLine.length)]; + [fullLabelString addAttribute:NSForegroundColorAttributeName + value:[UIColor ows_darkGrayColor] + range:NSMakeRange(firstLine.length + 1, secondLine.length)]; _emptyBoxLabel.attributedText = fullLabelString; } diff --git a/Signal/src/views/ContactTableViewCell.m b/Signal/src/views/ContactTableViewCell.m index c46ee8218..2e652e850 100644 --- a/Signal/src/views/ContactTableViewCell.m +++ b/Signal/src/views/ContactTableViewCell.m @@ -6,10 +6,9 @@ #define CONTACT_TABLE_CELL_BORDER_WIDTH 1.0f -@interface ContactTableViewCell() { - +@interface ContactTableViewCell () { } -@property(strong,nonatomic) Contact* associatedContact; +@property (strong, nonatomic) Contact *associatedContact; @end @implementation ContactTableViewCell @@ -25,11 +24,11 @@ - (void)configureWithContact:(Contact *)contact { - if(!contact.isTextSecureContact) { + if (!contact.isTextSecureContact) { self.selectionStyle = UITableViewCellSelectionStyleNone; } _associatedContact = contact; - + _nameLabel.attributedText = [self attributedStringForContact:contact]; if (!contact.isTextSecureContact) { _nameLabel.textColor = [UIColor lightGrayColor]; @@ -37,28 +36,37 @@ } - (NSAttributedString *)attributedStringForContact:(Contact *)contact { - NSMutableAttributedString *fullNameAttributedString = [[NSMutableAttributedString alloc] initWithString:contact.fullName]; + NSMutableAttributedString *fullNameAttributedString = + [[NSMutableAttributedString alloc] initWithString:contact.fullName]; UIFont *firstNameFont; UIFont *lastNameFont; - + if (ABPersonGetSortOrdering() == kABPersonCompositeNameFormatFirstNameFirst) { firstNameFont = [UIFont ows_mediumFontWithSize:_nameLabel.font.pointSize]; lastNameFont = [UIFont ows_regularFontWithSize:_nameLabel.font.pointSize]; - } - else { + } else { firstNameFont = [UIFont ows_regularFontWithSize:_nameLabel.font.pointSize]; lastNameFont = [UIFont ows_mediumFontWithSize:_nameLabel.font.pointSize]; } - [fullNameAttributedString addAttribute:NSFontAttributeName value:firstNameFont range:NSMakeRange(0, contact.firstName.length)]; - [fullNameAttributedString addAttribute:NSFontAttributeName value:lastNameFont range:NSMakeRange(contact.firstName.length + 1, contact.lastName.length)]; - [fullNameAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0, contact.fullName.length)]; - + [fullNameAttributedString addAttribute:NSFontAttributeName + value:firstNameFont + range:NSMakeRange(0, contact.firstName.length)]; + [fullNameAttributedString addAttribute:NSFontAttributeName + value:lastNameFont + range:NSMakeRange(contact.firstName.length + 1, contact.lastName.length)]; + [fullNameAttributedString addAttribute:NSForegroundColorAttributeName + value:[UIColor blackColor] + range:NSMakeRange(0, contact.fullName.length)]; + if (ABPersonGetSortOrdering() == kABPersonCompositeNameFormatFirstNameFirst) { - [fullNameAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor ows_darkGrayColor] range:NSMakeRange(contact.firstName.length + 1, contact.lastName.length)]; - } - else { - [fullNameAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor ows_darkGrayColor] range:NSMakeRange(0, contact.firstName.length)]; + [fullNameAttributedString addAttribute:NSForegroundColorAttributeName + value:[UIColor ows_darkGrayColor] + range:NSMakeRange(contact.firstName.length + 1, contact.lastName.length)]; + } else { + [fullNameAttributedString addAttribute:NSForegroundColorAttributeName + value:[UIColor ows_darkGrayColor] + range:NSMakeRange(0, contact.firstName.length)]; } return fullNameAttributedString; } diff --git a/Signal/test/network/tcp/tls/NetworkStreamTest.m b/Signal/test/network/tcp/tls/NetworkStreamTest.m index 4fb8ca534..4256a64ea 100644 --- a/Signal/test/network/tcp/tls/NetworkStreamTest.m +++ b/Signal/test/network/tcp/tls/NetworkStreamTest.m @@ -97,7 +97,7 @@ -(void) testAuthenticationFail_WrongCert { [Environment setCurrent:testEnv]; - NSString *certPath = [[[NSBundle bundleForClass:NetworkStream.class] resourcePath] stringByAppendingPathComponent:@"whisperFake.cer"]; + NSString *certPath = [[[NSBundle bundleForClass:[self class]] resourcePath] stringByAppendingPathComponent:@"whisperFake.cer"]; NSData *certData = [[NSData alloc] initWithContentsOfFile:certPath]; checkOperation(certData != nil); diff --git a/Signal/test/textsecure/CryptographyTests.mm b/Signal/test/textsecure/CryptographyTests.mm deleted file mode 100644 index 7b03ab57e..000000000 --- a/Signal/test/textsecure/CryptographyTests.mm +++ /dev/null @@ -1,65 +0,0 @@ -// -// CryptographyTests.m -// TextSecureiOS -// -// Created by Christine Corbett Moran on 12/19/13. -// Copyright (c) 2013 Open Whisper Systems. All rights reserved. -// - -#import -#import "Cryptography.h" -#import "NSData+Base64.h" - -@interface CryptographyTests : XCTestCase - -@end - - -@interface Cryptography (Test) -+(NSData*) truncatedSHA256HMAC:(NSData*)dataToHMAC withHMACKey:(NSData*)HMACKey truncation:(int)bytes; -+(NSData*)encryptCBCMode:(NSData*) dataToEncrypt withKey:(NSData*) key withIV:(NSData*) iv withVersion:(NSData*)version withHMACKey:(NSData*) hmacKey withHMACType:(TSMACType)hmacType computedHMAC:(NSData**)hmac; - -+(NSData*)decryptCBCMode:(NSData*)dataToDecrypt - key:(NSData*)key - IV:(NSData*)iv - version:(NSData*)version - HMACKey:(NSData*) hmacKey - HMACType:(TSMACType)hmacType - matchingHMAC:(NSData *)hmac; -@end - -@implementation CryptographyTests - - --(void) testLocalDecryption { - NSString* originalMessage = @"Hawaii is awesome"; - NSString* signalingKeyString = @"VJuRzZcwuY/6VjGw+QSPy5ROzHo8xE36mKwHNvkfyZ+mSPaDlSDcenUqavIX1Vwn\nRRIdrg=="; - NSData* signalingKey = [NSData dataFromBase64String:signalingKeyString]; - XCTAssertTrue([signalingKey length]==52, @"signaling key is not 52 bytes but %llu", (unsigned long long)[signalingKey length]); - NSData* signalingKeyAESKeyMaterial = [signalingKey subdataWithRange:NSMakeRange(0, 32)]; - NSData* signalingKeyHMACKeyMaterial = [signalingKey subdataWithRange:NSMakeRange(32, 20)]; - NSData* iv = [Cryptography generateRandomBytes:16]; - NSData* version = [Cryptography generateRandomBytes:1]; - NSData* mac; - - NSData* encryption = [Cryptography encryptCBCMode:[originalMessage dataUsingEncoding:NSUTF8StringEncoding] withKey:signalingKeyAESKeyMaterial withIV:iv withVersion:version withHMACKey:signalingKeyHMACKeyMaterial withHMACType:TSHMACSHA1Truncated10Bytes computedHMAC:&mac]; //Encrypt - - NSMutableData *dataToHmac = [NSMutableData data ]; - [dataToHmac appendData:version]; - [dataToHmac appendData:iv]; - [dataToHmac appendData:encryption]; - - - NSData* expectedHmac = [Cryptography truncatedSHA1HMAC:dataToHmac withHMACKey:signalingKeyHMACKeyMaterial truncation:10]; - - XCTAssertTrue([mac isEqualToData:expectedHmac], @"Hmac of encrypted data %@, not equal to expected hmac %@", [mac base64EncodedString], [expectedHmac base64EncodedString]); - - NSData* decryption=[Cryptography decryptCBCMode:encryption key:signalingKeyAESKeyMaterial IV:iv version:version HMACKey:signalingKeyHMACKeyMaterial HMACType:TSHMACSHA1Truncated10Bytes matchingHMAC:mac]; - - NSString* decryptedMessage = [[NSString alloc] initWithData:decryption encoding:NSUTF8StringEncoding]; - XCTAssertTrue([decryptedMessage isEqualToString:originalMessage], @"Decrypted message: %@ is not equal to original: %@",decryptedMessage,originalMessage); - -} - -@end - diff --git a/Signal/test/textsecure/MessagePaddingTests.m b/Signal/test/textsecure/MessagePaddingTests.m deleted file mode 100644 index 4b00dcfa2..000000000 --- a/Signal/test/textsecure/MessagePaddingTests.m +++ /dev/null @@ -1,44 +0,0 @@ -// -// MessagePaddingTests.m -// Signal -// -// Created by Frederic Jacobs on 26/02/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import "Cryptography.h" -#import "NSData+messagePadding.h" -#import - -@interface MessagePaddingTests : XCTestCase - -@end - -@implementation MessagePaddingTests - -- (void)testV3Padding { - for (NSUInteger i=0;i<159;i++) { - NSData *data = [NSMutableData dataWithLength:i]; - XCTAssert([data paddedMessageBody].length == 159); - } - - for (NSUInteger i=159;i<319;i++) { - NSData *data = [NSMutableData dataWithLength:i]; - XCTAssert([data paddedMessageBody].length == 319); - } - - for (NSUInteger i=319;i<479;i++) { - NSData *data = [NSMutableData dataWithLength:i]; - XCTAssert([data paddedMessageBody].length == 479); - } -} - -- (void)testV3RandomPadding{ - for (int i = 0; i < 1000; i++) { - NSData *randomMessage = [Cryptography generateRandomBytes:501]; - NSData *paddedMessage = [randomMessage paddedMessageBody]; - XCTAssert([[paddedMessage removePadding] isEqualToData:randomMessage]); - } -} - -@end diff --git a/Signal/test/textsecure/SignedPreKeyDeletionTests.m b/Signal/test/textsecure/SignedPreKeyDeletionTests.m deleted file mode 100644 index ce94fa288..000000000 --- a/Signal/test/textsecure/SignedPreKeyDeletionTests.m +++ /dev/null @@ -1,83 +0,0 @@ -// -// SignedPreKeyDeletionTests.m -// Signal -// -// Created by Frederic Jacobs on 27/01/15. -// Copyright (c) 2015 Open Whisper Systems. All rights reserved. -// - -#import - -#import - -#import "TSPreKeyManager.h" -#import "TSStorageManager+SignedPreKeyStore.h" - -@interface TSPreKeyManager () - -+ (void)clearSignedPreKeyRecordsWithKeyId:(NSNumber*)keyId; - -@end - - -@interface SignedPreKeyDeletionTests : XCTestCase - -@property int lastpreKeyId; - -@end - -@implementation SignedPreKeyDeletionTests - -- (void)setUp { - [super setUp]; -} - -- (void)tearDown { - [super tearDown]; -} - -- (void)testSignedPreKeyDeletion { - [[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [transaction removeAllObjectsInCollection:TSStorageManagerSignedPreKeyStoreCollection]; - }]; - - _lastpreKeyId = 20; - - for (int i = 0; i <= _lastpreKeyId; i++) { // 21 signed keys are generated, one per day from now until 20 days ago. - SignedPreKeyRecord *record = [[SignedPreKeyRecord alloc] initWithId:i keyPair:[Curve25519 generateKeyPair] signature:nil generatedAt:[NSDate dateWithTimeIntervalSinceNow:i*24*60*60]]; - [[TSStorageManager sharedManager] storeSignedPreKey:i signedPreKeyRecord:record]; - } - - - [TSPreKeyManager clearSignedPreKeyRecordsWithKeyId:[NSNumber numberWithInt:_lastpreKeyId]]; - - - XCTAssert([[TSStorageManager sharedManager]loadSignedPrekey:_lastpreKeyId] != nil); - - // We tolerate to keep keys around for 14 days. We have 20-15 = 5 keys to delete. Hence the result of 21-5 = 16 - XCTAssert([[[TSStorageManager sharedManager] loadSignedPreKeys] count] == 16); -} - - -- (void)testOlderRecordsNotDeletedIfNoReplacement { - [[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [transaction removeAllObjectsInCollection:TSStorageManagerSignedPreKeyStoreCollection]; - }]; - - _lastpreKeyId = 3; - - for (int i = 1; i <= _lastpreKeyId; i++) { // 21 signed keys are generated, one per day from now until 20 days ago. - SignedPreKeyRecord *record = [[SignedPreKeyRecord alloc] initWithId:i keyPair:[Curve25519 generateKeyPair] signature:nil generatedAt:[NSDate dateWithTimeIntervalSinceNow:i*100*24*60*60]]; - [[TSStorageManager sharedManager] storeSignedPreKey:i signedPreKeyRecord:record]; - } - - - [TSPreKeyManager clearSignedPreKeyRecordsWithKeyId:[NSNumber numberWithInt:_lastpreKeyId]]; - - - XCTAssert([[TSStorageManager sharedManager]loadSignedPrekey:_lastpreKeyId] != nil); - // All three records should still be stored. - XCTAssert([[[TSStorageManager sharedManager] loadSignedPreKeys] count] == 3); -} - -@end diff --git a/Signal/test/textsecure/TSAttachementsTest.m b/Signal/test/textsecure/TSAttachementsTest.m deleted file mode 100644 index bf7a19996..000000000 --- a/Signal/test/textsecure/TSAttachementsTest.m +++ /dev/null @@ -1,43 +0,0 @@ -// -// TSAttachementsTest.m -// Signal -// -// Created by Frederic Jacobs on 21/12/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import - -#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 diff --git a/Signal/test/textsecure/TSMessageStorageTests.m b/Signal/test/textsecure/TSMessageStorageTests.m deleted file mode 100644 index dacaa4ce7..000000000 --- a/Signal/test/textsecure/TSMessageStorageTests.m +++ /dev/null @@ -1,208 +0,0 @@ -// -// TSMessageStorageTests.m -// TextSecureKit -// -// Created by Frederic Jacobs on 16/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import - -#import "Cryptography.h" -#import "TSThread.h" -#import "TSContactThread.h" -#import "TSGroupThread.h" - -#import "TSStorageManager.h" - -#import "TSMessage.h" -#import "TSIncomingMessage.h" - - -@interface TSMessageStorageTests : XCTestCase - -@property TSContactThread *thread; - -@end - -@implementation TSMessageStorageTests - -- (void)setUp { - [super setUp]; - - [[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - self.thread = [TSContactThread getOrCreateThreadWithContactId:@"aStupidId" transaction:transaction]; - - [self.thread saveWithTransaction:transaction]; - }]; - - TSStorageManager *manager = [TSStorageManager sharedManager]; - [manager purgeCollection:[TSMessage collection]]; -} - -- (void)tearDown { - // Put teardown code here. This method is called after the invocation of each test method in the class. - [super tearDown]; -} - -- (void)testIncrementalMessageNumbers{ - __block NSInteger messageInt; - NSString *body = @"I don't see myself as a hero because what I'm doing is self-interested: I don't want to live in a world where there's no privacy and therefore no room for intellectual exploration and creativity."; - [[TSStorageManager sharedManager].newDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - - NSString* messageId; - - for (uint64_t i = 0; i<50; i++) { - TSIncomingMessage *newMessage = [[TSIncomingMessage alloc] initWithTimestamp:i - inThread:self.thread - messageBody:body - attachments:nil]; - [newMessage saveWithTransaction:transaction]; - if (i == 0) { - messageId = newMessage.uniqueId; - } - } - - messageInt = [messageId integerValue]; - - for (NSInteger i = messageInt; i < messageInt+50; i++) { - TSIncomingMessage *message = [TSIncomingMessage fetchObjectWithUniqueID:[@(i) stringValue] transaction:transaction]; - XCTAssert(message != nil); - XCTAssert(message.body == body); - } - }]; - - [[TSStorageManager sharedManager].newDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - TSIncomingMessage *deletedmessage = [TSIncomingMessage fetchObjectWithUniqueID:[@(messageInt+49) stringValue]]; - [deletedmessage removeWithTransaction:transaction]; - - uint64_t uniqueNewTimestamp = 985439854983; - TSIncomingMessage *newMessage = [[TSIncomingMessage alloc] initWithTimestamp:uniqueNewTimestamp - inThread:self.thread - messageBody:body - attachments:nil]; - [newMessage saveWithTransaction:transaction]; - - TSIncomingMessage *retrieved = [TSIncomingMessage fetchObjectWithUniqueID:[@(messageInt+50) stringValue] transaction:transaction]; - XCTAssert(retrieved.timestamp == uniqueNewTimestamp); - }]; -} - -- (void)testStoreIncomingMessage { - __block NSString *messageId; - uint64_t timestamp = 666; - - NSString *body = @"A child born today will grow up with no conception of privacy at all. They’ll never know what it means to have a private moment to themselves an unrecorded, unanalyzed thought. And that’s a problem because privacy matters; privacy is what allows us to determine who we are and who we want to be."; - - TSIncomingMessage *newMessage = [[TSIncomingMessage alloc] initWithTimestamp:timestamp - inThread:self.thread - messageBody:body - attachments:nil]; - [[TSStorageManager sharedManager].newDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - [newMessage saveWithTransaction:transaction]; - messageId = newMessage.uniqueId; - }]; - - TSIncomingMessage *fetchedMessage = [TSIncomingMessage fetchObjectWithUniqueID:messageId]; - - NSAssert([fetchedMessage.body isEqualToString:body], @"Body of incoming message recovered"); - NSAssert(fetchedMessage.attachments == nil, @"attachments are nil"); - NSAssert(fetchedMessage.timestamp == timestamp, @"Unique identifier is accurate"); - NSAssert(fetchedMessage.wasRead == false, @"Message should originally be unread"); - NSAssert([fetchedMessage.uniqueThreadId isEqualToString:self.thread.uniqueId], @"Isn't stored in the right thread!"); -} - -- (void)testMessagesDeletedOnThreadDeletion { - uint64_t timestamp = 666; - NSString *body = @"A child born today will grow up with no conception of privacy at all. They’ll never know what it means to have a private moment to themselves an unrecorded, unanalyzed thought. And that’s a problem because privacy matters; privacy is what allows us to determine who we are and who we want to be."; - - for (uint64_t i = timestamp; i<100; i++) { - TSIncomingMessage *newMessage = [[TSIncomingMessage alloc] initWithTimestamp:i - inThread:self.thread - messageBody:body - attachments:nil]; - [newMessage save]; - } - - - - [[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - for (uint64_t i = timestamp; i<100; i++) { - TSIncomingMessage *fetchedMessage = [TSIncomingMessage fetchObjectWithUniqueID:[TSInteraction stringFromTimeStamp:timestamp] transaction:transaction]; - - NSAssert([fetchedMessage.body isEqualToString:body], @"Body of incoming message recovered"); - NSAssert(fetchedMessage.attachments == nil, @"attachments are nil"); - NSAssert([fetchedMessage.uniqueId isEqualToString:[TSInteraction stringFromTimeStamp:timestamp]], @"Unique identifier is accurate"); - NSAssert(fetchedMessage.wasRead == false, @"Message should originally be unread"); - NSAssert([fetchedMessage.uniqueThreadId isEqualToString:self.thread.uniqueId], @"Isn't stored in the right thread!"); - } - }]; - - - [self.thread remove]; - - [[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - for (uint64_t i = timestamp; i<100; i++) { - TSIncomingMessage *fetchedMessage = [TSIncomingMessage fetchObjectWithUniqueID:[TSInteraction stringFromTimeStamp:timestamp] transaction:transaction]; - NSAssert(fetchedMessage == nil, @"Message should be deleted!"); - } - }]; -} - - -- (void)testGroupMessagesDeletedOnThreadDeletion { - uint64_t timestamp = 666; - NSString *body = @"A child born today will grow up with no conception of privacy at all. They’ll never know what it means to have a private moment to themselves an unrecorded, unanalyzed thought. And that’s a problem because privacy matters; privacy is what allows us to determine who we are and who we want to be."; - - - TSAttachmentStream *pointer = [[TSAttachmentStream alloc] initWithIdentifier:@"helloid" data:[Cryptography generateRandomBytes:16] key:[Cryptography generateRandomBytes:16] contentType:@"data/random"]; - - __block TSGroupThread *thread; - [[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - thread = [TSGroupThread getOrCreateThreadWithGroupModel:[[TSGroupModel alloc] initWithTitle:@"fdsfsd" memberIds:[@[] mutableCopy] image:nil groupId:[NSData data] associatedAttachmentId:pointer.uniqueId] transaction:transaction]; - - [thread saveWithTransaction:transaction]; - [pointer saveWithTransaction:transaction]; - - }]; - - TSStorageManager *manager = [TSStorageManager sharedManager]; - [manager purgeCollection:[TSMessage collection]]; - - for (uint64_t i = timestamp; i<100; i++) { - TSIncomingMessage *newMessage = [[TSIncomingMessage alloc] initWithTimestamp:i inThread:thread authorId:@"Ed" messageBody:body attachments:nil]; - - [newMessage save]; - } - - - - [[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - for (uint64_t i = timestamp; i<100; i++) { - TSIncomingMessage *fetchedMessage = [TSIncomingMessage fetchObjectWithUniqueID:[TSInteraction stringFromTimeStamp:timestamp] transaction:transaction]; - TSAttachmentStream *fetchedPointer = [TSAttachmentStream fetchObjectWithUniqueID:pointer.uniqueId]; - NSAssert([fetchedPointer.image isEqual:pointer.image], @"attachment pointers not equal"); - - - NSAssert([fetchedMessage.body isEqualToString:body], @"Body of incoming message recovered"); - NSAssert(fetchedMessage.attachments == nil, @"attachments are nil"); - NSAssert([fetchedMessage.uniqueId isEqualToString:[TSInteraction stringFromTimeStamp:timestamp]], @"Unique identifier is accurate"); - NSAssert(fetchedMessage.wasRead == false, @"Message should originally be unread"); - NSAssert([fetchedMessage.uniqueThreadId isEqualToString:self.thread.uniqueId], @"Isn't stored in the right thread!"); - } - }]; - - - [self.thread remove]; - - [[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - for (uint64_t i = timestamp; i<100; i++) { - TSIncomingMessage *fetchedMessage = [TSIncomingMessage fetchObjectWithUniqueID:[TSInteraction stringFromTimeStamp:timestamp] transaction:transaction]; - TSAttachmentStream *fetchedPointer = [TSAttachmentStream fetchObjectWithUniqueID:pointer.uniqueId]; - NSAssert(fetchedPointer == nil, @"Attachment pointer should be deleted"); - NSAssert(fetchedMessage == nil, @"Message should be deleted!"); - } - }]; -} - -@end diff --git a/Signal/test/textsecure/TSStorageIdentityKeyStoreTests.m b/Signal/test/textsecure/TSStorageIdentityKeyStoreTests.m deleted file mode 100644 index 84a0f301f..000000000 --- a/Signal/test/textsecure/TSStorageIdentityKeyStoreTests.m +++ /dev/null @@ -1,69 +0,0 @@ -// -// TSStorageIdentityKeyStoreTests.m -// TextSecureKit -// -// Created by Frederic Jacobs on 06/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import -#import <25519/Curve25519.h> - -#import "TSStorageManager.h" -#import "TSStorageManager+IdentityKeyStore.h" -#import "SecurityUtils.h" - -@interface TSStorageIdentityKeyStoreTests : XCTestCase - -@end - -@implementation TSStorageIdentityKeyStoreTests - -- (void)setUp { - [super setUp]; - [[TSStorageManager sharedManager] purgeCollection:@"TSStorageManagerTrustedKeysCollection"]; - // 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)testNewEmptyKey { - NSData *newKey = [SecurityUtils generateRandomBytes:32]; - NSString *recipientId = @"test@gmail.com"; - - XCTAssert([[TSStorageManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId]); -} - -- (void)testAlreadyRegisteredKey { - NSData *newKey = [SecurityUtils generateRandomBytes:32]; - NSString *recipientId = @"test@gmail.com"; - - [[TSStorageManager sharedManager] saveRemoteIdentity:newKey recipientId:recipientId]; - - XCTAssert([[TSStorageManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId]); -} - - -- (void)testChangedKey { - NSData *newKey = [SecurityUtils generateRandomBytes:32]; - NSString *recipientId = @"test@gmail.com"; - - [[TSStorageManager sharedManager] saveRemoteIdentity:newKey recipientId:recipientId]; - - XCTAssert([[TSStorageManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId]); - - NSData *otherKey = [SecurityUtils generateRandomBytes:32]; - - XCTAssertFalse([[TSStorageManager sharedManager] isTrustedIdentityKey:otherKey recipientId:recipientId]); -} - -- (void)testIdentityKey { - [[TSStorageManager sharedManager] generateNewIdentityKey]; - - XCTAssert([[[TSStorageManager sharedManager] identityKeyPair].publicKey length] == 32); -} - -@end diff --git a/Signal/test/textsecure/TSStoragePreKeyStoreTests.m b/Signal/test/textsecure/TSStoragePreKeyStoreTests.m deleted file mode 100644 index 2eddbc39c..000000000 --- a/Signal/test/textsecure/TSStoragePreKeyStoreTests.m +++ /dev/null @@ -1,63 +0,0 @@ -// -// TSStoragePreKeyStoreTests.m -// TextSecureKit -// -// Created by Frederic Jacobs on 07/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import "TSStorageManager+PreKeyStore.h" -#import - -@interface TSStoragePreKeyStoreTests : XCTestCase - -@end - -@implementation TSStoragePreKeyStoreTests - -- (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)testGeneratingAndStoringPreKeys { - NSArray *generatedKeys = [[TSStorageManager sharedManager] generatePreKeyRecords]; - - - XCTAssert([generatedKeys count] == 100, @"Not hundred keys generated"); - - [[TSStorageManager sharedManager] storePreKeyRecords:generatedKeys]; - - PreKeyRecord *lastPreKeyRecord = [generatedKeys lastObject]; - PreKeyRecord *firstPreKeyRecord = [generatedKeys firstObject]; - - XCTAssert([[[TSStorageManager sharedManager] loadPreKey:lastPreKeyRecord.Id].keyPair.publicKey isEqualToData:lastPreKeyRecord.keyPair.publicKey]); - - XCTAssert([[[TSStorageManager sharedManager] loadPreKey:firstPreKeyRecord.Id].keyPair.publicKey isEqualToData:firstPreKeyRecord.keyPair.publicKey]); - -} - - -- (void)testRemovingPreKeys { - NSArray *generatedKeys = [[TSStorageManager sharedManager] generatePreKeyRecords]; - - XCTAssert([generatedKeys count] == 100, @"Not hundred keys generated"); - - [[TSStorageManager sharedManager] storePreKeyRecords:generatedKeys]; - - PreKeyRecord *lastPreKeyRecord = [generatedKeys lastObject]; - PreKeyRecord *firstPreKeyRecord = [generatedKeys firstObject]; - - [[TSStorageManager sharedManager] removePreKey:lastPreKeyRecord.Id]; - - XCTAssertThrows([[TSStorageManager sharedManager] loadPreKey:lastPreKeyRecord.Id]); - XCTAssertNoThrow([[TSStorageManager sharedManager] loadPreKey:firstPreKeyRecord.Id]); - -} - -@end diff --git a/Signal/test/textsecure/TSStorageSignedPreKeyStore.m b/Signal/test/textsecure/TSStorageSignedPreKeyStore.m deleted file mode 100644 index f8d96b9d6..000000000 --- a/Signal/test/textsecure/TSStorageSignedPreKeyStore.m +++ /dev/null @@ -1,29 +0,0 @@ -// -// TSStorageSignedPreKeyStore.m -// TextSecureKit -// -// Created by Frederic Jacobs on 07/11/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import - -@interface TSStorageSignedPreKeyStore : XCTestCase - -@end - -@implementation TSStorageSignedPreKeyStore - -- (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]; -} - - - -@end diff --git a/Signal/test/textsecure/TextSecureKitTests.m b/Signal/test/textsecure/TextSecureKitTests.m deleted file mode 100644 index ab841ade7..000000000 --- a/Signal/test/textsecure/TextSecureKitTests.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// TextSecureKitTests.m -// TextSecureKitTests -// -// Created by Frederic Jacobs on 27/10/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// - -#import - -@interface TextSecureKitTests : XCTestCase - -@end - -@implementation TextSecureKitTests - -- (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]; -} - - -@end diff --git a/Signal/test/util/ExceptionsTest.m b/Signal/test/util/ExceptionsTest.m index da692e036..8b848b691 100644 --- a/Signal/test/util/ExceptionsTest.m +++ b/Signal/test/util/ExceptionsTest.m @@ -1,14 +1,14 @@ -#import "ExceptionsTest.h" #import "Constraints.h" +#import "ExceptionsTest.h" #import "TestUtil.h" @implementation ExceptionsTest --(void) testContracts { - require(1 + 1 == 2); +- (void)testContracts { + ows_require(1 + 1 == 2); @try { - require(1 + 1 == 3); + ows_require(1 + 1 == 3); XCTFail(@""); - } @catch (BadArgument* ex) { + } @catch (BadArgument *ex) { test([[ex reason] hasPrefix:@"require 1 + 1 == 3"]); } @@ -16,15 +16,15 @@ @try { requireState(1 + 1 == 3); XCTFail(@""); - } @catch (BadState* ex) { - test([[ex reason] hasPrefix:@"required state: 1 + 1 == 3"]); + } @catch (BadState *ex) { + test([[ex reason] hasPrefix:@"required state: 1 + 1 == 3"]); } checkOperationDescribe(1 + 1 == 2, @"addition."); @try { checkOperationDescribe(1 + 1 == 3, @"addition."); XCTFail(@""); - } @catch (OperationFailed* ex) { + } @catch (OperationFailed *ex) { test([[ex reason] hasPrefix:@"Operation failed: addition. Expected: 1 + 1 == 3"]); } @@ -32,7 +32,7 @@ @try { checkOperation(1 + 1 == 3); XCTFail(@""); - } @catch (OperationFailed* ex) { + } @catch (OperationFailed *ex) { test([[ex reason] hasPrefix:@"Operation failed. Expected: 1 + 1 == 3"]); } } diff --git a/Signal/test/util/FutureUtilTest.m b/Signal/test/util/FutureUtilTest.m index c209ab3a6..2211ac4f4 100644 --- a/Signal/test/util/FutureUtilTest.m +++ b/Signal/test/util/FutureUtilTest.m @@ -1,138 +1,182 @@ +#import #import +#import "FutureUtil.h" #import "TestUtil.h" #import "ThreadManager.h" -@interface FutureUtilTest:XCTestCase +@interface FutureUtilTest : XCTestCase @end @implementation FutureUtilTest --(void)testOperationTry { - TOCFuture* f = [TOCFuture operationTry:^TOCFuture*(TOCCancelToken *_) { @throw @"Fail"; }](nil); +- (void)testOperationTry { + TOCFuture *f = [TOCFuture operationTry:^TOCFuture *(TOCCancelToken *_) { + @throw @"Fail"; + }](nil); test([f isEqualToFuture:[TOCFuture futureWithFailure:@"Fail"]]); } --(void)testThenValue { +- (void)testThenValue { test([[[TOCFuture futureWithFailure:@0] thenValue:@""] isEqualToFuture:[TOCFuture futureWithFailure:@0]]); test([[[TOCFuture futureWithResult:@1] thenValue:@""] isEqualToFuture:[TOCFuture futureWithResult:@""]]); test([[TOCFutureSource new].future thenValue:@""].isIncomplete); } --(void)testFinallyTry { - test([[[TOCFuture futureWithResult:@1] finallyTry:^(TOCFuture* f) { return @""; }] isEqualToFuture:[TOCFuture futureWithResult:@""]]); - test([[[TOCFuture futureWithFailure:@0] finallyTry:^(TOCFuture* f) { return @""; }] isEqualToFuture:[TOCFuture futureWithResult:@""]]); - test([[TOCFutureSource new].future finallyTry:^(TOCFuture* f) { return @""; }].isIncomplete); - - test([[[TOCFuture futureWithResult:@1] finallyTry:^id(TOCFuture* f) { @throw @""; }] isEqualToFuture:[TOCFuture futureWithFailure:@""]]); - test([[[TOCFuture futureWithFailure:@0] finallyTry:^id(TOCFuture* f) { @throw @""; }] isEqualToFuture:[TOCFuture futureWithFailure:@""]]); - test([[TOCFutureSource new].future finallyTry:^id(TOCFuture* f) { @throw @""; }].isIncomplete); +- (void)testFinallyTry { + test([[[TOCFuture futureWithResult:@1] finallyTry:^(TOCFuture *f) { + return @""; + }] isEqualToFuture:[TOCFuture futureWithResult:@""]]); + test([[[TOCFuture futureWithFailure:@0] finallyTry:^(TOCFuture *f) { + return @""; + }] isEqualToFuture:[TOCFuture futureWithResult:@""]]); + test([[TOCFutureSource new] + .future finallyTry:^(TOCFuture *f) { + return @""; + }].isIncomplete); + + test([[[TOCFuture futureWithResult:@1] finallyTry:^id(TOCFuture *f) { + @throw @""; + }] isEqualToFuture:[TOCFuture futureWithFailure:@""]]); + test([[[TOCFuture futureWithFailure:@0] finallyTry:^id(TOCFuture *f) { + @throw @""; + }] isEqualToFuture:[TOCFuture futureWithFailure:@""]]); + test([[TOCFutureSource new] + .future finallyTry:^id(TOCFuture *f) { + @throw @""; + }].isIncomplete); } --(void)testThenTry { - test([[[TOCFuture futureWithResult:@1] thenTry:^(id f) { return @""; }] isEqualToFuture:[TOCFuture futureWithResult:@""]]); - test([[[TOCFuture futureWithFailure:@0] thenTry:^(id f) { return @""; }] isEqualToFuture:[TOCFuture futureWithFailure:@0]]); - test([[TOCFutureSource new].future thenTry:^(id f) { return @""; }].isIncomplete); - - test([[[TOCFuture futureWithResult:@1] thenTry:^id(id f) { @throw @""; }] isEqualToFuture:[TOCFuture futureWithFailure:@""]]); - test([[[TOCFuture futureWithFailure:@0] thenTry:^id(id f) { @throw @""; }] isEqualToFuture:[TOCFuture futureWithFailure:@0]]); - test([[TOCFutureSource new].future thenTry:^id(id f) { @throw @""; }].isIncomplete); +- (void)testThenTry { + test([[[TOCFuture futureWithResult:@1] thenTry:^(id f) { + return @""; + }] isEqualToFuture:[TOCFuture futureWithResult:@""]]); + test([[[TOCFuture futureWithFailure:@0] thenTry:^(id f) { + return @""; + }] isEqualToFuture:[TOCFuture futureWithFailure:@0]]); + test([[TOCFutureSource new] + .future thenTry:^(id f) { + return @""; + }].isIncomplete); + + test([[[TOCFuture futureWithResult:@1] thenTry:^id(id f) { + @throw @""; + }] isEqualToFuture:[TOCFuture futureWithFailure:@""]]); + test([[[TOCFuture futureWithFailure:@0] thenTry:^id(id f) { + @throw @""; + }] isEqualToFuture:[TOCFuture futureWithFailure:@0]]); + test([[TOCFutureSource new] + .future thenTry:^id(id f) { + @throw @""; + }].isIncomplete); } --(void)testCatchTry { - test([[[TOCFuture futureWithResult:@1] catchTry:^(id f) { return @""; }] isEqualToFuture:[TOCFuture futureWithResult:@1]]); - test([[[TOCFuture futureWithFailure:@0] catchTry:^(id f) { return @""; }] isEqualToFuture:[TOCFuture futureWithResult:@""]]); - test([[TOCFutureSource new].future catchTry:^(id f) { return @""; }].isIncomplete); - - test([[[TOCFuture futureWithResult:@1] catchTry:^id(id f) { @throw @""; }] isEqualToFuture:[TOCFuture futureWithResult:@1]]); - test([[[TOCFuture futureWithFailure:@0] catchTry:^id(id f) { @throw @""; }] isEqualToFuture:[TOCFuture futureWithFailure:@""]]); - test([[TOCFutureSource new].future catchTry:^id(id f) { @throw @""; }].isIncomplete); +- (void)testCatchTry { + test([[[TOCFuture futureWithResult:@1] catchTry:^(id f) { + return @""; + }] isEqualToFuture:[TOCFuture futureWithResult:@1]]); + test([[[TOCFuture futureWithFailure:@0] catchTry:^(id f) { + return @""; + }] isEqualToFuture:[TOCFuture futureWithResult:@""]]); + test([[TOCFutureSource new] + .future catchTry:^(id f) { + return @""; + }].isIncomplete); + + test([[[TOCFuture futureWithResult:@1] catchTry:^id(id f) { + @throw @""; + }] isEqualToFuture:[TOCFuture futureWithResult:@1]]); + test([[[TOCFuture futureWithFailure:@0] catchTry:^id(id f) { + @throw @""; + }] isEqualToFuture:[TOCFuture futureWithFailure:@""]]); + test([[TOCFutureSource new] + .future catchTry:^id(id f) { + @throw @""; + }].isIncomplete); } --(void) testRetry_pass { - __block NSUInteger repeat = 0; +- (void)testRetry_pass { + __block NSUInteger repeat = 0; __block NSUInteger evalCount = 0; - TOCUntilOperation op = ^(TOCCancelToken* c) { - repeat += 1; - return [TimeUtil scheduleEvaluate:^id{ evalCount++; return @YES; } - afterDelay:0.35 - onRunLoop:[ThreadManager normalLatencyThreadRunLoop] - unlessCancelled:c]; + TOCUntilOperation op = ^(TOCCancelToken *c) { + repeat += 1; + return [TimeUtil scheduleEvaluate:^id { + evalCount++; + return @YES; + } + afterDelay:0.35 + onRunLoop:[ThreadManager normalLatencyThreadRunLoop] + unlessCancelled:c]; }; - TOCFuture* f = [TOCFuture retry:op - upToNTimes:4 - withBaseTimeout:0.5/8 - andRetryFactor:2 - untilCancelled:nil]; + TOCFuture *f = [TOCFuture retry:op upToNTimes:4 withBaseTimeout:0.5 / 8 andRetryFactor:2 untilCancelled:nil]; testChurnUntil(!f.isIncomplete, 500.0); - + test(repeat == 3 || repeat == 4); test(evalCount == 1); test(f.hasResult); test([[f forceGetResult] isEqual:@YES]); } --(void) testRetry_fail { - __block NSUInteger repeat = 0; +- (void)testRetry_fail { + __block NSUInteger repeat = 0; __block NSUInteger evalCount = 0; - TOCUntilOperation op = ^(TOCCancelToken* c) { - repeat += 1; - return [TimeUtil scheduleEvaluate:^{ evalCount++; return [TOCFuture futureWithFailure:@13]; } - afterDelay:0.1 - onRunLoop:[ThreadManager normalLatencyThreadRunLoop] - unlessCancelled:c]; + TOCUntilOperation op = ^(TOCCancelToken *c) { + repeat += 1; + return [TimeUtil scheduleEvaluate:^{ + evalCount++; + return [TOCFuture futureWithFailure:@13]; + } + afterDelay:0.1 + onRunLoop:[ThreadManager normalLatencyThreadRunLoop] + unlessCancelled:c]; }; - TOCFuture* f = [TOCFuture retry:op - upToNTimes:4 - withBaseTimeout:0.5/8 - andRetryFactor:2 - untilCancelled:nil]; + TOCFuture *f = [TOCFuture retry:op upToNTimes:4 withBaseTimeout:0.5 / 8 andRetryFactor:2 untilCancelled:nil]; testChurnUntil(!f.isIncomplete, 5.0); - + test(repeat >= 1); test(evalCount >= 1); test(f.hasFailed); test([f.forceGetFailure isEqual:@13]); } --(void) testRetry_timeout { - __block NSUInteger repeat = 0; +- (void)testRetry_timeout { + __block NSUInteger repeat = 0; __block NSUInteger evalCount = 0; - TOCUntilOperation op = ^(TOCCancelToken* c) { - repeat += 1; - return [TimeUtil scheduleEvaluate:^id{ evalCount++; return @YES; } - afterDelay:0.5 - onRunLoop:[ThreadManager normalLatencyThreadRunLoop] - unlessCancelled:c]; + TOCUntilOperation op = ^(TOCCancelToken *c) { + repeat += 1; + return [TimeUtil scheduleEvaluate:^id { + evalCount++; + return @YES; + } + afterDelay:0.5 + onRunLoop:[ThreadManager normalLatencyThreadRunLoop] + unlessCancelled:c]; }; - TOCFuture* f = [TOCFuture retry:op - upToNTimes:2 - withBaseTimeout:0.5/8 - andRetryFactor:2 - untilCancelled:nil]; + TOCFuture *f = [TOCFuture retry:op upToNTimes:2 withBaseTimeout:0.5 / 8 andRetryFactor:2 untilCancelled:nil]; testChurnUntil(!f.isIncomplete, 5.0); - + test(repeat == 2); test(evalCount == 0); test(f.hasFailedWithTimeout); } --(void) testRetry_cancel { - TOCCancelTokenSource* s = [TOCCancelTokenSource new]; - __block NSUInteger repeat = 0; +- (void)testRetry_cancel { + TOCCancelTokenSource *s = [TOCCancelTokenSource new]; + __block NSUInteger repeat = 0; __block NSUInteger evalCount = 0; - TOCUntilOperation op = ^(TOCCancelToken* c) { - repeat += 1; - [TimeUtil scheduleRun:^{ [s cancel]; } - afterDelay:0.1 - onRunLoop:[ThreadManager normalLatencyThreadRunLoop] - unlessCancelled:nil]; - return [TimeUtil scheduleEvaluate:^id{ evalCount++; return @YES; } - afterDelay:0.5 - onRunLoop:[ThreadManager normalLatencyThreadRunLoop] - unlessCancelled:c]; + TOCUntilOperation op = ^(TOCCancelToken *c) { + repeat += 1; + [TimeUtil scheduleRun:^{ + [s cancel]; + } + afterDelay:0.1 + onRunLoop:[ThreadManager normalLatencyThreadRunLoop] + unlessCancelled:nil]; + return [TimeUtil scheduleEvaluate:^id { + evalCount++; + return @YES; + } + afterDelay:0.5 + onRunLoop:[ThreadManager normalLatencyThreadRunLoop] + unlessCancelled:c]; }; - TOCFuture* f = [TOCFuture retry:op - upToNTimes:2 - withBaseTimeout:0.5/8 - andRetryFactor:2 - untilCancelled:s.token]; + TOCFuture *f = [TOCFuture retry:op upToNTimes:2 withBaseTimeout:0.5 / 8 andRetryFactor:2 untilCancelled:s.token]; testChurnUntil(!f.isIncomplete, 5.0); - + test(repeat == 2); test(evalCount == 0); test(f.hasFailedWithCancel); diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index f477985ef..609cbd1a7 100644 Binary files a/Signal/translations/en.lproj/Localizable.strings and b/Signal/translations/en.lproj/Localizable.strings differ