From bbde7cd2a85b5daa755ed2929babe48060ef00a9 Mon Sep 17 00:00:00 2001 From: Frederic Jacobs Date: Tue, 1 Sep 2015 19:22:08 +0200 Subject: [PATCH] iOS 9 Support - Fixing size classes rendering bugs. - Supporting native iOS San Francisco font. - Quick Reply - Settings now slide to the left as suggested in original designed opposed to modal. - Simplification of restraints on many screens. - Full-API compatiblity with iOS 9 and iOS 8 legacy support. - Customized AddressBook Permission prompt when restrictions are enabled. If user installed Signal previously and already approved access to Contacts, don't bugg him again. - Fixes crash in migration for users who installed Signal <2.1.3 but hadn't signed up yet. - Xcode 7 / iOS 9 Travis Support - Bitcode Support is disabled until it is better understood how exactly optimizations are performed. In a first time, we will split out the crypto code into a separate binary to make it easier to optimize the non-sensitive code. Blog post with more details coming. - Partial ATS support. We are running our own Certificate Authority at Open Whisper Systems. Signal is doing certificate pinning to verify that certificates were signed by our own CA. Unfortunately Apple's App Transport Security requires to hand over chain verification to their framework with no control over the trust store. We have filed a radar to get ATS features with pinned certificates. In the meanwhile, ATS is disabled on our domain. We also followed Amazon's recommendations for our S3 domain we use to upload/download attachments. (#891) - Implement a unified `AFSecurityOWSPolicy` pinning strategy accross libraries (AFNetworking RedPhone/TextSecure & SocketRocket). --- .travis.yml | 10 +- .../spandsp/spandsp.xcodeproj/project.pbxproj | 3 +- .../xcshareddata/xcschemes/spandsp.xcscheme | 13 +- .../speex/speex.xcodeproj/project.pbxproj | 3 +- .../xcshareddata/xcschemes/speex.xcscheme | 13 +- Podfile | 13 +- Podfile.lock | 88 +- Pods | 2 +- Signal.xcodeproj/project.pbxproj | 77 +- .../xcshareddata/xcschemes/Signal.xcscheme | 13 +- .../xcshareddata/Signal.xcscmblueprint | 30 + Signal/Fonts/HelveticaNeueLTStd-Bd.otf | Bin 20816 -> 0 bytes Signal/Fonts/HelveticaNeueLTStd-Lt.otf | Bin 28120 -> 0 bytes Signal/Fonts/HelveticaNeueLTStd-Md.otf | Bin 28260 -> 0 bytes Signal/Fonts/HelveticaNeueLTStd-Th.otf | Bin 28124 -> 0 bytes Signal/Signal-Info.plist | 37 +- Signal/Signal-Prefix.pch | 2 + Signal/src/AppDelegate.h | 1 - Signal/src/AppDelegate.m | 38 +- Signal/src/Storyboard/Storyboard.storyboard | 3627 +++-------------- Signal/src/contact/ContactsManager.m | 58 +- Signal/src/environment/Environment.h | 2 + Signal/src/environment/Environment.m | 1 - Signal/src/environment/VersionMigrations.m | 6 +- Signal/src/environment/iOSVersions.h | 8 + Signal/src/network/AFSecurityOWSPolicy.h | 16 + Signal/src/network/AFSecurityOWSPolicy.m | 100 + Signal/src/network/PushManager.h | 8 +- Signal/src/network/PushManager.m | 115 +- .../network/http/RPServerRequestsManager.m | 10 +- .../TSInvalidIdentityKeySendingErrorMessage.m | 2 +- .../Messages/TSMessagesManager+attachments.m | 2 +- .../Messages/TSMessagesManager+sendMessages.h | 7 +- .../Messages/TSMessagesManager+sendMessages.m | 97 +- .../textsecure/Messages/TSMessagesManager.m | 16 +- .../Network/API/Requests/TSRequest.m | 5 + .../textsecure/Network/API/TSNetworkManager.m | 14 +- .../Network/WebSockets/TSSocketManager.m | 8 +- Signal/src/util/UIFont+OWS.m | 16 +- .../CodeVerificationViewController.m | 216 +- .../view controllers/InCallViewController.h | 3 +- .../view controllers/InCallViewController.m | 54 +- .../src/view controllers/InboxTableViewCell.h | 7 +- .../src/view controllers/InboxTableViewCell.m | 34 +- .../view controllers/MessagesViewController.m | 10 +- .../SettingsTableViewController.m | 2 + .../UITests/SignalsViewController.h | 2 + .../UITests/SignalsViewController.m | 15 +- .../Supporting Files/SignalTests-Info.plist | 2 +- .../translations/en.lproj/Localizable.strings | Bin 28654 -> 29428 bytes 50 files changed, 1214 insertions(+), 3592 deletions(-) create mode 100644 Signal.xcworkspace/xcshareddata/Signal.xcscmblueprint delete mode 100644 Signal/Fonts/HelveticaNeueLTStd-Bd.otf delete mode 100755 Signal/Fonts/HelveticaNeueLTStd-Lt.otf delete mode 100755 Signal/Fonts/HelveticaNeueLTStd-Md.otf delete mode 100755 Signal/Fonts/HelveticaNeueLTStd-Th.otf create mode 100644 Signal/src/network/AFSecurityOWSPolicy.h create mode 100644 Signal/src/network/AFSecurityOWSPolicy.m diff --git a/.travis.yml b/.travis.yml index 70ed0a9cb..254cb71e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,12 @@ language: objective-c -osx_image: beta-xcode6.3 -xcode_sdk: iphonesimulator8.3 + +osx_image: xcode7 +xcode_sdk: iphonesimulator9.0 + +before_install: + - brew update + - brew uninstall xctool && brew install --HEAD xctool install: true + xcode_workspace: Signal.xcworkspace xcode_scheme: Signal diff --git a/Libraries/spandsp/spandsp/spandsp.xcodeproj/project.pbxproj b/Libraries/spandsp/spandsp/spandsp.xcodeproj/project.pbxproj index 313cb11c7..a3fa5d60e 100644 --- a/Libraries/spandsp/spandsp/spandsp.xcodeproj/project.pbxproj +++ b/Libraries/spandsp/spandsp/spandsp.xcodeproj/project.pbxproj @@ -642,7 +642,7 @@ A1B9895C1725EC1300B6E8B5 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0500; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Twisted Oak Studios"; }; buildConfigurationList = A1B9895F1725EC1300B6E8B5 /* Build configuration list for PBXProject "spandsp" */; @@ -686,6 +686,7 @@ CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; diff --git a/Libraries/spandsp/spandsp/spandsp.xcodeproj/xcshareddata/xcschemes/spandsp.xcscheme b/Libraries/spandsp/spandsp/spandsp.xcodeproj/xcshareddata/xcschemes/spandsp.xcscheme index 8e596736e..d3775c9d2 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 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> + + + shouldUseLaunchSchemeArgsEnv = "YES"> + + 1.0.204' +pod 'OpenSSL', '~> 1.0.204.1' pod 'libPhoneNumber-iOS', '~> 0.8.7' -pod 'AxolotlKit', '~> 0.7' +pod 'AxolotlKit' pod 'PastelogKit', '~> 1.3' pod 'TwistedOakCollapsingFutures','~> 1.0' -pod 'AFNetworking', '~> 2.5.4' +pod 'AFNetworking', '~> 2.6' pod 'Mantle', '~> 2.0.4' pod 'FFCircularProgressView', '~> 0.5' pod 'SCWaveformView', '~> 1.0' -pod 'YapDatabase/SQLCipher', '~> 2.7' +pod 'YapDatabase/SQLCipher', '~> 2.7.2' pod 'iRate', '~> 1.11' pod 'SSKeychain' pod 'DJWActionSheet' -pod 'SocketRocket', :git => 'https://github.com/FredericJacobs/SocketRocket.git', :commit => 'f1567f1be7ce49ecf2c9d284ead8ea7c422ee99b' +pod 'SocketRocket', :git => 'https://github.com/FredericJacobs/SocketRocket.git', :commit => 'dd7e47fed78214785d7c032081da94008335fc35' pod 'JSQMessagesViewController', :git => 'https://github.com/WhisperSystems/JSQMessagesViewController', :commit => 'e5582fef8a6b3e35f8070361ef37237222da712b' pod 'APDropDownNavToolbar', :git => 'https://github.com/corbett/APDropDownNavToolbar.git', :branch => 'master' diff --git a/Podfile.lock b/Podfile.lock index 41d891134..66df2574b 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,24 +1,24 @@ PODS: - - 25519 (2.0.1) - - AFNetworking (2.5.4): - - AFNetworking/NSURLConnection (= 2.5.4) - - AFNetworking/NSURLSession (= 2.5.4) - - AFNetworking/Reachability (= 2.5.4) - - AFNetworking/Security (= 2.5.4) - - AFNetworking/Serialization (= 2.5.4) - - AFNetworking/UIKit (= 2.5.4) - - AFNetworking/NSURLConnection (2.5.4): + - 25519 (2.0.2) + - AFNetworking (2.6.1): + - AFNetworking/NSURLConnection (= 2.6.1) + - AFNetworking/NSURLSession (= 2.6.1) + - AFNetworking/Reachability (= 2.6.1) + - AFNetworking/Security (= 2.6.1) + - AFNetworking/Serialization (= 2.6.1) + - AFNetworking/UIKit (= 2.6.1) + - AFNetworking/NSURLConnection (2.6.1): - AFNetworking/Reachability - AFNetworking/Security - AFNetworking/Serialization - - AFNetworking/NSURLSession (2.5.4): + - AFNetworking/NSURLSession (2.6.1): - AFNetworking/Reachability - AFNetworking/Security - AFNetworking/Serialization - - AFNetworking/Reachability (2.5.4) - - AFNetworking/Security (2.5.4) - - AFNetworking/Serialization (2.5.4) - - AFNetworking/UIKit (2.5.4): + - AFNetworking/Reachability (2.6.1) + - AFNetworking/Security (2.6.1) + - AFNetworking/Serialization (2.6.1) + - AFNetworking/UIKit (2.6.1): - AFNetworking/NSURLConnection - AFNetworking/NSURLSession - APDropDownNavToolbar (1.1) @@ -26,13 +26,13 @@ PODS: - 25519 (~> 2.0.1) - HKDFKit (~> 0.0.3) - ProtocolBuffers (~> 1.9.8) - - CocoaLumberjack (2.0.1): - - CocoaLumberjack/Default (= 2.0.1) - - CocoaLumberjack/Extensions (= 2.0.1) - - CocoaLumberjack/Core (2.0.1) - - CocoaLumberjack/Default (2.0.1): + - CocoaLumberjack (2.2.0): + - CocoaLumberjack/Default (= 2.2.0) + - CocoaLumberjack/Extensions (= 2.2.0) + - CocoaLumberjack/Core (2.2.0) + - CocoaLumberjack/Default (2.2.0): - CocoaLumberjack/Core - - CocoaLumberjack/Extensions (2.0.1): + - CocoaLumberjack/Extensions (2.2.0): - CocoaLumberjack/Default - DJWActionSheet (1.0.4) - FFCircularProgressView (0.5) @@ -41,16 +41,16 @@ PODS: - JSQMessagesViewController (7.1.0): - JSQSystemSoundPlayer (~> 2.0.1) - JSQSystemSoundPlayer (2.0.1) - - libPhoneNumber-iOS (0.8.7) - - Mantle (2.0.4): - - Mantle/extobjc (= 2.0.4) - - Mantle/extobjc (2.0.4) - - OpenSSL (1.0.204) + - libPhoneNumber-iOS (0.8.8) + - Mantle (2.0.5): + - Mantle/extobjc (= 2.0.5) + - Mantle/extobjc (2.0.5) + - OpenSSL (1.0.204.1) - PastelogKit (1.3): - CocoaLumberjack (~> 2.0) - - ProtocolBuffers (1.9.8) + - ProtocolBuffers (1.9.9.1) - SCWaveformView (1.0.0) - - SocketRocket (0.3.1-beta2) + - SocketRocket (0.4.2) - SQLCipher/common (3.1.0) - SQLCipher/fts (3.1.0): - SQLCipher/common @@ -58,15 +58,15 @@ PODS: - TwistedOakCollapsingFutures (1.0.0): - UnionFind (~> 1.0) - UnionFind (1.0.1) - - YapDatabase/SQLCipher (2.7.1): + - YapDatabase/SQLCipher (2.7.3): - CocoaLumberjack (~> 2) - SQLCipher/fts DEPENDENCIES: - - AFNetworking (~> 2.5.4) + - AFNetworking (~> 2.6) - APDropDownNavToolbar (from `https://github.com/corbett/APDropDownNavToolbar.git`, branch `master`) - - AxolotlKit (~> 0.7) + - AxolotlKit - DJWActionSheet - FFCircularProgressView (~> 0.5) - iRate (~> 1.11) @@ -74,14 +74,14 @@ DEPENDENCIES: commit `e5582fef8a6b3e35f8070361ef37237222da712b`) - libPhoneNumber-iOS (~> 0.8.7) - Mantle (~> 2.0.4) - - OpenSSL (~> 1.0.204) + - OpenSSL (~> 1.0.204.1) - PastelogKit (~> 1.3) - SCWaveformView (~> 1.0) - SocketRocket (from `https://github.com/FredericJacobs/SocketRocket.git`, commit - `f1567f1be7ce49ecf2c9d284ead8ea7c422ee99b`) + `dd7e47fed78214785d7c032081da94008335fc35`) - SSKeychain - TwistedOakCollapsingFutures (~> 1.0) - - YapDatabase/SQLCipher (~> 2.7) + - YapDatabase/SQLCipher (~> 2.7.2) EXTERNAL SOURCES: APDropDownNavToolbar: @@ -91,7 +91,7 @@ EXTERNAL SOURCES: :commit: e5582fef8a6b3e35f8070361ef37237222da712b :git: https://github.com/WhisperSystems/JSQMessagesViewController SocketRocket: - :commit: f1567f1be7ce49ecf2c9d284ead8ea7c422ee99b + :commit: dd7e47fed78214785d7c032081da94008335fc35 :git: https://github.com/FredericJacobs/SocketRocket.git CHECKOUT OPTIONS: @@ -102,32 +102,32 @@ CHECKOUT OPTIONS: :commit: e5582fef8a6b3e35f8070361ef37237222da712b :git: https://github.com/WhisperSystems/JSQMessagesViewController SocketRocket: - :commit: f1567f1be7ce49ecf2c9d284ead8ea7c422ee99b + :commit: dd7e47fed78214785d7c032081da94008335fc35 :git: https://github.com/FredericJacobs/SocketRocket.git SPEC CHECKSUMS: - '25519': cd3f6f0658ac9dd4f95d7fb906378e1d0649c46c - AFNetworking: 05edc0ac4c4c8cf57bcf4b84be5b0744b6d8e71e + '25519': dc4bad7e2dbcbf1efa121068a705a44cd98c80fc + AFNetworking: 8e4e60500beb8bec644cf575beee72990a76d399 APDropDownNavToolbar: 5d0c3f363208543d20e86ddb4630927c28cdfd4b AxolotlKit: 8652fca51f4bc8225cbda791b0026c21e912b694 - CocoaLumberjack: 019d1361244274a6138c788c6cb80baabc13fb8f + CocoaLumberjack: 17fe8581f84914d5d7e6360f7c70022b173c3ae0 DJWActionSheet: 2fe54b1298a7f0fe44462233752c76a530e0cd80 FFCircularProgressView: 683a4ab1e1bd613246a3dffa61503ffdebcde8d8 HKDFKit: c058305d6f64b84f28c50bd7aa89574625bcb62a iRate: 599ed07c854e0695f3c605d1b2a64c67d912acb7 JSQMessagesViewController: ca11f86fa68ca70835f05e169df9244147c1dc40 JSQSystemSoundPlayer: c5850e77a4363ffd374cd851154b9af93264ed8d - libPhoneNumber-iOS: 1bccd3288375d954b0b904e26061cecaa0fb83d6 - Mantle: 6bee68168423948be0c0c5924832bf3af188e099 - OpenSSL: 576b352e6e6e60793ca133c6785736e3cbc31a09 + libPhoneNumber-iOS: fe877b7c44c270a9da2082d3e2892d5316f6a2f9 + Mantle: 1912395033f601de5adc8ee91e48f46e4c7051ad + OpenSSL: 7f853fcada78e5162c2183b4d90ebbd0aa02f5ac PastelogKit: 7b475be4cf577713506a943dd940bcc0499c8bca - ProtocolBuffers: 9a4a171c0c7cc8f21dd29aeca4f9ac775d84a880 + ProtocolBuffers: 1aac782c597fd7b95c5d278df55c34bff2937909 SCWaveformView: 52a96750255d817e300565a80c81fb643e233e07 - SocketRocket: 70df1983148525857ced17c57207bfb939bc6b8e + SocketRocket: ffe08119b00ef982f6c37052a4705a057c8494ad SQLCipher: c44fcca49c31483c2489cfb79aa7a69407f3794a SSKeychain: 3f42991739c6c60a9cf1bbd4dff6c0d3694bcf3d TwistedOakCollapsingFutures: f359b90f203e9ab13dfb92c9ff41842a7fe1cd0c UnionFind: c33be5adb12983981d6e827ea94fc7f9e370f52d - YapDatabase: e9ff9a189e99268a331575411e8462e4c6df2bc3 + YapDatabase: 6d6a30e97face6c3158830823c27614afe83e1e0 COCOAPODS: 0.38.2 diff --git a/Pods b/Pods index 1101c9b71..e7975283f 160000 --- a/Pods +++ b/Pods @@ -1 +1 @@ -Subproject commit 1101c9b712ac694978812826833de1177e71a7a4 +Subproject commit e7975283fc4cca612967198d5c749e1700d0c78b diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index c03665dd8..7c66a38e7 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ 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 */; }; + 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 */; }; @@ -16,9 +19,6 @@ 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 */; }; - 765052AA18294C9F008313E1 /* HelveticaNeueLTStd-Lt.otf in Resources */ = {isa = PBXBuildFile; fileRef = 765052A518294C9F008313E1 /* HelveticaNeueLTStd-Lt.otf */; }; - 765052AC18294C9F008313E1 /* HelveticaNeueLTStd-Md.otf in Resources */ = {isa = PBXBuildFile; fileRef = 765052A618294C9F008313E1 /* HelveticaNeueLTStd-Md.otf */; }; - 765052B3182BF839008313E1 /* HelveticaNeueLTStd-Th.otf in Resources */ = {isa = PBXBuildFile; fileRef = 765052B1182BF839008313E1 /* HelveticaNeueLTStd-Th.otf */; }; 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 */; }; @@ -223,6 +223,7 @@ 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 */; }; @@ -280,7 +281,7 @@ 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 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8313AE91B4954215858A5662 /* libPods.a */; }; + 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 */; }; @@ -307,6 +308,7 @@ 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 */; settings = {ASSET_TAGS = (); }; }; 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 */; }; @@ -409,7 +411,6 @@ 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 */; }; - B96A3100187DA1B600648F3E /* HelveticaNeueLTStd-Bd.otf in Resources */ = {isa = PBXBuildFile; fileRef = B96A30FE187DA1B600648F3E /* HelveticaNeueLTStd-Bd.otf */; }; 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 */; }; @@ -436,6 +437,7 @@ 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 */; }; @@ -444,10 +446,6 @@ E1370BE418A0686C00826894 /* outring.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = E18AB40B18A05754001A532A /* outring.mp3 */; }; E1370BE518A0686C00826894 /* r.caf in Resources */ = {isa = PBXBuildFile; fileRef = E18AB40C18A05754001A532A /* r.caf */; }; E1370BE618A0686C00826894 /* sonarping.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = E18AB40D18A05754001A532A /* sonarping.mp3 */; }; - E148751218A06AFD002CC4F3 /* HelveticaNeueLTStd-Bd.otf in Resources */ = {isa = PBXBuildFile; fileRef = B96A30FE187DA1B600648F3E /* HelveticaNeueLTStd-Bd.otf */; }; - E148751318A06AFD002CC4F3 /* HelveticaNeueLTStd-Th.otf in Resources */ = {isa = PBXBuildFile; fileRef = 765052B1182BF839008313E1 /* HelveticaNeueLTStd-Th.otf */; }; - E148751418A06AFD002CC4F3 /* HelveticaNeueLTStd-Lt.otf in Resources */ = {isa = PBXBuildFile; fileRef = 765052A518294C9F008313E1 /* HelveticaNeueLTStd-Lt.otf */; }; - E148751518A06AFD002CC4F3 /* HelveticaNeueLTStd-Md.otf in Resources */ = {isa = PBXBuildFile; fileRef = 765052A618294C9F008313E1 /* HelveticaNeueLTStd-Md.otf */; }; 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 */; }; @@ -473,7 +471,6 @@ E197B62418BBF5BB00F073E5 /* SoundPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B62318BBF5BB00F073E5 /* SoundPlayer.m */; }; E197B62718BBF63B00F073E5 /* SoundBoard.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B62618BBF63B00F073E5 /* SoundBoard.m */; }; E1CD329618BCFF9900B1A496 /* SoundInstance.m in Sources */ = {isa = PBXBuildFile; fileRef = E1CD329518BCFF9900B1A496 /* SoundInstance.m */; }; - F995AC2FFD6D4442B012604A /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8313AE91B4954215858A5662 /* libPods.a */; }; FC31962A1A067D8F0094C78E /* MessageComposeTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FC3196291A067D8F0094C78E /* MessageComposeTableViewController.m */; }; FC31962D1A06A2190094C78E /* FingerprintViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FC31962C1A06A2190094C78E /* FingerprintViewController.m */; }; FC3196301A0814130094C78E /* SettingsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FC31962F1A0814130094C78E /* SettingsTableViewController.m */; }; @@ -555,9 +552,6 @@ 70BAFD5B190584BE00FA5E0B /* NotificationTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotificationTracker.h; sourceTree = ""; }; 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 = ""; }; - 765052A518294C9F008313E1 /* HelveticaNeueLTStd-Lt.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "HelveticaNeueLTStd-Lt.otf"; sourceTree = ""; }; - 765052A618294C9F008313E1 /* HelveticaNeueLTStd-Md.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "HelveticaNeueLTStd-Md.otf"; sourceTree = ""; }; - 765052B1182BF839008313E1 /* HelveticaNeueLTStd-Th.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "HelveticaNeueLTStd-Th.otf"; 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; }; @@ -773,7 +767,6 @@ 76EB051018170B33006006FC /* NextResponderScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NextResponderScrollView.m; sourceTree = ""; }; 76EB052E18170B33006006FC /* ContactTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactTableViewCell.h; sourceTree = ""; }; 76EB052F18170B33006006FC /* ContactTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactTableViewCell.m; sourceTree = ""; }; - 8313AE91B4954215858A5662 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 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; }; @@ -883,6 +876,8 @@ 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 = ""; }; 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 = ""; }; @@ -1095,7 +1090,6 @@ 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 = ""; }; - B96A30FE187DA1B600648F3E /* HelveticaNeueLTStd-Bd.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "HelveticaNeueLTStd-Bd.otf"; sourceTree = ""; }; B97940251832BD2400BD66CB /* UIUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIUtil.h; sourceTree = ""; }; B97940261832BD2400BD66CB /* UIUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIUtil.m; sourceTree = ""; }; B97CBFA518860EA3008E0DE9 /* CountryCodeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CountryCodeViewController.h; sourceTree = ""; }; @@ -1121,6 +1115,7 @@ 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 = ""; }; @@ -1252,7 +1247,7 @@ D221A090169C9E5E00537ABF /* Foundation.framework in Frameworks */, D221A0E8169DFFC500537ABF /* AVFoundation.framework in Frameworks */, D24B5BD5169F568C00681372 /* AudioToolbox.framework in Frameworks */, - F995AC2FFD6D4442B012604A /* libPods.a in Frameworks */, + 28508611F3DF531CEDF5103D /* libPods.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1275,7 +1270,11 @@ D202868116DBE0E7009068E9 /* CFNetwork.framework in Frameworks */, D221A0AD169C9E5F00537ABF /* UIKit.framework in Frameworks */, D221A0AE169C9E5F00537ABF /* Foundation.framework in Frameworks */, - AA0C8E498E2046B0B81EEE6E /* libPods.a in Frameworks */, + AA0C8E498E2046B0B81EEE6E /* (null) in Frameworks */, + 53EF5134D8FB5FCBDEDE2A35 /* (null) in Frameworks */, + DE9907A5A8074160B34A8261 /* (null) in Frameworks */, + 7FAA7C04BD50D54101D1BB1A /* (null) in Frameworks */, + 057B54FA6208D8269CFE6146 /* libPods.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1322,17 +1321,6 @@ path = crypto; sourceTree = ""; }; - 765052A318294C9F008313E1 /* Fonts */ = { - isa = PBXGroup; - children = ( - B96A30FE187DA1B600648F3E /* HelveticaNeueLTStd-Bd.otf */, - 765052B1182BF839008313E1 /* HelveticaNeueLTStd-Th.otf */, - 765052A518294C9F008313E1 /* HelveticaNeueLTStd-Lt.otf */, - 765052A618294C9F008313E1 /* HelveticaNeueLTStd-Md.otf */, - ); - path = Fonts; - sourceTree = ""; - }; 76919BF51805D169008C664A /* contact */ = { isa = PBXGroup; children = ( @@ -1433,6 +1421,8 @@ 76EB041D18170B33006006FC /* network */ = { isa = PBXGroup; children = ( + B63006411B9631EC00F2FEB5 /* AFSecurityOWSPolicy.h */, + B63006421B9631EC00F2FEB5 /* AFSecurityOWSPolicy.m */, 76EB041E18170B33006006FC /* dns */, 76EB042318170B33006006FC /* failures */, 76EB042818170B33006006FC /* http */, @@ -2482,7 +2472,7 @@ D221A08D169C9E5E00537ABF /* UIKit.framework */, D221A08F169C9E5E00537ABF /* Foundation.framework */, D221A091169C9E5E00537ABF /* CoreGraphics.framework */, - 8313AE91B4954215858A5662 /* libPods.a */, + D488327B732CFBE8349C7024 /* libPods.a */, ); name = Frameworks; sourceTree = ""; @@ -2492,7 +2482,6 @@ children = ( B657DDC91911A40500F45B0C /* Signal.entitlements */, B633C4FD1A1D190B0059AC12 /* Images */, - 765052A318294C9F008313E1 /* Fonts */, B67EBF5C19194AC60084CCFD /* Settings.bundle */, 76EB03C118170B33006006FC /* src */, D221A094169C9E5E00537ABF /* Supporting Files */, @@ -2726,7 +2715,7 @@ isa = PBXProject; attributes = { LastTestingUpgradeCheck = 0600; - LastUpgradeCheck = 0500; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Open Whisper Systems"; TargetAttributes = { D221A088169C9E5E00537ABF = { @@ -2872,12 +2861,8 @@ FC9120411A39EFB70074545C /* qr@2x.png in Resources */, E1370BE618A0686C00826894 /* sonarping.mp3 in Resources */, B10C9B5F1A7049EC00ECA2BF /* pause_icon.png in Resources */, - E148751218A06AFD002CC4F3 /* HelveticaNeueLTStd-Bd.otf in Resources */, AD83FF471A73428300B5C81A /* audio_play_button_blue.png in Resources */, AD83FF451A73426500B5C81A /* audio_pause_button@2x.png in Resources */, - E148751318A06AFD002CC4F3 /* HelveticaNeueLTStd-Th.otf in Resources */, - E148751418A06AFD002CC4F3 /* HelveticaNeueLTStd-Lt.otf in Resources */, - E148751518A06AFD002CC4F3 /* HelveticaNeueLTStd-Md.otf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2885,12 +2870,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - B96A3100187DA1B600648F3E /* HelveticaNeueLTStd-Bd.otf in Resources */, - 765052AC18294C9F008313E1 /* HelveticaNeueLTStd-Md.otf in Resources */, 76EB060118170B33006006FC /* InitiateSignal.proto in Resources */, - 765052AA18294C9F008313E1 /* HelveticaNeueLTStd-Lt.otf in Resources */, B6850E5A1995A4710068E715 /* whisperFake.cer in Resources */, - 765052B3182BF839008313E1 /* HelveticaNeueLTStd-Th.otf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3063,6 +3044,7 @@ 76EB061618170B33006006FC /* AnonymousOccurrenceLogger.m in Sources */, 76EB063018170B33006006FC /* Conversions.m in Sources */, 76EB065618170B34006006FC /* InCallViewController.m in Sources */, + B63006431B9631EC00F2FEB5 /* AFSecurityOWSPolicy.m in Sources */, B6B096681A1D25ED008BFAA6 /* TSRecipient.m in Sources */, 76EB05FE18170B33006006FC /* InitiateSignal.pb.m in Sources */, 76EB05CA18170B33006006FC /* RecipientUnavailable.m in Sources */, @@ -3475,6 +3457,8 @@ 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; @@ -3512,10 +3496,9 @@ GCC_WARN_UNUSED_VALUE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ""; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "-fobjc-arc-exceptions"; - PROVISIONING_PROFILE = ""; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; @@ -3543,6 +3526,7 @@ 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; @@ -3574,13 +3558,12 @@ GCC_WARN_UNUSED_VALUE = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ""; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = ( "-DNS_BLOCK_ASSERTIONS=1", "-fobjc-arc-exceptions", ); - PROVISIONING_PROFILE = ""; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; @@ -3629,10 +3612,9 @@ ); LLVM_LTO = NO; OTHER_LDFLAGS = "$(inherited)"; + PRODUCT_BUNDLE_IDENTIFIER = org.whispersystems.signal; PRODUCT_NAME = Signal; - PROVISIONING_PROFILE = ""; SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = 1; TEST_AFTER_BUILD = YES; VALID_ARCHS = "arm64 armv7 armv7s i386"; WRAPPER_EXTENSION = app; @@ -3682,10 +3664,9 @@ ); LLVM_LTO = NO; OTHER_LDFLAGS = "$(inherited)"; + PRODUCT_BUNDLE_IDENTIFIER = org.whispersystems.signal; PRODUCT_NAME = Signal; - PROVISIONING_PROFILE = ""; SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = 1; TEST_AFTER_BUILD = YES; VALID_ARCHS = "arm64 armv7 armv7s i386"; WRAPPER_EXTENSION = app; @@ -3734,6 +3715,7 @@ "-ObjC", "$(inherited)", ); + PRODUCT_BUNDLE_IDENTIFIER = "org.whispersystems.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = SignalTests; PROVISIONING_PROFILE = ""; TEST_HOST = "$(BUNDLE_LOADER)"; @@ -3783,6 +3765,7 @@ "-ObjC", "$(inherited)", ); + PRODUCT_BUNDLE_IDENTIFIER = "org.whispersystems.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = SignalTests; PROVISIONING_PROFILE = ""; TEST_HOST = "$(BUNDLE_LOADER)"; diff --git a/Signal.xcodeproj/xcshareddata/xcschemes/Signal.xcscheme b/Signal.xcodeproj/xcshareddata/xcschemes/Signal.xcscheme index 5abdfd2e9..b7415917d 100644 --- a/Signal.xcodeproj/xcshareddata/xcschemes/Signal.xcscheme +++ b/Signal.xcodeproj/xcshareddata/xcschemes/Signal.xcscheme @@ -1,6 +1,6 @@ + shouldUseLaunchSchemeArgsEnv = "NO"> @@ -55,15 +55,18 @@ isEnabled = "YES"> + + @@ -79,10 +82,10 @@ diff --git a/Signal.xcworkspace/xcshareddata/Signal.xcscmblueprint b/Signal.xcworkspace/xcshareddata/Signal.xcscmblueprint new file mode 100644 index 000000000..7fd52d4e1 --- /dev/null +++ b/Signal.xcworkspace/xcshareddata/Signal.xcscmblueprint @@ -0,0 +1,30 @@ +{ + "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "5D79A077E31B3FE97A3C6613CBFFDD71C314D14C", + "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { + + }, + "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { + "5D79A077E31B3FE97A3C6613CBFFDD71C314D14C" : 0, + "D74FB800F048CB516BB4BC70047F7CC676D291B9" : 0 + }, + "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "1D917339-756B-4BA2-8BAF-70AFEDF98BC0", + "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { + "5D79A077E31B3FE97A3C6613CBFFDD71C314D14C" : "Signal-iOS", + "D74FB800F048CB516BB4BC70047F7CC676D291B9" : "Signal-iOSPods" + }, + "DVTSourceControlWorkspaceBlueprintNameKey" : "Signal", + "DVTSourceControlWorkspaceBlueprintVersion" : 204, + "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "Signal.xcworkspace", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:WhisperSystems\/Signal-iOS.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "5D79A077E31B3FE97A3C6613CBFFDD71C314D14C" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:FredericJacobs\/Precompiled-Signal-Dependencies.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "D74FB800F048CB516BB4BC70047F7CC676D291B9" + } + ] +} \ No newline at end of file diff --git a/Signal/Fonts/HelveticaNeueLTStd-Bd.otf b/Signal/Fonts/HelveticaNeueLTStd-Bd.otf deleted file mode 100644 index de6e718344ea258f0ec4670798fa1f2ccc40a973..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20816 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 BZ2JHJ diff --git a/Signal/Fonts/HelveticaNeueLTStd-Lt.otf b/Signal/Fonts/HelveticaNeueLTStd-Lt.otf deleted file mode 100755 index 1b27e9f67dd3c10b48e7696bef0cb0dd80514094..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28120 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 diff --git a/Signal/Fonts/HelveticaNeueLTStd-Md.otf b/Signal/Fonts/HelveticaNeueLTStd-Md.otf deleted file mode 100755 index 08222549943d74fcf77879f640d6db2b41ad63e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28260 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 diff --git a/Signal/Fonts/HelveticaNeueLTStd-Th.otf b/Signal/Fonts/HelveticaNeueLTStd-Th.otf deleted file mode 100755 index 3217384301c9a18b143e6d64e62370e045bf3561..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28124 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%0DDNW=l1Iyv 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 diff --git a/Signal/Signal-Info.plist b/Signal/Signal-Info.plist index fb486ba6f..cd92f7661 100644 --- a/Signal/Signal-Info.plist +++ b/Signal/Signal-Info.plist @@ -12,10 +12,8 @@ CFBundleIcons - CFBundleIcons~ipad - CFBundleIdentifier - org.whispersystems.signal + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -23,7 +21,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 2.1.3 + 2.1.4 CFBundleSignature ???? CFBundleURLTypes @@ -40,7 +38,7 @@ CFBundleVersion - 2.1.80 + 2.1.90 LOGS_EMAIL support@whispersystems.org LOGS_URL @@ -49,17 +47,32 @@ public.app-category.social-networking LSRequiresIPhoneOS + NSAppTransportSecurity + + NSExceptionDomains + + amazonaws.com + + NSIncludesSubdomains + + NSThirdPartyExceptionMinimumTLSVersion + TLSv1.0 + NSThirdPartyExceptionRequiresForwardSecrecy + + + whispersystems.org + + NSExceptionAllowsInsecureHTTPLoads + + NSIncludesSubdomains + + + + NSContactsUsageDescription Signal uses your contacts to find users you know. We do not store your contacts on the server. NSMicrophoneUsageDescription Signal needs access to your microphone to make and receive phone calls. - UIAppFonts - - HelveticaNeueLTStd-Bd.otf - HelveticaNeueLTStd-Lt.otf - HelveticaNeueLTStd-Md.otf - HelveticaNeueLTStd-Th.otf - UIBackgroundModes audio diff --git a/Signal/Signal-Prefix.pch b/Signal/Signal-Prefix.pch index 2b6601300..4f389aa26 100644 --- a/Signal/Signal-Prefix.pch +++ b/Signal/Signal-Prefix.pch @@ -20,4 +20,6 @@ #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 ? block(__VA_ARGS__) : nil + #endif diff --git a/Signal/src/AppDelegate.h b/Signal/src/AppDelegate.h index c95e39340..a3f15e79d 100644 --- a/Signal/src/AppDelegate.h +++ b/Signal/src/AppDelegate.h @@ -5,7 +5,6 @@ @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; - @property (strong, nonatomic) SignalsViewController *signalVC; @end diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index a0a8b4af1..f95cefcd7 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -34,6 +34,10 @@ static NSString * const kURLHostVerifyPrefix = @"verify"; [AppStoreRating setupRatingLibrary]; } +- (void)applicationWillEnterForeground:(UIApplication *)application { + [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]; +} + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [self setupAppearance]; [[PushManager sharedManager] registerPushKitNotificationFuture]; @@ -162,20 +166,22 @@ static NSString * const kURLHostVerifyPrefix = @"verify"; } - (void)applicationWillResignActive:(UIApplication *)application { - [self protectScreen]; - - if ([TSAccountManager isRegistered]) { - [self updateBadge]; - [TSSocketManager resignActivity]; - } -} - -- (void)updateBadge { - if ([TSAccountManager isRegistered]) { - [[UIApplication sharedApplication] setApplicationIconBadgeNumber:1]; - [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]; - [[UIApplication sharedApplication] setApplicationIconBadgeNumber:(NSInteger)[[TSMessagesManager sharedManager] unreadMessagesCount]]; - } + UIBackgroundTaskIdentifier __block bgTask = UIBackgroundTaskInvalid; + bgTask = [application beginBackgroundTaskWithExpirationHandler:^{ + + }]; + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [self protectScreen]; + if ([TSAccountManager isRegistered]) { + [[[Environment getCurrent] signalsViewController] updateInboxCountLabel]; + [TSSocketManager resignActivity]; + } + + [application endBackgroundTask:bgTask]; + bgTask = UIBackgroundTaskInvalid; + }); + } - (void)prepareScreenshotProtection{ @@ -266,6 +272,10 @@ static NSString * const kURLHostVerifyPrefix = @"verify"; [[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]; +} + /** * Signal requires an iPhone to be unlocked after reboot to be able to access keying material. */ diff --git a/Signal/src/Storyboard/Storyboard.storyboard b/Signal/src/Storyboard/Storyboard.storyboard index de99ce76c..880ce2583 100755 --- a/Signal/src/Storyboard/Storyboard.storyboard +++ b/Signal/src/Storyboard/Storyboard.storyboard @@ -1,85 +1,61 @@ - + - - - + + - + - + - + + - - - - - - - - - - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -157,39 +85,40 @@ - + - + - - + + - + - + - + + @@ -203,14 +132,14 @@ - - - + + + - + @@ -221,87 +150,49 @@ - + - + - + - + - - + + - - - - - - - - - - - + + - - - - - - - - - - - - + @@ -360,175 +233,64 @@ A0 09 9A FF A8 8A 09 99 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + - - - - - - - - - - - + + - - - - - - - - - - - - + @@ -568,242 +321,54 @@ A0 09 9A FF A8 8A 09 99 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - + - - - - - - - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -820,8 +385,8 @@ A0 09 9A FF A8 8A 09 99 - - + + @@ -836,22 +401,27 @@ A0 09 9A FF A8 8A 09 99 - + - + - + + + + + + @@ -859,44 +429,27 @@ A0 09 9A FF A8 8A 09 99 + - + - + - + - - + + - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -991,73 +496,41 @@ A0 09 9A FF A8 8A 09 99 - + - + - + + - - - - - - - - - - - - - - - - - - @@ -1067,115 +540,63 @@ A0 09 9A FF A8 8A 09 99 - + - + - + - - + + - + + + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + + - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + + - - - - - - - - - - - - - - - + + + - - - + - + - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1839,12 +763,12 @@ A0 09 9A FF A8 8A 09 99 - + - + @@ -1853,6 +777,7 @@ A0 09 9A FF A8 8A 09 99 + @@ -1861,19 +786,21 @@ A0 09 9A FF A8 8A 09 99 - + - + - + + - + + @@ -1881,80 +808,42 @@ A0 09 9A FF A8 8A 09 99 + + + - - - - - - - - - - - - - - - - - - - - - - - - + @@ -1992,105 +881,67 @@ A0 09 9A FF A8 8A 09 99 - + - + - + - - - - + + + + + + - + - + + - - - - - - - - - - - - - - - - - - + - @@ -2098,157 +949,56 @@ A0 09 9A FF A8 8A 09 99 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + - - - - - - - - - - - - - + - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - + - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -2495,181 +1101,34 @@ A0 09 9A FF A8 8A 09 99 - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + - - - - - - - - - - - + + + + - - - - - - + - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2678,6 +1137,7 @@ A0 09 9A FF A8 8A 09 99 + @@ -2687,503 +1147,207 @@ A0 09 9A FF A8 8A 09 99 + - + - + - + - + - + + + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + + - + - - - - - - - - - - - - + + + - - - - - - - - - - - - - + - - - + - - - - - - - + + - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + + - - - - + - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -3477,21 +1437,23 @@ A0 09 9A FF A8 8A 09 99 - + - + + + @@ -3499,224 +1461,82 @@ A0 09 9A FF A8 8A 09 99 - - - - - - - - - - - - - - - - - - - - - - - + - + - + + - + + + + + - - - - - - - - - - - + - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -3724,474 +1544,187 @@ A0 09 9A FF A8 8A 09 99 + + + - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -4203,7 +1736,7 @@ A0 09 9A FF A8 8A 09 99 - + @@ -4227,7 +1760,7 @@ A0 09 9A FF A8 8A 09 99 - + @@ -4237,6 +1770,7 @@ A0 09 9A FF A8 8A 09 99 + @@ -4246,160 +1780,57 @@ A0 09 9A FF A8 8A 09 99 - + - + - + + - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -4424,7 +1855,7 @@ A0 09 9A FF A8 8A 09 99 - + @@ -4432,183 +1863,102 @@ A0 09 9A FF A8 8A 09 99 - + - + - + - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + - + - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - + + + + @@ -4617,59 +1967,26 @@ A0 09 9A FF A8 8A 09 99 + - - + - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -4679,7 +1996,7 @@ A0 09 9A FF A8 8A 09 99 - + @@ -4689,10 +2006,12 @@ A0 09 9A FF A8 8A 09 99 + + @@ -4700,7 +2019,7 @@ A0 09 9A FF A8 8A 09 99 - + @@ -4726,7 +2045,7 @@ A0 09 9A FF A8 8A 09 99 - + diff --git a/Signal/src/contact/ContactsManager.m b/Signal/src/contact/ContactsManager.m index 3e8cfb985..28a2e9961 100644 --- a/Signal/src/contact/ContactsManager.m +++ b/Signal/src/contact/ContactsManager.m @@ -113,17 +113,51 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in } + (void)blockingContactDialog{ - 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]; + 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]; + + 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]; + break; + } + + case kABAuthorizationStatusNotDetermined: { + DDLogInfo(@"AddressBook access not granted but status undetermined."); + [[Environment getCurrent].contactsManager pullLatestAddressBook]; + break; + } + + case kABAuthorizationStatusAuthorized:{ + DDLogInfo(@"AddressBook access not granted but status authorized."); + break; + } + + default: + break; + } } - (void)setupLatestRedPhoneUsers:(NSArray *)users { @@ -157,7 +191,7 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in id addressBook = (__bridge_transfer id)addressBookRef; ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef requestAccessError) { - if (granted) { + if (granted && ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) { dispatch_async(ADDRESSBOOK_QUEUE,^{ [futureAddressBookSource trySetResult:addressBook]; }); diff --git a/Signal/src/environment/Environment.h b/Signal/src/environment/Environment.h index 13ebfb377..45ba12129 100644 --- a/Signal/src/environment/Environment.h +++ b/Signal/src/environment/Environment.h @@ -6,6 +6,8 @@ #import "TSGroupModel.h" #import "TSStorageHeaders.h" +static NSString* const kCallSegue = @"2.0_6.0_Call_Segue"; + /** * * Environment is a data and data accessor class. diff --git a/Signal/src/environment/Environment.m b/Signal/src/environment/Environment.m index 74e460487..ecbce115c 100644 --- a/Signal/src/environment/Environment.m +++ b/Signal/src/environment/Environment.m @@ -12,7 +12,6 @@ #import "TSContactThread.h" #import "TSGroupThread.h" -static NSString* const kCallSegue = @"2.0_6.0_Call_Segue"; #define isRegisteredUserDefaultString @"isRegistered" static Environment* environment = nil; diff --git a/Signal/src/environment/VersionMigrations.m b/Signal/src/environment/VersionMigrations.m index a7cdf9b9c..86762a9ce 100644 --- a/Signal/src/environment/VersionMigrations.m +++ b/Signal/src/environment/VersionMigrations.m @@ -54,7 +54,7 @@ [self nonBlockingPushRegistration]; } - if ([self isVersion:previousVersion atLeast:@"2.0.0" andLessThan:@"2.1.70"] || [self needsRegisterAttributes]) { + if ([self isVersion:previousVersion atLeast:@"2.0.0" andLessThan:@"2.1.70"] && [TSAccountManager isRegistered]) { [self clearVideoCache]; [self blockingAttributesUpdate]; } @@ -83,7 +83,7 @@ DDLogWarn(@"Registered for VOIP Push."); } failure:failedBlock]; } failure:failedBlock]; - + } + (void)blockingPushRegistration{ @@ -146,7 +146,7 @@ #pragma mark Upgrading to 2.1.3 - Adding VOIP flag on TS Server + (BOOL)needsRegisterAttributes { - return [self userDefaultsBoolForKey:NEEDS_TO_REGISTER_ATTRIBUTES]; + return [self userDefaultsBoolForKey:NEEDS_TO_REGISTER_ATTRIBUTES] && [TSAccountManager isRegistered]; } + (void)blockingAttributesUpdate { diff --git a/Signal/src/environment/iOSVersions.h b/Signal/src/environment/iOSVersions.h index d11d7cb8a..5f0e0d447 100644 --- a/Signal/src/environment/iOSVersions.h +++ b/Signal/src/environment/iOSVersions.h @@ -93,6 +93,14 @@ #define _iOS_8_2_0 NSFoundationVersionNumber_iOS_8_2_0 #endif +#ifndef NSFoundationVersionNumber_iOS_9 +#define NSFoundationVersionNumber_iOS_9 1231 //extracted with NSLog(@"%f", NSFoundationVersionNumber) +#endif + +#ifdef NSFoundationVersionNumber_iOS_9 +#define _iOS_9 NSFoundationVersionNumber_iOS_9 +#endif + /** Add a Singelton implementation to the .m File */ diff --git a/Signal/src/network/AFSecurityOWSPolicy.h b/Signal/src/network/AFSecurityOWSPolicy.h new file mode 100644 index 000000000..85e104510 --- /dev/null +++ b/Signal/src/network/AFSecurityOWSPolicy.h @@ -0,0 +1,16 @@ +// +// 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 new file mode 100644 index 000000000..7607ae249 --- /dev/null +++ b/Signal/src/network/AFSecurityOWSPolicy.m @@ -0,0 +1,100 @@ +// +// 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/PushManager.h b/Signal/src/network/PushManager.h index fa094ef32..7095a3399 100644 --- a/Signal/src/network/PushManager.h +++ b/Signal/src/network/PushManager.h @@ -10,6 +10,8 @@ #import #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_Accept_Identifier @"Signal_Call_Accept" @@ -18,10 +20,10 @@ #define Signal_CallBack_Identifier @"Signal_CallBack" #define Signal_Call_Category @"Signal_IncomingCall" -#define Signal_Message_Category @"Signal_Message" +#define Signal_Full_New_Message_Category @"Signal_Full_New_Message" #define Signal_CallBack_Category @"Signal_CallBack" -#define Signal_Message_View_Identifier @"Signal_Message_Read" +#define Signal_Message_Reply_Identifier @"Signal_New_Message_Reply" #define Signal_Message_MarkAsRead_Identifier @"Signal_Message_MarkAsRead" typedef void(^failedPushRegistrationBlock)(NSError *error); @@ -71,6 +73,7 @@ typedef void (^registrationTokensSuccessBlock)(NSData *pushToken, NSData *voipTo -(TOCFuture*)registerPushKitNotificationFuture; - (BOOL)supportsVOIPPush; - (UILocalNotification*)closeVOIPBackgroundTask; +- (void)presentNotification:(UILocalNotification*)notification; #pragma mark Push Notifications Delegate Methods @@ -78,5 +81,6 @@ typedef void (^registrationTokensSuccessBlock)(NSData *pushToken, NSData *voipTo - (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; @end diff --git a/Signal/src/network/PushManager.m b/Signal/src/network/PushManager.m index f33bbe2e6..bfbb53eed 100644 --- a/Signal/src/network/PushManager.m +++ b/Signal/src/network/PushManager.m @@ -8,8 +8,11 @@ #import +#import "AppDelegate.h" #import "ContactsManager.h" #import "InCallViewController.h" +#import "NSDate+millisecondTimeStamp.h" +#import "TSMessagesManager+sendMessages.h" #import "NotificationTracker.h" #import "PreferencesUtil.h" @@ -25,8 +28,9 @@ @property UIAlertView *missingPermissionsAlertView; @property (nonatomic, strong) NotificationTracker *notificationTracker; @property UILocalNotification *lastCallNotification; - +@property (nonatomic, retain) NSMutableArray *currentNotifications; @property (nonatomic) UIBackgroundTaskIdentifier callBackgroundTask; + @end @implementation PushManager @@ -53,6 +57,7 @@ cancelButtonTitle:NSLocalizedString(@"OK", @"") otherButtonTitles:nil, nil]; _callBackgroundTask = UIBackgroundTaskInvalid; + self.currentNotifications = [NSMutableArray array]; } return self; } @@ -99,7 +104,7 @@ notification.category = Signal_Call_Category; notification.soundName = @"r.caf"; - [[UIApplication sharedApplication] presentLocalNotificationNow:notification]; + [[PushManager sharedManager] presentNotification:notification]; _lastCallNotification = notification; if (_callBackgroundTask == UIBackgroundTaskInvalid) { @@ -143,15 +148,36 @@ } - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { - if ([notification.category isEqualToString:Signal_Message_Category]) { - NSString *threadId = [notification.userInfo objectForKey:Signal_Thread_UserInfo_Key]; + NSString *threadId = notification.userInfo[Signal_Thread_UserInfo_Key]; + if (threadId && [TSThread fetchObjectWithUniqueID:threadId]) { [Environment messageThreadId:threadId]; } } - (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 { - if ([identifier isEqualToString:Signal_Call_Accept_Identifier]) { + + 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]; + } 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(); @@ -163,20 +189,37 @@ completionHandler(); }); } else if([identifier isEqualToString:Signal_CallBack_Identifier]){ - NSString * contactId = [notification.userInfo objectForKeyedSubscript:Signal_Call_UserInfo_Key]; + 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{ - NSString *threadId = [notification.userInfo objectForKey:Signal_Thread_UserInfo_Key]; + } 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 { + 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(); + }]; } - (BOOL)isRedPhonePush:(NSDictionary*)pushDict { - NSDictionary *aps = [pushDict objectForKey:@"aps"]; - NSString *category = [aps objectForKey:@"category"]; + NSDictionary *aps = pushDict[@"aps"]; + NSString *category = aps[@"category"]; if ([category isEqualToString:Signal_Call_Category]) { return YES; @@ -294,7 +337,7 @@ NSError *error; NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:&error]; - NSString *tsToken = [dictionary objectForKey:@"token"]; + NSString *tsToken = dictionary[@"token"]; if (!tsToken || !pushToken || error) { failure(error); @@ -315,25 +358,37 @@ UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationType)[self allNotificationTypes] categories:[NSSet setWithObjects:[self userNotificationsCallCategory], - [self userNotificationsMessageCategory], + [self fullNewMessageNotificationCategory], [self userNotificationsCallBackCategory], nil]]; [UIApplication.sharedApplication registerUserNotificationSettings:settings]; return self.userNotificationFutureSource.future; } -- (UIUserNotificationCategory*)userNotificationsMessageCategory{ - UIMutableUserNotificationAction *action_view = [UIMutableUserNotificationAction new]; - action_view.identifier = Signal_Message_View_Identifier; - action_view.title = NSLocalizedString(@"PUSH_MANAGER_VIEW", @""); - action_view.activationMode = UIUserNotificationActivationModeForeground; - action_view.destructive = NO; - action_view.authenticationRequired = YES; +- (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 + if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(_iOS_9)) { + action_reply.behavior = UIUserNotificationActionBehaviorTextInput; + action_reply.activationMode = UIUserNotificationActivationModeBackground; + } else { + action_reply.activationMode = UIUserNotificationActivationModeForeground; + } UIMutableUserNotificationCategory *messageCategory = [UIMutableUserNotificationCategory new]; - messageCategory.identifier = Signal_Message_Category; - [messageCategory setActions:@[action_view] forContext:UIUserNotificationActionContextMinimal]; - [messageCategory setActions:@[action_view] forContext:UIUserNotificationActionContextDefault]; + messageCategory.identifier = Signal_Full_New_Message_Category; + [messageCategory setActions:@[action_markRead, action_reply] forContext:UIUserNotificationActionContextMinimal]; + [messageCategory setActions:@[] forContext:UIUserNotificationActionContextDefault]; return messageCategory; } @@ -445,4 +500,20 @@ return NO; } +- (void)presentNotification:(UILocalNotification*)notification { + [[UIApplication sharedApplication] scheduleLocalNotification:notification]; + [self.currentNotifications addObject:notification]; +} + +- (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]; + } + }]; + [self.currentNotifications removeObjectsInArray:toDelete]; +} + @end diff --git a/Signal/src/network/http/RPServerRequestsManager.m b/Signal/src/network/http/RPServerRequestsManager.m index a510061fe..3cb0cea37 100644 --- a/Signal/src/network/http/RPServerRequestsManager.m +++ b/Signal/src/network/http/RPServerRequestsManager.m @@ -9,6 +9,7 @@ #import "Environment.h" #import "AFHTTPSessionManager+SignalMethods.h" +#import "AFSecurityOWSPolicy.h" @interface RPServerRequestsManager () @@ -29,14 +30,7 @@ MacrosSingletonImplemention 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]; - AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate]; - securityPolicy.allowInvalidCertificates = YES; //The certificate is not signed by a CA in the iOS trust store. - securityPolicy.validatesCertificateChain = NO; //Looking at AFNetworking's implementation of chain checking, we don't need to pin all certs in chain. https://github.com/AFNetworking/AFNetworking/blob/e4855e9f25e4914ac2eb5caee26bc6e7a024a840/AFNetworking/AFSecurityPolicy.m#L271 Trust to the trusted cert is already vertified before by AFServerTrustIsValid(); - NSString *certPath = [NSBundle.mainBundle pathForResource:@"redphone" ofType:@"cer"]; - NSData *certData = [NSData dataWithContentsOfFile:certPath]; - SecCertificateRef cert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(certData)); - securityPolicy.pinnedCertificates = @[(__bridge_transfer NSData *)SecCertificateCopyData(cert)]; - self.operationManager.securityPolicy = securityPolicy; + self.operationManager.securityPolicy = [AFSecurityOWSPolicy OWS_PinningPolicy]; } return self; } diff --git a/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.m b/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.m index cccf2af01..12669a455 100644 --- a/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.m +++ b/Signal/src/textsecure/Messages/InvalidKeyMessages/TSInvalidIdentityKeySendingErrorMessage.m @@ -68,7 +68,7 @@ }]; if (message) { - [[TSMessagesManager sharedManager] sendMessage:message inThread:thread]; + [[TSMessagesManager sharedManager] sendMessage:message inThread:thread success:nil failure:nil]; } } diff --git a/Signal/src/textsecure/Messages/TSMessagesManager+attachments.m b/Signal/src/textsecure/Messages/TSMessagesManager+attachments.m index 645a95f69..429e1859d 100644 --- a/Signal/src/textsecure/Messages/TSMessagesManager+attachments.m +++ b/Signal/src/textsecure/Messages/TSMessagesManager+attachments.m @@ -106,7 +106,7 @@ dispatch_queue_t attachmentsQueue() { result.pointer.isDownloaded = YES; [result.pointer saveWithTransaction:transaction]; }]; - [self sendMessage:outgoingMessage inThread:thread]; + [self sendMessage:outgoingMessage inThread:thread success:nil failure:nil]; } else{ DDLogWarn(@"Failed to upload attachment"); } diff --git a/Signal/src/textsecure/Messages/TSMessagesManager+sendMessages.h b/Signal/src/textsecure/Messages/TSMessagesManager+sendMessages.h index 08bf64243..5baa23fb8 100644 --- a/Signal/src/textsecure/Messages/TSMessagesManager+sendMessages.h +++ b/Signal/src/textsecure/Messages/TSMessagesManager+sendMessages.h @@ -10,6 +10,11 @@ @interface TSMessagesManager (sendMessages) -- (void)sendMessage:(TSOutgoingMessage*)message inThread:(TSThread*)thread; +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 index 69fa7d083..10edd78c9 100644 --- a/Signal/src/textsecure/Messages/TSMessagesManager+sendMessages.m +++ b/Signal/src/textsecure/Messages/TSMessagesManager+sendMessages.m @@ -25,6 +25,9 @@ #import "TSServerMessage.h" #import "TSInfoMessage.h" +#import "CollapsingFutures.h" + +#define RETRY_ATTEMPTS 3 @interface TSMessagesManager () dispatch_queue_t sendingQueue(void); @@ -43,7 +46,10 @@ dispatch_queue_t sendingQueue() { return queue; } -- (void)sendMessage:(TSOutgoingMessage*)message inThread:(TSThread*)thread{ +- (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]]) { @@ -54,16 +60,7 @@ dispatch_queue_t sendingQueue() { recipients = [groupThread recipientsWithTransaction:transaction]; }]; - for(TSRecipient *rec in recipients){ - // we don't need to send the message to ourselves, but otherwise we send - if( ![[rec uniqueId] isEqualToString:[SignalKeyingStorage.localNumber toE164]]){ - [self sendMessage:message - toRecipient:rec - inThread:thread - withAttemps:3]; - } - } - + [self groupSend:recipients Message:message inThread:thread success:successCompletionBlock failure:failedCompletionBlock]; } else if([thread isKindOfClass:[TSContactThread class]]){ TSContactThread *contactThread = (TSContactThread*)thread; @@ -79,7 +76,9 @@ dispatch_queue_t sendingQueue() { [self sendMessage:message toRecipient:recipient inThread:thread - withAttemps:3]; + 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 @@ -91,10 +90,55 @@ dispatch_queue_t sendingQueue() { }); } +/// For group sends, we're using chained futures to make the code more readable. + +- (TOCFuture*)sendMessageFuture:(TSOutgoingMessage*)message + recipient:(TSRecipient*)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(TSRecipient *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)sendMessage:(TSOutgoingMessage*)message toRecipient:(TSRecipient*)recipient inThread:(TSThread*)thread - withAttemps:(int)remainingAttempts{ + withAttemps:(int)remainingAttempts + success:(successSendingCompletionBlock)successBlock + failure:(failedSendingCompletionBlock)failureBlock +{ if (remainingAttempts > 0) { remainingAttempts -= 1; @@ -107,7 +151,7 @@ dispatch_queue_t sendingQueue() { [recipient saveWithTransaction:transaction]; }]; [self handleMessageSent:message]; - + BLOCK_SAFE_RUN(successBlock); } failure:^(NSURLSessionDataTask *task, NSError *error) { NSHTTPURLResponse *response = (NSHTTPURLResponse *)task.response; long statuscode = response.statusCode; @@ -116,11 +160,12 @@ dispatch_queue_t sendingQueue() { switch (statuscode) { case 404:{ DDLogError(@"Recipient not found"); - [self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + [self.dbConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { [recipient removeWithTransaction:transaction]; [message setMessageState:TSOutgoingMessageStateUnsent]; [[TSInfoMessage userNotRegisteredMessageInThread:thread transaction:transaction] saveWithTransaction:transaction]; }]; + BLOCK_SAFE_RUN(failureBlock); break; } case 409:{ @@ -140,7 +185,12 @@ dispatch_queue_t sendingQueue() { } dispatch_async(sendingQueue(), ^{ - [self sendMessage:message toRecipient:recipient inThread:thread withAttemps:remainingAttempts]; + [self sendMessage:message + toRecipient:recipient + inThread:thread + withAttemps:remainingAttempts + success:successBlock + failure:failureBlock]; }); break; @@ -157,19 +207,30 @@ dispatch_queue_t sendingQueue() { [self handleStaleDevicesWithResponse:responseData recipientId:recipient.uniqueId]; dispatch_async(sendingQueue(), ^{ - [self sendMessage:message toRecipient:recipient inThread:thread withAttemps:remainingAttempts]; + [self sendMessage:message + toRecipient:recipient + inThread:thread + withAttemps:remainingAttempts + success:successBlock + failure:failureBlock]; }); break; } default: - [self sendMessage:message toRecipient:recipient inThread:thread withAttemps:remainingAttempts]; + [self sendMessage:message + toRecipient:recipient + inThread:thread + withAttemps:remainingAttempts + success:successBlock + failure:failureBlock]; break; } }]; }]; } else{ [self saveMessage:message withState:TSOutgoingMessageStateUnsent]; + BLOCK_SAFE_RUN(failureBlock); } } diff --git a/Signal/src/textsecure/Messages/TSMessagesManager.m b/Signal/src/textsecure/Messages/TSMessagesManager.m index 3864389d1..291e28729 100644 --- a/Signal/src/textsecure/Messages/TSMessagesManager.m +++ b/Signal/src/textsecure/Messages/TSMessagesManager.m @@ -290,7 +290,7 @@ thread = gThread; - } else{ + } else { TSContactThread *cThread = [TSContactThread getOrCreateThreadWithContactId:message.source transaction:transaction pushSignal:message]; @@ -424,7 +424,7 @@ notification.soundName = @"NewMessage.aifc"; notification.alertBody = [NSString stringWithFormat:NSLocalizedString(@"MSGVIEW_MISSED_CALL", nil), [thread name]]; - [[UIApplication sharedApplication] presentLocalNotificationNow:notification]; + [[PushManager sharedManager] presentNotification:notification]; } } } @@ -434,7 +434,6 @@ if (([UIApplication sharedApplication].applicationState != UIApplicationStateActive) && messageDescription) { UILocalNotification *notification = [[UILocalNotification alloc] init]; - notification.category = Signal_Message_Category; notification.userInfo = @{Signal_Thread_UserInfo_Key:thread.uniqueId}; notification.soundName = @"NewMessage.aifc"; @@ -452,7 +451,7 @@ } notification.alertBody = alertBodyString; - [[UIApplication sharedApplication] presentLocalNotificationNow:notification]; + [[PushManager sharedManager]presentNotification:notification]; } else { if ([Environment.preferences soundInForeground]) { AudioServicesPlayAlertSound(_newMessageSound); @@ -465,12 +464,14 @@ if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive && messageDescription) { UILocalNotification *notification = [[UILocalNotification alloc] init]; - notification.category = Signal_Message_Category; - notification.userInfo = @{Signal_Thread_UserInfo_Key:thread.uniqueId}; 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) { @@ -484,6 +485,7 @@ } 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 { @@ -499,7 +501,7 @@ break; } - [[UIApplication sharedApplication] presentLocalNotificationNow:notification]; + [[PushManager sharedManager] presentNotification:notification]; } else { if ([Environment.preferences soundInForeground]) { AudioServicesPlayAlertSound(_newMessageSound); diff --git a/Signal/src/textsecure/Network/API/Requests/TSRequest.m b/Signal/src/textsecure/Network/API/Requests/TSRequest.m index 0cdcf8634..ccf26c87e 100644 --- a/Signal/src/textsecure/Network/API/Requests/TSRequest.m +++ b/Signal/src/textsecure/Network/API/Requests/TSRequest.m @@ -26,12 +26,17 @@ 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]}]; } diff --git a/Signal/src/textsecure/Network/API/TSNetworkManager.m b/Signal/src/textsecure/Network/API/TSNetworkManager.m index 0b928eb78..83e331db9 100644 --- a/Signal/src/textsecure/Network/API/TSNetworkManager.m +++ b/Signal/src/textsecure/Network/API/TSNetworkManager.m @@ -8,6 +8,8 @@ #import +#import "AFSecurityOWSPolicy.h" + #import "TSAccountManager.h" #import "TSNetworkManager.h" #import "TSRegisterWithTokenRequest.h" @@ -36,14 +38,7 @@ if (self = [super init]) { NSURLSessionConfiguration *sessionConf = NSURLSessionConfiguration.ephemeralSessionConfiguration; self.operationManager = [[AFHTTPSessionManager alloc] initWithBaseURL:[[NSURL alloc] initWithString:textSecureServerURL] sessionConfiguration:sessionConf]; - AFSecurityPolicy *policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate]; - policy.allowInvalidCertificates = YES; //The certificate is not signed by a CA in the iOS trust store. - policy.validatesCertificateChain = NO; //Looking at AFNetworking's implementation of chain checking, we don't need to pin all certs in chain. https://github.com/AFNetworking/AFNetworking/blob/e4855e9f25e4914ac2eb5caee26bc6e7a024a840/AFNetworking/AFSecurityPolicy.m#L271 Trust to the trusted cert is already vertified before by AFServerTrustIsValid(); - NSString *certPath = [NSBundle.mainBundle pathForResource:@"textsecure" ofType:@"cer"]; - NSData *certData = [NSData dataWithContentsOfFile:certPath]; - SecCertificateRef cert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(certData)); - policy.pinnedCertificates = @[(__bridge_transfer NSData *)SecCertificateCopyData(cert)]; - self.operationManager.securityPolicy = policy; + self.operationManager.securityPolicy = [AFSecurityOWSPolicy OWS_PinningPolicy]; } return self; } @@ -73,8 +68,7 @@ [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"]){ + } else if ([request.HTTPMethod isEqualToString:@"DELETE"]){ [self.operationManager DELETE:[textSecureServerURL stringByAppendingString:request.URL.absoluteString] parameters:request.parameters success:success failure:failure]; } } diff --git a/Signal/src/textsecure/Network/WebSockets/TSSocketManager.m b/Signal/src/textsecure/Network/WebSockets/TSSocketManager.m index 3cbb945d9..c5ad4f585 100644 --- a/Signal/src/textsecure/Network/WebSockets/TSSocketManager.m +++ b/Signal/src/textsecure/Network/WebSockets/TSSocketManager.m @@ -15,6 +15,7 @@ #import "TSStorageManager+keyingMaterial.h" #import "Cryptography.h" +#import "AFSecurityOWSPolicy.h" #define kWebSocketHeartBeat 30 #define kWebSocketReconnectTry 5 @@ -101,12 +102,7 @@ NSString * const SocketConnectingNotification = @"SocketConnectingNotification"; NSString* webSocketConnect = [textSecureWebSocketAPI stringByAppendingString:[[self sharedManager] webSocketAuthenticationString]]; NSURL* webSocketConnectURL = [NSURL URLWithString:webSocketConnect]; NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:webSocketConnectURL]; - NSString* cerPath = [[NSBundle mainBundle] pathForResource:@"textsecure" ofType:@"cer"]; - NSData* certData = [[NSData alloc] initWithContentsOfFile:cerPath]; - CFDataRef certDataRef = (__bridge CFDataRef)certData; - SecCertificateRef certRef = SecCertificateCreateWithData(NULL, certDataRef); - id certificate = (__bridge id)certRef; - [request setSR_SSLPinnedCertificates:@[ certificate ]]; + request.securityPolicy = [AFSecurityOWSPolicy OWS_PinningPolicy]; socket = [[SRWebSocket alloc] initWithURLRequest:request]; socket.delegate = [self sharedManager]; diff --git a/Signal/src/util/UIFont+OWS.m b/Signal/src/util/UIFont+OWS.m index ce5f5f35a..279000e93 100644 --- a/Signal/src/util/UIFont+OWS.m +++ b/Signal/src/util/UIFont+OWS.m @@ -6,40 +6,34 @@ // Copyright (c) 2014 Open Whisper Systems. All rights reserved. // -static NSString *const kHelveticaNeueThin = @"HelveticaNeue-Thin"; -static NSString *const kHelveticaNeueLight = @"HelveticaNeue-Light"; -static NSString *const kHelveticaNeueRegular = @"HelveticaNeue"; -static NSString *const kHelveticaNeueMedium = @"HelveticaNeue-Medium"; -static NSString *const kHelveticaNeueBold = @"HelveticaNeue-Bold"; - #import "UIFont+OWS.h" @implementation UIFont (OWS) + (UIFont*) ows_thinFontWithSize:(CGFloat)size { - return [UIFont fontWithName:kHelveticaNeueThin size:size]; + return [UIFont systemFontOfSize:size weight:UIFontWeightThin]; } + (UIFont*) ows_lightFontWithSize:(CGFloat)size { - return [UIFont fontWithName:kHelveticaNeueLight size:size]; + return [UIFont systemFontOfSize:size weight:UIFontWeightLight]; } + (UIFont*) ows_regularFontWithSize:(CGFloat)size { - return [UIFont fontWithName:kHelveticaNeueRegular size:size]; + return [UIFont systemFontOfSize:size weight:UIFontWeightRegular]; } + (UIFont*) ows_mediumFontWithSize:(CGFloat)size { - return [UIFont fontWithName:kHelveticaNeueMedium size:size]; + return [UIFont systemFontOfSize:size weight:UIFontWeightMedium]; } + (UIFont*) ows_boldFontWithSize:(CGFloat)size { - return [UIFont fontWithName:kHelveticaNeueBold size:size]; + return [UIFont boldSystemFontOfSize:size]; } @end diff --git a/Signal/src/view controllers/CodeVerificationViewController.m b/Signal/src/view controllers/CodeVerificationViewController.m index 9c3cf5108..f80fef01d 100644 --- a/Signal/src/view controllers/CodeVerificationViewController.m +++ b/Signal/src/view controllers/CodeVerificationViewController.m @@ -30,15 +30,15 @@ _challengeTextField.placeholder = NSLocalizedString(@"VERIFICATION_CHALLENGE_DEFAULT_TEXT", @""); [_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 @@ -59,60 +59,74 @@ { [self enableServerActions:NO]; [_challengeTextField resignFirstResponder]; - + [self registerWithSuccess:^{ - [_submitCodeSpinner stopAnimating]; - [Environment.getCurrent.phoneDirectoryManager forceUpdate]; - [self.navigationController dismissViewControllerAnimated:YES completion:^{ - 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) { - [Environment.getCurrent.contactsManager doAfterEnvironmentInitSetup]; - }]]; - - [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:controller animated:YES completion:nil]; - }]; + [_submitCodeSpinner stopAnimating]; + [Environment.getCurrent.phoneDirectoryManager forceUpdate]; + + [self.navigationController dismissViewControllerAnimated:YES completion:^{ + [self passedVerification]; + }]; } failure:^(NSError *error) { - [self showAlertForError:error]; - [self enableServerActions:YES]; - [_submitCodeSpinner stopAnimating]; + [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]; + } +} + +- (void)setupContacts { + [[Environment getCurrent].contactsManager doAfterEnvironmentInitSetup]; +} - (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]; - - }]; + 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]; + + }]; } @@ -126,14 +140,14 @@ DDLogError(@"%@: Unable to display error because localizedDescription was not set: %@", self.class, error); return; } - + NSString *alertBody = nil; if (error.localizedFailureReason.length > 0) { alertBody = error.localizedFailureReason; } else if (error.localizedRecoverySuggestion.length > 0) { alertBody = error.localizedRecoverySuggestion; } - + SignalAlertView(error.localizedDescription, alertBody); } @@ -143,7 +157,7 @@ NSString *description = NSLocalizedString(@"REGISTRATION_ERROR", @""); NSString *failureReason = nil; TSRegistrationFailure failureType; - + if (badResponse.statusCode == 401) { failureReason = REGISTER_CHALLENGE_ALERT_VIEW_BODY; failureType = kTSRegistrationFailureAuthentication; @@ -152,14 +166,14 @@ failureType = kTSRegistrationFailureRateLimit; } else { failureReason = [NSString - stringWithFormat:@"%@ %lu", NSLocalizedString(@"SERVER_CODE", @""), (unsigned long)badResponse.statusCode]; + stringWithFormat:@"%@ %lu", NSLocalizedString(@"SERVER_CODE", @""), (unsigned long)badResponse.statusCode]; failureType = kTSRegistrationFailureNetwork; } - + NSDictionary *userInfo = - @{NSLocalizedDescriptionKey : description, NSLocalizedFailureReasonErrorKey : failureReason}; + @{NSLocalizedDescriptionKey : description, NSLocalizedFailureReasonErrorKey : failureReason}; NSError *error = [NSError errorWithDomain:TSRegistrationErrorDomain code:failureType userInfo:userInfo]; - + return error; } @@ -167,57 +181,57 @@ - (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]; - }]; + 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]; + }]; } - (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]; - }]; + 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]; + }]; } - (void)enableServerActions:(BOOL)enabled @@ -233,7 +247,7 @@ - (void)initializeKeyboardHandlers { UITapGestureRecognizer *outsideTabRecognizer = - [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)]; + [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboardFromAppropriateSubView)]; [self.view addGestureRecognizer:outsideTabRecognizer]; } @@ -246,14 +260,14 @@ { CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height; CGFloat blueHeaderHeight; - + if (screenHeight < 667) { self.signalLogo.hidden = YES; blueHeaderHeight = screenHeight - 400; } else { blueHeaderHeight = screenHeight - 410; } - + _headerConstraint.constant = blueHeaderHeight; } diff --git a/Signal/src/view controllers/InCallViewController.h b/Signal/src/view controllers/InCallViewController.h index 222bd2d6e..934f42b65 100644 --- a/Signal/src/view controllers/InCallViewController.h +++ b/Signal/src/view controllers/InCallViewController.h @@ -34,8 +34,7 @@ @property (nonatomic, strong) IBOutlet UIButton *rejectButton; @property (nonatomic, strong) IBOutlet UIButton *answerButton; -@property (nonatomic, strong) IBOutlet UIImageView *connectingIndicatorImageView; -@property (nonatomic, strong) IBOutlet UIImageView *callStateImageContainerView; +@property IBOutlet UIView *containerView; @property (nonatomic, readonly) CallState *callState; @property (nonatomic, readonly) Contact *potentiallyKnownContact; diff --git a/Signal/src/view controllers/InCallViewController.m b/Signal/src/view controllers/InCallViewController.m index ea78a02cf..33c4c3791 100644 --- a/Signal/src/view controllers/InCallViewController.m +++ b/Signal/src/view controllers/InCallViewController.m @@ -11,13 +11,6 @@ #define CONNECTING_FLASH_DURATION 0.5f #define END_CALL_CLEANUP_DELAY (int)(3.1f * NSEC_PER_SEC) -static NSString *const SPINNER_CONNECTING_IMAGE_NAME = @"spinner_connecting"; -static NSString *const SPINNER_CONNECTING_FLASH_IMAGE_NAME = @"spinner_connecting_flash"; -static NSString *const SPINNER_RINGING_IMAGE_NAME = @"spinner_ringing"; -static NSString *const SPINNER_ERROR_FLASH_IMAGE_NAME = @"spinner_error"; - -static NSInteger connectingFlashCounter = 0; - @interface InCallViewController () { CallAudioManager *_callAudioManager; @@ -40,7 +33,7 @@ static NSInteger connectingFlashCounter = 0; - (void)viewDidLoad { [super viewDidLoad]; - + [self showCallState]; [self setPotentiallyKnownContact:_potentiallyKnownContact]; [self localizeButtons]; @@ -58,7 +51,6 @@ static NSInteger connectingFlashCounter = 0; - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; - [self startConnectingFlashAnimation]; [UIDevice.currentDevice setProximityMonitoringEnabled:YES]; } @@ -76,37 +68,8 @@ static NSInteger connectingFlashCounter = 0; [self handleIncomingDetails]; } -- (void)startConnectingFlashAnimation { - if(!_ringingAnimationTimer.isValid){ - _connectingFlashTimer = [NSTimer scheduledTimerWithTimeInterval:CONNECTING_FLASH_DURATION - target:self - selector:@selector(flashConnectingIndicator) - userInfo:nil - repeats:YES]; - } -} - -- (void)flashConnectingIndicator { - - NSString *newImageName; - - if (connectingFlashCounter % 2 == 0) { - newImageName = SPINNER_CONNECTING_IMAGE_NAME; - } else { - newImageName = SPINNER_CONNECTING_FLASH_IMAGE_NAME; - } - - [_connectingIndicatorImageView setImage:[UIImage imageNamed:newImageName]]; - connectingFlashCounter++; -} - - (void)startRingingAnimation { [self stopConnectingFlashAnimation]; - _ringingAnimationTimer = [NSTimer scheduledTimerWithTimeInterval:RINGING_ROTATION_DURATION - target:self - selector:@selector(rotateConnectingIndicator) - userInfo:nil - repeats:YES]; if (!_incomingCallButtonsView.hidden) { _vibrateTimer = [NSTimer scheduledTimerWithTimeInterval:VIBRATE_TIMER_DURATION @@ -123,19 +86,6 @@ static NSInteger connectingFlashCounter = 0; AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); } -- (void)rotateConnectingIndicator { - [_connectingIndicatorImageView setImage:[UIImage imageNamed:SPINNER_RINGING_IMAGE_NAME]]; - [UIView animateWithDuration:RINGING_ROTATION_DURATION delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{ - _connectingIndicatorImageView.transform = CGAffineTransformRotate(_connectingIndicatorImageView.transform, (float)M_PI_2); - } completion:nil]; -} - -- (void)performCallInSessionAnimation { - [UIView animateWithDuration:0.5f animations:^{ - [_callStateImageContainerView setFrame:CGRectMake(0, _callStateImageContainerView.frame.origin.y, _callStateImageContainerView.frame.size.width, _callStateImageContainerView.frame.size.height)]; - }]; -} - - (void)stopRingingAnimation { if (_ringingAnimationTimer) { [_ringingAnimationTimer invalidate]; @@ -154,7 +104,6 @@ static NSInteger connectingFlashCounter = 0; - (void)showConnectingError { [self stopRingingAnimation]; [self stopConnectingFlashAnimation]; - [_connectingIndicatorImageView setImage:[UIImage imageNamed:SPINNER_ERROR_FLASH_IMAGE_NAME]]; } - (void)localizeButtons { @@ -205,7 +154,6 @@ static NSInteger connectingFlashCounter = 0; _muteButton.hidden = NO; _speakerButton.hidden = NO; _authenicationStringLabel.text = sas; - [self performCallInSessionAnimation]; }]; [[_callState observableProgress] watchLatestValue:^(CallProgress* latestProgress) { diff --git a/Signal/src/view controllers/InboxTableViewCell.h b/Signal/src/view controllers/InboxTableViewCell.h index b59ffeca1..f6ec26ccf 100644 --- a/Signal/src/view controllers/InboxTableViewCell.h +++ b/Signal/src/view controllers/InboxTableViewCell.h @@ -36,8 +36,9 @@ typedef enum : NSUInteger { @property (nonatomic, strong) IBOutlet UIImageView *archiveImageView; @property (nonatomic, assign) id delegate; --(void)configureWithThread:(TSThread*)thread; --(void)configureForState:(CellState)state; --(void)animateDisappear; ++ (instancetype)inboxTableViewCell; +- (void)configureWithThread:(TSThread*)thread; +- (void)configureForState:(CellState)state; +- (void)animateDisappear; @end diff --git a/Signal/src/view controllers/InboxTableViewCell.m b/Signal/src/view controllers/InboxTableViewCell.m index d27722126..eae892d0f 100644 --- a/Signal/src/view controllers/InboxTableViewCell.m +++ b/Signal/src/view controllers/InboxTableViewCell.m @@ -22,19 +22,21 @@ @implementation InboxTableViewCell -- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { - self = [NSBundle.mainBundle loadNibNamed:NSStringFromClass(self.class) - owner:self - options:nil][0]; ++ (instancetype)inboxTableViewCell { + InboxTableViewCell *cell = [NSBundle.mainBundle loadNibNamed:NSStringFromClass(self.class) + owner:self + options:nil][0]; - if (self) { - _scrollView.contentSize = CGSizeMake(CGRectGetWidth(_contentContainerView.bounds), - CGRectGetHeight(_scrollView.frame)); - - _scrollView.contentOffset = CGPointMake(CGRectGetWidth(_archiveView.frame), 0); - _archiveImageView.image = [_archiveImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; - } - return self; + [cell initializeLayout]; + return cell; +} + +- (void)initializeLayout { + _scrollView.contentSize = CGSizeMake(CGRectGetWidth(_contentContainerView.bounds), + CGRectGetHeight(_scrollView.frame)); + + _scrollView.contentOffset = CGPointMake(CGRectGetWidth(_archiveView.frame), 0); + _archiveImageView.image = [_archiveImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; } - (NSString *)reuseIdentifier { @@ -51,7 +53,7 @@ _nameLabel.text = NSLocalizedString(@"NEW_GROUP_DEFAULT_TITLE", @""); } if(_contactPictureView.image!=nil) { - [UIUtil applyRoundedBorderToImageView:&_contactPictureView]; + [UIUtil applyRoundedBorderToImageView:&_contactPictureView]; } } else { @@ -77,7 +79,7 @@ [UIUtil applyRoundedBorderToImageView:&_contactPictureView]; } } - + self.separatorInset = UIEdgeInsetsMake(0,_contactPictureView.frame.size.width*1.5f, 0, 0); if (thread.hasUnreadMessages) { @@ -130,12 +132,12 @@ 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; } diff --git a/Signal/src/view controllers/MessagesViewController.m b/Signal/src/view controllers/MessagesViewController.m index b9e360748..5c6959662 100644 --- a/Signal/src/view controllers/MessagesViewController.m +++ b/Signal/src/view controllers/MessagesViewController.m @@ -126,7 +126,7 @@ typedef enum : NSUInteger { [[TSMessagesManager sharedManager] sendAttachment:UIImagePNGRepresentation(model.groupImage) contentType:@"image/png" inMessage:message thread:self.thread]; } else { - [[TSMessagesManager sharedManager] sendMessage:message inThread:self.thread]; + [[TSMessagesManager sharedManager] sendMessage:message inThread:self.thread success:nil failure:nil]; } isGroupConversation = YES; } @@ -572,7 +572,7 @@ typedef enum : NSUInteger { TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp] inThread:self.thread messageBody:text attachments:nil]; - [[TSMessagesManager sharedManager] sendMessage:message inThread:self.thread]; + [[TSMessagesManager sharedManager] sendMessage:message inThread:self.thread success:nil failure:nil]; [self finishSendingMessage]; } } @@ -1072,7 +1072,7 @@ typedef enum : NSUInteger { [message removeWithTransaction:transaction]; }]; }else { - [[TSMessagesManager sharedManager] sendMessage:message inThread:self.thread]; + [[TSMessagesManager sharedManager] sendMessage:message inThread:self.thread success:nil failure:nil]; [self finishSendingMessage]; } }]; @@ -1603,7 +1603,7 @@ typedef enum : NSUInteger { 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]; + [[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]]; @@ -1630,7 +1630,7 @@ typedef enum : NSUInteger { [[TSMessagesManager sharedManager] sendAttachment:UIImagePNGRepresentation(newGroupModel.groupImage) contentType:@"image/png" inMessage:message thread:groupThread]; } else { - [[TSMessagesManager sharedManager] sendMessage:message inThread:groupThread]; + [[TSMessagesManager sharedManager] sendMessage:message inThread:groupThread success:nil failure:nil]; } self.thread = groupThread; diff --git a/Signal/src/view controllers/SettingsTableViewController.m b/Signal/src/view controllers/SettingsTableViewController.m index 0c4cfc4f1..dd50a0058 100644 --- a/Signal/src/view controllers/SettingsTableViewController.m +++ b/Signal/src/view controllers/SettingsTableViewController.m @@ -60,6 +60,8 @@ typedef enum { - (void)viewDidLoad { [super viewDidLoad]; + [self.navigationItem setHidesBackButton:YES]; + [self.navigationController.navigationBar setTranslucent:NO]; self.tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero]; diff --git a/Signal/src/view controllers/UITests/SignalsViewController.h b/Signal/src/view controllers/UITests/SignalsViewController.h index 1f47219e9..72677fc05 100644 --- a/Signal/src/view controllers/UITests/SignalsViewController.h +++ b/Signal/src/view controllers/UITests/SignalsViewController.h @@ -24,4 +24,6 @@ @property (nonatomic, retain) CallState* latestCall; +- (NSNumber*)updateInboxCountLabel; + @end diff --git a/Signal/src/view controllers/UITests/SignalsViewController.m b/Signal/src/view controllers/UITests/SignalsViewController.m index 1322dc9fa..f7e519368 100644 --- a/Signal/src/view controllers/UITests/SignalsViewController.m +++ b/Signal/src/view controllers/UITests/SignalsViewController.m @@ -10,7 +10,6 @@ #import "InboxTableViewCell.h" #import "ContactsManager.h" -#import "Environment.h" #import "MessagesViewController.h" #import "SignalsViewController.h" #import "InCallViewController.h" @@ -31,7 +30,6 @@ static NSString *const inboxTableViewCell = @"inBoxTableViewCell"; static NSString *const kSegueIndentifier = @"showSegue"; -static NSString* const kCallSegue = @"2.0_6.0_Call_Segue"; static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; @interface SignalsViewController () @@ -97,8 +95,8 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; return; } - [[self tableView] reloadData]; [self updateInboxCountLabel]; + [[self tableView] reloadData]; } -(void)tableViewSetUp @@ -123,8 +121,7 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; TSThread *thread = [self threadForIndexPath:indexPath]; if (!cell) { - cell = [[InboxTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault - reuseIdentifier:inboxTableViewCell]; + cell = [InboxTableViewCell inboxTableViewCell]; cell.delegate = self; } @@ -186,7 +183,7 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; 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]; + [[TSMessagesManager sharedManager] sendMessage:message inThread:thread success:nil failure:nil]; } [self.editingDbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { [thread removeWithTransaction:transaction]; @@ -202,12 +199,11 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; BOOL viewingThreadsIn = self.viewingThreadsIn; [self.editingDbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { viewingThreadsIn == kInboxState ? [thread archiveThreadWithTransaction:transaction] : [thread unarchiveThreadWithTransaction:transaction]; - + }]; [self checkIfEmptyView]; } - - (NSNumber*)updateInboxCountLabel { NSUInteger numberOfItems = [[TSMessagesManager sharedManager] unreadMessagesCount]; NSNumber *badgeNumber = [NSNumber numberWithUnsignedInteger:numberOfItems]; @@ -219,6 +215,7 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; } [_segmentedControl setTitle:unreadString forSegmentAtIndex:0]; + [_segmentedControl reloadInputViews]; [[UIApplication sharedApplication] setApplicationIconBadgeNumber:badgeNumber.integerValue]; return badgeNumber; @@ -280,7 +277,7 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow"; self.threadMappings = [[YapDatabaseViewMappings alloc] initWithGroups:@[grouping] view:TSThreadDatabaseViewExtensionName]; [self.threadMappings setIsReversed:YES forGroup:grouping]; - + [self.uiDatabaseConnection asyncReadWithBlock:^(YapDatabaseReadTransaction *transaction){ [self.threadMappings updateWithTransaction:transaction]; diff --git a/Signal/test/Supporting Files/SignalTests-Info.plist b/Signal/test/Supporting Files/SignalTests-Info.plist index 59b7babee..169b6f710 100644 --- a/Signal/test/Supporting Files/SignalTests-Info.plist +++ b/Signal/test/Supporting Files/SignalTests-Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - org.whispersystems.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 5d6a65d370e3401cc4c496a9867d2e4424ca4124..f219a8503c015098ede1fdcda3c30f59b87491a8 100644 GIT binary patch delta 555 zcmbVJyGjF55IvDVU`0hNj0AB>Viidz2oiC#D-x6#vYR4R*lgmuux_3rRw?YXygy>d z7x)Q&K`I*yD;qn{Yy?xwaPQoiJ9FmD%;!Au^`3ZH*-=kHI@N-WGgMWtkx}81rnJg> zLB};*1PIYZ2Rg>+@gC8Nmh63;qB#3bKdv5HuuvzAO)2Awa)H*b$Dyvkgu{P}UIUkW z)#0dV&fhfPQMv>lEefgE>=p?Gu|14`#u(D}NJHop8E4b>NybH}29@oJ_?jenNA1xY zQFmet7wxzWY2t?YImMBclnI7>7bjZXLiq27llpgN+Hc3y2`-~c~$t;ec@isWLe+-v{ yE~CMrJ6uLp%}Z-3sl*-52Kmz7u57EuO*C0TM~NrPopjkhyH?L;ZuVg&4}Ji__io4l delta 58 zcmezJl=0nt#tlr8n>!?{xF_#X*4n&6okLzSjKPz^l_8u#i9vzE7KoJ?!Wc3cQW?r8 NU(6TY{J>2_2LL*o5kUX|