Compare commits
2 Commits
master
...
mkirk/only
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2737845c25 | ||
|
|
388f75ef04 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -17,7 +17,6 @@ DerivedData
|
||||
*.hmap
|
||||
*.ipa
|
||||
*.xcuserstate
|
||||
xcshareddata
|
||||
|
||||
Pods/
|
||||
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
language: objective-c
|
||||
|
||||
osx_image: xcode8.3
|
||||
osx_image: xcode8
|
||||
|
||||
env:
|
||||
-EARLY_START_SIMULATOR=1 # early starting simulator reduces false negatives due to test timeouts
|
||||
|
||||
before_install:
|
||||
- brew update
|
||||
- bundle
|
||||
- bundle exec pod repo update --silent
|
||||
- gem install cocoapods xcpretty --no-ri --no-rdoc
|
||||
- pod repo update --silent
|
||||
|
||||
after_failure:
|
||||
- sleep 10 # This prevents the occasional output truncation that happens when piping to xcpretty.
|
||||
|
||||
script: make scan_test
|
||||
script: make
|
||||
|
||||
|
||||
@ -11,19 +11,3 @@ target 'TSKitiOSTestApp' do
|
||||
end
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
if target.to_s == "SignalServiceKit"
|
||||
puts "--[!] Disabling singleton enforcement for SSK."
|
||||
target.build_configurations.each do |config|
|
||||
existing_definitions = config.build_settings['GCC_PREPROCESSOR_DEFINITIONS']
|
||||
if existing_definitions == nil || existing.length == 0
|
||||
existing_definitions = "$(inheritied)"
|
||||
end
|
||||
|
||||
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = "#{existing_definitions} SSK_BUILDING_FOR_TESTS=1"
|
||||
config.build_settings['OTHER_SWIFT_FLAGS'] = ['$(inherited)', '-DSSK_BUILDING_FOR_TESTS']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -17,7 +17,6 @@ PODS:
|
||||
- AFNetworking/NSURLSession
|
||||
- AxolotlKit (0.8.1):
|
||||
- 25519 (~> 2.0.1)
|
||||
- CocoaLumberjack
|
||||
- HKDFKit (~> 0.0.3)
|
||||
- ProtocolBuffers (~> 1.9.8)
|
||||
- CocoaLumberjack (2.4.0):
|
||||
@ -29,11 +28,12 @@ PODS:
|
||||
- CocoaLumberjack/Extensions (2.4.0):
|
||||
- CocoaLumberjack/Default
|
||||
- HKDFKit (0.0.3)
|
||||
- libPhoneNumber-iOS (0.9.10)
|
||||
- libPhoneNumber-iOS (0.9.4)
|
||||
- Mantle (2.1.0):
|
||||
- Mantle/extobjc (= 2.1.0)
|
||||
- Mantle/extobjc (2.1.0)
|
||||
- ProtocolBuffers (1.9.11)
|
||||
- Reachability (3.2)
|
||||
- SAMKeychain (1.5.2)
|
||||
- SignalServiceKit (0.9.0):
|
||||
- '25519'
|
||||
@ -45,7 +45,7 @@ PODS:
|
||||
- SAMKeychain
|
||||
- SocketRocket
|
||||
- TwistedOakCollapsingFutures
|
||||
- YapDatabase/SQLCipher (~> 2.9.3)
|
||||
- YapDatabase/SQLCipher
|
||||
- SocketRocket (0.5.1)
|
||||
- SQLCipher/common (3.4.1)
|
||||
- SQLCipher/fts (3.4.1):
|
||||
@ -53,53 +53,54 @@ PODS:
|
||||
- TwistedOakCollapsingFutures (1.0.0):
|
||||
- UnionFind (~> 1.0)
|
||||
- UnionFind (1.0.1)
|
||||
- YapDatabase/SQLCipher (2.9.3):
|
||||
- YapDatabase/SQLCipher/Core (= 2.9.3)
|
||||
- YapDatabase/SQLCipher/Extensions (= 2.9.3)
|
||||
- YapDatabase/SQLCipher/Core (2.9.3):
|
||||
- YapDatabase/SQLCipher (2.9.2):
|
||||
- YapDatabase/SQLCipher/Core (= 2.9.2)
|
||||
- YapDatabase/SQLCipher/Extensions (= 2.9.2)
|
||||
- YapDatabase/SQLCipher/Core (2.9.2):
|
||||
- CocoaLumberjack (~> 2)
|
||||
- SQLCipher/fts
|
||||
- YapDatabase/SQLCipher/Extensions (2.9.3):
|
||||
- YapDatabase/SQLCipher/Extensions (2.9.2):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/ActionManager (= 2.9.3)
|
||||
- YapDatabase/SQLCipher/Extensions/CloudKit (= 2.9.3)
|
||||
- YapDatabase/SQLCipher/Extensions/ConnectionProxy (= 2.9.3)
|
||||
- YapDatabase/SQLCipher/Extensions/CrossProcessNotification (= 2.9.3)
|
||||
- YapDatabase/SQLCipher/Extensions/FilteredViews (= 2.9.3)
|
||||
- YapDatabase/SQLCipher/Extensions/FullTextSearch (= 2.9.3)
|
||||
- YapDatabase/SQLCipher/Extensions/Hooks (= 2.9.3)
|
||||
- YapDatabase/SQLCipher/Extensions/Relationships (= 2.9.3)
|
||||
- YapDatabase/SQLCipher/Extensions/RTreeIndex (= 2.9.3)
|
||||
- YapDatabase/SQLCipher/Extensions/SearchResults (= 2.9.3)
|
||||
- YapDatabase/SQLCipher/Extensions/SecondaryIndex (= 2.9.3)
|
||||
- YapDatabase/SQLCipher/Extensions/Views (= 2.9.3)
|
||||
- YapDatabase/SQLCipher/Extensions/ActionManager (2.9.3):
|
||||
- YapDatabase/SQLCipher/Extensions/ActionManager (= 2.9.2)
|
||||
- YapDatabase/SQLCipher/Extensions/CloudKit (= 2.9.2)
|
||||
- YapDatabase/SQLCipher/Extensions/ConnectionProxy (= 2.9.2)
|
||||
- YapDatabase/SQLCipher/Extensions/CrossProcessNotification (= 2.9.2)
|
||||
- YapDatabase/SQLCipher/Extensions/FilteredViews (= 2.9.2)
|
||||
- YapDatabase/SQLCipher/Extensions/FullTextSearch (= 2.9.2)
|
||||
- YapDatabase/SQLCipher/Extensions/Hooks (= 2.9.2)
|
||||
- YapDatabase/SQLCipher/Extensions/Relationships (= 2.9.2)
|
||||
- YapDatabase/SQLCipher/Extensions/RTreeIndex (= 2.9.2)
|
||||
- YapDatabase/SQLCipher/Extensions/SearchResults (= 2.9.2)
|
||||
- YapDatabase/SQLCipher/Extensions/SecondaryIndex (= 2.9.2)
|
||||
- YapDatabase/SQLCipher/Extensions/Views (= 2.9.2)
|
||||
- YapDatabase/SQLCipher/Extensions/ActionManager (2.9.2):
|
||||
- Reachability (~> 3)
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/Views
|
||||
- YapDatabase/SQLCipher/Extensions/CloudKit (2.9.3):
|
||||
- YapDatabase/SQLCipher/Extensions/CloudKit (2.9.2):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/ConnectionProxy (2.9.3):
|
||||
- YapDatabase/SQLCipher/Extensions/ConnectionProxy (2.9.2):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/CrossProcessNotification (2.9.3):
|
||||
- YapDatabase/SQLCipher/Extensions/CrossProcessNotification (2.9.2):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/FilteredViews (2.9.3):
|
||||
- YapDatabase/SQLCipher/Extensions/FilteredViews (2.9.2):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/Views
|
||||
- YapDatabase/SQLCipher/Extensions/FullTextSearch (2.9.3):
|
||||
- YapDatabase/SQLCipher/Extensions/FullTextSearch (2.9.2):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/Hooks (2.9.3):
|
||||
- YapDatabase/SQLCipher/Extensions/Hooks (2.9.2):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/Relationships (2.9.3):
|
||||
- YapDatabase/SQLCipher/Extensions/Relationships (2.9.2):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/RTreeIndex (2.9.3):
|
||||
- YapDatabase/SQLCipher/Extensions/RTreeIndex (2.9.2):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/SearchResults (2.9.3):
|
||||
- YapDatabase/SQLCipher/Extensions/SearchResults (2.9.2):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/FullTextSearch
|
||||
- YapDatabase/SQLCipher/Extensions/Views
|
||||
- YapDatabase/SQLCipher/Extensions/SecondaryIndex (2.9.3):
|
||||
- YapDatabase/SQLCipher/Extensions/SecondaryIndex (2.9.2):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/Views (2.9.3):
|
||||
- YapDatabase/SQLCipher/Extensions/Views (2.9.2):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
|
||||
DEPENDENCIES:
|
||||
@ -111,13 +112,13 @@ EXTERNAL SOURCES:
|
||||
AxolotlKit:
|
||||
:git: https://github.com/WhisperSystems/SignalProtocolKit.git
|
||||
SignalServiceKit:
|
||||
:path: ../../SignalServiceKit.podspec
|
||||
:path: "../../SignalServiceKit.podspec"
|
||||
SocketRocket:
|
||||
:git: https://github.com/facebook/SocketRocket.git
|
||||
|
||||
CHECKOUT OPTIONS:
|
||||
AxolotlKit:
|
||||
:commit: 28afe5c1dbcfdea73d147e464c53d191d1e3ea50
|
||||
:commit: a3c843cc8a423c5924c663490978f81dba34d04e
|
||||
:git: https://github.com/WhisperSystems/SignalProtocolKit.git
|
||||
SocketRocket:
|
||||
:commit: 877ac7438be3ad0b45ef5ca3969574e4b97112bf
|
||||
@ -126,20 +127,21 @@ CHECKOUT OPTIONS:
|
||||
SPEC CHECKSUMS:
|
||||
'25519': dc4bad7e2dbcbf1efa121068a705a44cd98c80fc
|
||||
AFNetworking: 5e0e199f73d8626b11e79750991f5d173d1f8b67
|
||||
AxolotlKit: a9530d6835baae0f204b1f6b9dd79b7901176f0d
|
||||
AxolotlKit: 240c7d761e4b1be9c6de78ebec498aaeedc978f4
|
||||
CocoaLumberjack: aa9dcab71bdf9eaf2a63bbd9ddc87863efe45457
|
||||
HKDFKit: c058305d6f64b84f28c50bd7aa89574625bcb62a
|
||||
libPhoneNumber-iOS: f721ae4d5854bce60934f9fb9b0b28e8e68913cb
|
||||
libPhoneNumber-iOS: 63bab980d1fc9783d82d955800ac9d7c1d81fde3
|
||||
Mantle: 2fa750afa478cd625a94230fbf1c13462f29395b
|
||||
ProtocolBuffers: d509225eb2ea43d9582a59e94348fcf86e2abd65
|
||||
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
|
||||
SAMKeychain: 1865333198217411f35327e8da61b43de79b635b
|
||||
SignalServiceKit: 2ad8d86da055e24ac3ea0354ec1d4b13251af28f
|
||||
SignalServiceKit: 59a79a51b89b963ba94db30cc99ed5212da0bb9f
|
||||
SocketRocket: dbb1554b8fc288ef8ef370d6285aeca7361be31e
|
||||
SQLCipher: 43d12c0eb9c57fb438749618fc3ce0065509a559
|
||||
TwistedOakCollapsingFutures: f359b90f203e9ab13dfb92c9ff41842a7fe1cd0c
|
||||
UnionFind: c33be5adb12983981d6e827ea94fc7f9e370f52d
|
||||
YapDatabase: cd911121580ff16675f65ad742a9eb0ab4d9e266
|
||||
YapDatabase: b1e43555a34a5298e23a045be96817a5ef0da58f
|
||||
|
||||
PODFILE CHECKSUM: a0f4507b6b4e6f9da3250901b06187a67236e083
|
||||
PODFILE CHECKSUM: 1a7633963dbcaa43f298949d83c42c1cd1dce940
|
||||
|
||||
COCOAPODS: 1.2.1
|
||||
COCOAPODS: 1.2.0
|
||||
|
||||
@ -457,7 +457,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
276B029791E679B0E87877B7 /* [CP] Copy Pods Resources */ = {
|
||||
@ -532,7 +532,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "FF3F51F81980908EDE1836B76AA3A1EC"
|
||||
BlueprintIdentifier = "1D0826C97B09E58C83B3C228FBC535FA"
|
||||
BuildableName = "libSignalServiceKit.a"
|
||||
BlueprintName = "SignalServiceKit"
|
||||
ReferencedContainer = "container:Pods/Pods.xcodeproj">
|
||||
|
||||
189
Gemfile.lock
189
Gemfile.lock
@ -1,189 +0,0 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (2.3.5)
|
||||
activesupport (4.2.9)
|
||||
i18n (~> 0.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.5.1)
|
||||
public_suffix (~> 2.0, >= 2.0.2)
|
||||
babosa (1.0.2)
|
||||
claide (1.0.2)
|
||||
cocoapods (1.2.1)
|
||||
activesupport (>= 4.0.2, < 5)
|
||||
claide (>= 1.0.1, < 2.0)
|
||||
cocoapods-core (= 1.2.1)
|
||||
cocoapods-deintegrate (>= 1.0.1, < 2.0)
|
||||
cocoapods-downloader (>= 1.1.3, < 2.0)
|
||||
cocoapods-plugins (>= 1.0.0, < 2.0)
|
||||
cocoapods-search (>= 1.0.0, < 2.0)
|
||||
cocoapods-stats (>= 1.0.0, < 2.0)
|
||||
cocoapods-trunk (>= 1.2.0, < 2.0)
|
||||
cocoapods-try (>= 1.1.0, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
escape (~> 0.0.4)
|
||||
fourflusher (~> 2.0.1)
|
||||
gh_inspector (~> 1.0)
|
||||
molinillo (~> 0.5.7)
|
||||
nap (~> 1.0)
|
||||
ruby-macho (~> 1.1)
|
||||
xcodeproj (>= 1.4.4, < 2.0)
|
||||
cocoapods-core (1.2.1)
|
||||
activesupport (>= 4.0.2, < 5)
|
||||
fuzzy_match (~> 2.0.4)
|
||||
nap (~> 1.0)
|
||||
cocoapods-deintegrate (1.0.1)
|
||||
cocoapods-downloader (1.1.3)
|
||||
cocoapods-plugins (1.0.0)
|
||||
nap
|
||||
cocoapods-search (1.0.0)
|
||||
cocoapods-stats (1.0.0)
|
||||
cocoapods-trunk (1.2.0)
|
||||
nap (>= 0.8, < 2.0)
|
||||
netrc (= 0.7.8)
|
||||
cocoapods-try (1.1.0)
|
||||
colored (1.2)
|
||||
colored2 (3.1.2)
|
||||
commander-fastlane (4.4.5)
|
||||
highline (~> 1.7.2)
|
||||
declarative (0.0.9)
|
||||
declarative-option (0.1.0)
|
||||
domain_name (0.5.20170404)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
dotenv (2.2.1)
|
||||
escape (0.0.4)
|
||||
excon (0.57.1)
|
||||
faraday (0.12.1)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
faraday-cookie_jar (0.0.6)
|
||||
faraday (>= 0.7.4)
|
||||
http-cookie (~> 1.0.0)
|
||||
faraday_middleware (0.11.0.1)
|
||||
faraday (>= 0.7.4, < 1.0)
|
||||
fastimage (2.1.0)
|
||||
fastlane (2.46.0)
|
||||
CFPropertyList (>= 2.3, < 3.0.0)
|
||||
addressable (>= 2.3, < 3.0.0)
|
||||
babosa (>= 1.0.2, < 2.0.0)
|
||||
bundler (>= 1.12.0, < 2.0.0)
|
||||
colored
|
||||
commander-fastlane (>= 4.4.5, < 5.0.0)
|
||||
dotenv (>= 2.1.1, < 3.0.0)
|
||||
excon (>= 0.45.0, < 1.0.0)
|
||||
faraday (~> 0.9)
|
||||
faraday-cookie_jar (~> 0.0.6)
|
||||
faraday_middleware (~> 0.9)
|
||||
fastimage (>= 2.1.0, < 3.0.0)
|
||||
gh_inspector (>= 1.0.1, < 2.0.0)
|
||||
google-api-client (>= 0.12.0, < 0.13.0)
|
||||
highline (>= 1.7.2, < 2.0.0)
|
||||
json (< 3.0.0)
|
||||
mini_magick (~> 4.5.1)
|
||||
multi_json
|
||||
multi_xml (~> 0.5)
|
||||
multipart-post (~> 2.0.0)
|
||||
plist (>= 3.1.0, < 4.0.0)
|
||||
rubyzip (>= 1.1.0, < 2.0.0)
|
||||
security (= 0.1.3)
|
||||
slack-notifier (>= 1.3, < 2.0.0)
|
||||
terminal-notifier (>= 1.6.2, < 2.0.0)
|
||||
terminal-table (>= 1.4.5, < 2.0.0)
|
||||
tty-screen (~> 0.5.0)
|
||||
word_wrap (~> 1.0.0)
|
||||
xcodeproj (>= 1.4.4, < 2.0.0)
|
||||
xcpretty (>= 0.2.4, < 1.0.0)
|
||||
xcpretty-travis-formatter (>= 0.0.3)
|
||||
fourflusher (2.0.1)
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.0.3)
|
||||
google-api-client (0.12.0)
|
||||
addressable (~> 2.5, >= 2.5.1)
|
||||
googleauth (~> 0.5)
|
||||
httpclient (>= 2.8.1, < 3.0)
|
||||
mime-types (~> 3.0)
|
||||
representable (~> 3.0)
|
||||
retriable (>= 2.0, < 4.0)
|
||||
googleauth (0.5.1)
|
||||
faraday (~> 0.9)
|
||||
jwt (~> 1.4)
|
||||
logging (~> 2.0)
|
||||
memoist (~> 0.12)
|
||||
multi_json (~> 1.11)
|
||||
os (~> 0.9)
|
||||
signet (~> 0.7)
|
||||
highline (1.7.8)
|
||||
http-cookie (1.0.3)
|
||||
domain_name (~> 0.5)
|
||||
httpclient (2.8.3)
|
||||
i18n (0.8.6)
|
||||
json (2.1.0)
|
||||
jwt (1.5.6)
|
||||
little-plugger (1.1.4)
|
||||
logging (2.2.2)
|
||||
little-plugger (~> 1.1)
|
||||
multi_json (~> 1.10)
|
||||
memoist (0.16.0)
|
||||
mime-types (3.1)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2016.0521)
|
||||
mini_magick (4.5.1)
|
||||
minitest (5.10.2)
|
||||
molinillo (0.5.7)
|
||||
multi_json (1.12.1)
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.0.0)
|
||||
nanaimo (0.2.3)
|
||||
nap (1.1.0)
|
||||
netrc (0.7.8)
|
||||
os (0.9.6)
|
||||
plist (3.3.0)
|
||||
public_suffix (2.0.5)
|
||||
representable (3.0.4)
|
||||
declarative (< 0.1.0)
|
||||
declarative-option (< 0.2.0)
|
||||
uber (< 0.2.0)
|
||||
retriable (3.0.2)
|
||||
rouge (2.0.7)
|
||||
ruby-macho (1.1.0)
|
||||
rubyzip (1.2.1)
|
||||
security (0.1.3)
|
||||
signet (0.7.3)
|
||||
addressable (~> 2.3)
|
||||
faraday (~> 0.9)
|
||||
jwt (~> 1.5)
|
||||
multi_json (~> 1.10)
|
||||
slack-notifier (1.5.1)
|
||||
terminal-notifier (1.8.0)
|
||||
terminal-table (1.8.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
thread_safe (0.3.6)
|
||||
tty-screen (0.5.0)
|
||||
tzinfo (1.2.3)
|
||||
thread_safe (~> 0.1)
|
||||
uber (0.1.0)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.7.4)
|
||||
unicode-display_width (1.3.0)
|
||||
word_wrap (1.0.0)
|
||||
xcodeproj (1.5.0)
|
||||
CFPropertyList (~> 2.3.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
nanaimo (~> 0.2.3)
|
||||
xcpretty (0.2.8)
|
||||
rouge (~> 2.0.7)
|
||||
xcpretty-travis-formatter (0.0.4)
|
||||
xcpretty (~> 0.2, >= 0.0.7)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
cocoapods
|
||||
fastlane
|
||||
|
||||
BUNDLED WITH
|
||||
1.14.6
|
||||
7
Makefile
7
Makefile
@ -14,11 +14,9 @@ default: test
|
||||
|
||||
test: pod_install retest
|
||||
|
||||
scan_test: pod_install scan
|
||||
|
||||
pod_install:
|
||||
cd $(WORKING_DIR) && \
|
||||
bundle exec pod install
|
||||
pod install
|
||||
|
||||
build: pod_install
|
||||
cd $(WORKING_DIR) && \
|
||||
@ -30,9 +28,6 @@ retest: optional_early_start_simulator
|
||||
-destination '${BUILD_DESTINATION}' \
|
||||
test | xcpretty
|
||||
|
||||
scan:
|
||||
bundle exec fastlane scan
|
||||
|
||||
clean:
|
||||
cd $(WORKING_DIR) && \
|
||||
$(XCODE_BUILD) \
|
||||
|
||||
24
README.md
24
README.md
@ -1,27 +1,3 @@
|
||||
# SignalServiceKit has Moved
|
||||
|
||||
Per https://github.com/WhisperSystems/Signal-iOS/pull/2341 we've moved
|
||||
the SignalServiceKit codebase into the primary Signal-iOS repository at
|
||||
https://github.com/WhisperSystems/Signal-iOS. As such, this repository
|
||||
will no longer be updated.
|
||||
|
||||
Don't worry - we will continue to make updates to SignalServiceKit, and
|
||||
you can continue to use it in your projects as before. The only
|
||||
difference is where the code lives.
|
||||
|
||||
If you are using Cocoapods, staying up to date is as simple as modifying
|
||||
a line in your Podfile from this:
|
||||
|
||||
```
|
||||
- pod 'SignalServiceKit', git: 'https://github.com/WhisperSystems/SignalServiceKit.git'
|
||||
```
|
||||
|
||||
To this:
|
||||
|
||||
```
|
||||
+ pod 'SignalServiceKit', git: 'https://github.com/WhisperSystems/Signal-iOS.git'
|
||||
```
|
||||
|
||||
# SignalServiceKit
|
||||
|
||||
SignalServiceKit is an Objective-C library for communicating with the Signal
|
||||
|
||||
@ -17,37 +17,15 @@ An Objective-C library for communicating with the Signal messaging service.
|
||||
|
||||
s.homepage = "https://github.com/WhisperSystems/SignalServiceKit"
|
||||
s.license = 'GPLv3'
|
||||
s.author = { "Whisper Systems" => "ios@whispersystems.com" }
|
||||
s.author = { "Frederic Jacobs" => "github@fredericjacobs.com" }
|
||||
s.source = { :git => "https://github.com/WhisperSystems/SignalServiceKit.git", :tag => s.version.to_s }
|
||||
s.social_media_url = 'https://twitter.com/WhipserSystems'
|
||||
|
||||
deprecation_message = <<EOS
|
||||
installing SignalServiceKit via the Signal-iOS repository.
|
||||
|
||||
To get future updates, point your Podfile at the new location. Simply change this:
|
||||
|
||||
pod 'SignalServiceKit', git: 'https://github.com/WhisperSystems/SignalServiceKit.git'
|
||||
|
||||
To this:
|
||||
|
||||
pod 'SignalServiceKit', git: 'https://github.com/WhisperSystems/Signal-iOS.git'
|
||||
|
||||
Sorry for the disruption!
|
||||
|
||||
EOS
|
||||
|
||||
s.deprecated_in_favor_of = deprecation_message
|
||||
s.social_media_url = 'https://twitter.com/FredericJacobs'
|
||||
|
||||
s.platform = :ios, '8.0'
|
||||
#s.ios.deployment_target = '8.0'
|
||||
#s.osx.deployment_target = '10.9'
|
||||
s.requires_arc = true
|
||||
|
||||
# By not including any actual files, upgrading users will see
|
||||
# that they need to point upgrades to the new source at
|
||||
# https://github.com/WhisperSystems/Signal-iOS
|
||||
# Details in README.md
|
||||
s.source_files = 'README.md'
|
||||
s.source_files = 'src/**/*.{h,m,mm}'
|
||||
|
||||
s.resources = ['src/Security/PinningCertificate/textsecure.cer',
|
||||
'src/Security/PinningCertificate/GIAG2.crt']
|
||||
|
||||
1
fastlane/.gitignore
vendored
1
fastlane/.gitignore
vendored
@ -1 +0,0 @@
|
||||
test_output
|
||||
@ -1,8 +0,0 @@
|
||||
# For more information about this configuration visit
|
||||
# https://github.com/fastlane/fastlane/tree/master/scan#scanfile
|
||||
|
||||
workspace "Example/TSKitiOSTestApp/TSKitiOSTestApp.xcworkspace"
|
||||
scheme "TSKitiOSTestApp"
|
||||
|
||||
devices ["iPhone SE"]
|
||||
|
||||
@ -34,24 +34,6 @@ message Content {
|
||||
optional DataMessage dataMessage = 1;
|
||||
optional SyncMessage syncMessage = 2;
|
||||
optional CallMessage callMessage = 3;
|
||||
optional NullMessage nullMessage = 4;
|
||||
}
|
||||
|
||||
message NullMessage {
|
||||
optional bytes padding = 1;
|
||||
}
|
||||
|
||||
message Verified {
|
||||
enum State {
|
||||
DEFAULT = 0;
|
||||
VERIFIED = 1;
|
||||
UNVERIFIED = 2;
|
||||
}
|
||||
|
||||
optional string destination = 1;
|
||||
optional bytes identityKey = 2;
|
||||
optional State state = 3;
|
||||
optional bytes nullMessage = 4;
|
||||
}
|
||||
|
||||
message CallMessage {
|
||||
@ -142,13 +124,25 @@ message SyncMessage {
|
||||
optional uint64 timestamp = 2;
|
||||
}
|
||||
|
||||
message Verified {
|
||||
enum State {
|
||||
DEFAULT = 0;
|
||||
VERIFIED = 1;
|
||||
UNVERIFIED = 2;
|
||||
}
|
||||
|
||||
optional string destination = 1;
|
||||
optional bytes identityKey = 2;
|
||||
optional State state = 3;
|
||||
}
|
||||
|
||||
optional Sent sent = 1;
|
||||
optional Contacts contacts = 2;
|
||||
optional Groups groups = 3;
|
||||
optional Request request = 4;
|
||||
repeated Read read = 5;
|
||||
optional Blocked blocked = 6;
|
||||
optional Verified verified = 7;
|
||||
repeated Verified verified = 7;
|
||||
optional bytes padding = 8;
|
||||
}
|
||||
|
||||
@ -192,7 +186,6 @@ message ContactDetails {
|
||||
optional string name = 2;
|
||||
optional Avatar avatar = 3;
|
||||
optional string color = 4;
|
||||
optional Verified verified = 5;
|
||||
}
|
||||
|
||||
message GroupDetails {
|
||||
|
||||
@ -244,12 +244,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (NSArray<NSString *> *)textSecureIdentifiers {
|
||||
__block NSMutableArray *identifiers = [NSMutableArray array];
|
||||
|
||||
[[TSStorageManager sharedManager].dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
for (PhoneNumber *number in self.parsedPhoneNumbers) {
|
||||
if ([SignalRecipient recipientWithTextSecureIdentifier:number.toE164 withTransaction:transaction]) {
|
||||
[identifiers addObject:number.toE164];
|
||||
}
|
||||
}
|
||||
[[TSStorageManager sharedManager]
|
||||
.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
for (PhoneNumber *number in self.parsedPhoneNumbers) {
|
||||
if ([SignalRecipient recipientWithTextSecureIdentifier:number.toE164 withTransaction:transaction]) {
|
||||
[identifiers addObject:number.toE164];
|
||||
}
|
||||
}
|
||||
}];
|
||||
return [identifiers copy];
|
||||
}
|
||||
|
||||
@ -122,11 +122,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
}
|
||||
|
||||
NSMutableSet *recipientIds = [NSMutableSet set];
|
||||
[[TSStorageManager sharedManager].dbReadConnection
|
||||
readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
NSArray *allRecipientKeys = [transaction allKeysInCollection:[SignalRecipient collection]];
|
||||
[recipientIds addObjectsFromArray:allRecipientKeys];
|
||||
}];
|
||||
[[TSStorageManager sharedManager]
|
||||
.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
NSArray *allRecipientKeys = [transaction allKeysInCollection:[SignalRecipient collection]];
|
||||
[recipientIds addObjectsFromArray:allRecipientKeys];
|
||||
}];
|
||||
|
||||
NSMutableSet<NSString *> *allContacts = [[abPhoneNumbers setByAddingObjectsFromSet:recipientIds] mutableCopy];
|
||||
|
||||
@ -135,7 +135,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
[recipientIds minusSet:matchedIds];
|
||||
|
||||
// Cleaning up unregistered identifiers
|
||||
[[TSStorageManager sharedManager].dbReadWriteConnection
|
||||
[[TSStorageManager sharedManager].dbConnection
|
||||
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
for (NSString *identifier in recipientIds) {
|
||||
SignalRecipient *recipient =
|
||||
@ -185,22 +185,23 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
}
|
||||
|
||||
// Insert or update contact attributes
|
||||
[[TSStorageManager sharedManager].dbReadWriteConnection
|
||||
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
for (NSString *identifier in attributesForIdentifier) {
|
||||
SignalRecipient *recipient =
|
||||
[SignalRecipient recipientWithTextSecureIdentifier:identifier withTransaction:transaction];
|
||||
if (!recipient) {
|
||||
recipient = [[SignalRecipient alloc] initWithTextSecureIdentifier:identifier relay:nil];
|
||||
}
|
||||
[[TSStorageManager sharedManager]
|
||||
.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
for (NSString *identifier in attributesForIdentifier) {
|
||||
SignalRecipient *recipient =
|
||||
[SignalRecipient recipientWithTextSecureIdentifier:identifier withTransaction:transaction];
|
||||
if (!recipient) {
|
||||
recipient = [[SignalRecipient alloc] initWithTextSecureIdentifier:identifier
|
||||
relay:nil];
|
||||
}
|
||||
|
||||
NSDictionary *attributes = [attributesForIdentifier objectForKey:identifier];
|
||||
NSDictionary *attributes = [attributesForIdentifier objectForKey:identifier];
|
||||
|
||||
recipient.relay = attributes[@"relay"];
|
||||
recipient.relay = attributes[@"relay"];
|
||||
|
||||
[recipient saveWithTransaction:transaction];
|
||||
}
|
||||
}];
|
||||
[recipient saveWithTransaction:transaction];
|
||||
}
|
||||
}];
|
||||
|
||||
success([NSSet setWithArray:attributesForIdentifier.allKeys]);
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ static NSString *const RPDefaultsKeyPhoneNumberCanonical = @"RPDefaultsKeyPhoneN
|
||||
NBPhoneNumber *number = [phoneUtil parse:text defaultRegion:regionCode error:&parseError];
|
||||
|
||||
if (parseError) {
|
||||
DDLogDebug(@"Issue while parsing number: %@", [parseError description]);
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
@ -85,9 +85,6 @@
|
||||
NSDictionary *countryCodeComponent = @{NSLocaleCountryCode : countryCode};
|
||||
NSString *identifier = [NSLocale localeIdentifierFromComponents:countryCodeComponent];
|
||||
NSString *country = [NSLocale.currentLocale displayNameForKey:NSLocaleIdentifier value:identifier];
|
||||
if (country.length < 1) {
|
||||
country = [NSLocale.systemLocale displayNameForKey:NSLocaleIdentifier value:identifier];
|
||||
}
|
||||
return country;
|
||||
}
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
+ (nullable instancetype)recipientWithTextSecureIdentifier:(NSString *)textSecureIdentifier
|
||||
{
|
||||
__block SignalRecipient *recipient;
|
||||
[self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
recipient = [self recipientWithTextSecureIdentifier:textSecureIdentifier withTransaction:transaction];
|
||||
}];
|
||||
return recipient;
|
||||
|
||||
@ -131,7 +131,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (void)enumerateInteractionsUsingBlock:(void (^)(TSInteraction *interaction))block
|
||||
{
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self enumerateInteractionsWithTransaction:transaction
|
||||
usingBlock:^(
|
||||
TSInteraction *interaction, YapDatabaseReadTransaction *transaction) {
|
||||
@ -172,7 +172,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (NSUInteger)numberOfInteractions
|
||||
{
|
||||
__block NSUInteger count;
|
||||
[[self dbReadConnection] readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
[[self dbConnection] readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
YapDatabaseViewTransaction *interactionsByThread = [transaction ext:TSMessageDatabaseViewExtensionName];
|
||||
count = [interactionsByThread numberOfItemsInGroup:self.uniqueId];
|
||||
}];
|
||||
@ -237,7 +237,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (TSInteraction *) lastInteraction {
|
||||
__block TSInteraction *last;
|
||||
[TSStorageManager.sharedManager.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
[TSStorageManager.sharedManager.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction){
|
||||
last = [[transaction ext:TSMessageDatabaseViewExtensionName] lastObjectInGroup:self.uniqueId];
|
||||
}];
|
||||
return last;
|
||||
@ -246,7 +246,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (TSInteraction *)lastInteractionForInbox
|
||||
{
|
||||
__block TSInteraction *last = nil;
|
||||
[TSStorageManager.sharedManager.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
[TSStorageManager.sharedManager.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
[[transaction ext:TSMessageDatabaseViewExtensionName]
|
||||
enumerateRowsInGroup:self.uniqueId
|
||||
withOptions:NSEnumerationReverse
|
||||
@ -289,6 +289,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
OWSAssert(interaction);
|
||||
|
||||
if (interaction.isDynamicInteraction) {
|
||||
DDLogDebug(@"%@ not showing dynamic interaction in inbox: %@", self.tag, interaction.debugDescription);
|
||||
return NO;
|
||||
}
|
||||
|
||||
@ -297,11 +298,15 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
if (errorMessage.errorType == TSErrorMessageNonBlockingIdentityChange) {
|
||||
// Otherwise all group threads with the recipient will percolate to the top of the inbox, even though
|
||||
// there was no meaningful interaction.
|
||||
DDLogDebug(
|
||||
@"%@ not showing nonblocking identity change in inbox: %@", self.tag, errorMessage.debugDescription);
|
||||
return NO;
|
||||
}
|
||||
} else if ([interaction isKindOfClass:[TSInfoMessage class]]) {
|
||||
TSInfoMessage *infoMessage = (TSInfoMessage *)interaction;
|
||||
if (infoMessage.messageType == TSInfoMessageVerificationStateChange) {
|
||||
DDLogDebug(
|
||||
@"%@ not showing verification state change in inbox: %@", self.tag, infoMessage.debugDescription);
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
@ -397,7 +402,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (void)updateWithMutedUntilDate:(NSDate *)mutedUntilDate
|
||||
{
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self applyChangeToSelfAndLatestThread:transaction
|
||||
changeBlock:^(TSThread *thread) {
|
||||
[thread setMutedUntilDate:mutedUntilDate];
|
||||
|
||||
@ -76,7 +76,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
OWSAssert(contactId.length > 0);
|
||||
|
||||
__block TSContactThread *thread;
|
||||
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[[self dbConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
thread = [self getOrCreateThreadWithContactId:contactId transaction:transaction];
|
||||
}];
|
||||
|
||||
|
||||
@ -91,7 +91,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
OWSAssert(groupModel.groupId.length > 0);
|
||||
|
||||
__block TSGroupThread *thread;
|
||||
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[[self dbConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
thread = [self getOrCreateThreadWithGroupModel:groupModel transaction:transaction];
|
||||
}];
|
||||
return thread;
|
||||
|
||||
@ -27,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return self;
|
||||
}
|
||||
|
||||
- (OWSSignalServiceProtosSyncMessageBuilder *)syncMessageBuilder
|
||||
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
|
||||
{
|
||||
OWSSignalServiceProtosSyncMessageBlockedBuilder *blockedPhoneNumbersBuilder =
|
||||
[OWSSignalServiceProtosSyncMessageBlockedBuilder new];
|
||||
@ -35,7 +35,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
|
||||
[syncMessageBuilder setBlocked:[blockedPhoneNumbersBuilder build]];
|
||||
|
||||
return syncMessageBuilder;
|
||||
return [syncMessageBuilder build];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -7,12 +7,10 @@
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class SignalAccount;
|
||||
@class OWSRecipientIdentity;
|
||||
|
||||
@interface OWSContactsOutputStream : OWSChunkedOutputStream
|
||||
|
||||
- (void)writeSignalAccount:(SignalAccount *)signalAccount
|
||||
recipientIdentity:(nullable OWSRecipientIdentity *)recipientIdentity;
|
||||
- (void)writeSignalAccount:(SignalAccount *)signalAccount;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@ -5,8 +5,6 @@
|
||||
#import "OWSContactsOutputStream.h"
|
||||
#import "Contact.h"
|
||||
#import "MIMETypeUtil.h"
|
||||
#import "NSData+keyVersionByte.h"
|
||||
#import "OWSRecipientIdentity.h"
|
||||
#import "OWSSignalServiceProtos.pb.h"
|
||||
#import "SignalAccount.h"
|
||||
#import <ProtocolBuffers/CodedOutputStream.h>
|
||||
@ -16,23 +14,14 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@implementation OWSContactsOutputStream
|
||||
|
||||
- (void)writeSignalAccount:(SignalAccount *)signalAccount
|
||||
recipientIdentity:(nullable OWSRecipientIdentity *)recipientIdentity
|
||||
{
|
||||
OWSAssert(signalAccount);
|
||||
OWSAssert(signalAccount.contact);
|
||||
|
||||
|
||||
OWSSignalServiceProtosContactDetailsBuilder *contactBuilder = [OWSSignalServiceProtosContactDetailsBuilder new];
|
||||
[contactBuilder setName:signalAccount.contact.fullName];
|
||||
[contactBuilder setNumber:signalAccount.recipientId];
|
||||
|
||||
if (recipientIdentity != nil) {
|
||||
OWSSignalServiceProtosVerifiedBuilder *verifiedBuilder = [OWSSignalServiceProtosVerifiedBuilder new];
|
||||
verifiedBuilder.destination = recipientIdentity.recipientId;
|
||||
verifiedBuilder.identityKey = [recipientIdentity.identityKey prependKeyType];
|
||||
verifiedBuilder.state = OWSVerificationStateToProtoState(recipientIdentity.verificationState);
|
||||
contactBuilder.verifiedBuilder = verifiedBuilder;
|
||||
}
|
||||
|
||||
NSData *avatarPng;
|
||||
if (signalAccount.contact.image) {
|
||||
OWSSignalServiceProtosContactDetailsAvatarBuilder *avatarBuilder =
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSReadReceipt.h"
|
||||
#import <YapDatabase/YapDatabase.h>
|
||||
@ -106,7 +104,7 @@ NSString *const OWSReadReceiptColumnSenderId = @"senderId";
|
||||
stringWithFormat:@"WHERE %@ = ? AND %@ = ?", OWSReadReceiptColumnSenderId, OWSReadReceiptColumnTimestamp];
|
||||
YapDatabaseQuery *query = [YapDatabaseQuery queryWithFormat:queryFormat, senderId, @(timestamp)];
|
||||
|
||||
[[self dbReadConnection] readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
[[self dbConnection] readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
[[transaction ext:OWSReadReceiptIndexOnSenderIdAndTimestamp]
|
||||
enumerateKeysAndObjectsMatchingQuery:query
|
||||
usingBlock:^(NSString *collection, NSString *key, id object, BOOL *stop) {
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSReadReceiptsMessage.h"
|
||||
#import "OWSReadReceipt.h"
|
||||
@ -28,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return self;
|
||||
}
|
||||
|
||||
- (OWSSignalServiceProtosSyncMessageBuilder *)syncMessageBuilder
|
||||
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
|
||||
{
|
||||
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
|
||||
for (OWSReadReceipt *readReceipt in self.readReceipts) {
|
||||
@ -39,7 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
[syncMessageBuilder addRead:[readProtoBuilder build]];
|
||||
}
|
||||
|
||||
return syncMessageBuilder;
|
||||
return [syncMessageBuilder build];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -94,8 +94,7 @@ NSString *const OWSReadReceiptsProcessorMarkedMessageAsReadNotification =
|
||||
// Always mark the message specified by the read receipt as read.
|
||||
[interactionsToMarkAsRead addObject:message];
|
||||
|
||||
[self.storageManager.dbReadWriteConnection readWriteWithBlock:^(
|
||||
YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.storageManager.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[[TSDatabaseView unseenDatabaseViewExtension:transaction]
|
||||
enumerateRowsInGroup:message.uniqueThreadId
|
||||
usingBlock:^(NSString *collection,
|
||||
|
||||
@ -9,15 +9,12 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSVerificationStateSyncMessage : OWSOutgoingSyncMessage
|
||||
|
||||
- (instancetype)initWithVerificationState:(OWSVerificationState)verificationState
|
||||
identityKey:(NSData *)identityKey
|
||||
verificationForRecipientId:(NSString *)recipientId;
|
||||
- (void)addVerificationState:(OWSVerificationState)verificationState
|
||||
identityKey:(NSData *)identityKey
|
||||
recipientId:(NSString *)recipientId;
|
||||
|
||||
// This is a clunky name, but we want to differentiate it from `recipientIdentifier` inherited from `TSOutgoingMessage`
|
||||
@property (nonatomic, readonly) NSString *verificationForRecipientId;
|
||||
|
||||
@property (nonatomic, readonly) size_t paddingBytesLength;
|
||||
@property (nonatomic, readonly) size_t unpaddedVerifiedLength;
|
||||
// Returns the list of recipient ids referenced in this message.
|
||||
- (NSArray<NSString *> *)recipientIds;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@ -9,12 +9,25 @@
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSVerificationStateTuple : NSObject
|
||||
|
||||
@property (nonatomic) OWSVerificationState verificationState;
|
||||
@property (nonatomic) NSData *identityKey;
|
||||
@property (nonatomic) NSString *recipientId;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation OWSVerificationStateTuple
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@interface OWSVerificationStateSyncMessage ()
|
||||
|
||||
@property (nonatomic, readonly) OWSVerificationState verificationState;
|
||||
@property (nonatomic, readonly) NSData *identityKey;
|
||||
@property (nonatomic, readonly) NSMutableArray<OWSVerificationStateTuple *> *tuples;
|
||||
|
||||
@end
|
||||
|
||||
@ -22,78 +35,72 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation OWSVerificationStateSyncMessage
|
||||
|
||||
- (instancetype)initWithVerificationState:(OWSVerificationState)verificationState
|
||||
identityKey:(NSData *)identityKey
|
||||
verificationForRecipientId:(NSString *)verificationForRecipientId
|
||||
- (instancetype)init
|
||||
{
|
||||
OWSAssert(identityKey.length == kIdentityKeyLength);
|
||||
OWSAssert(verificationForRecipientId.length > 0);
|
||||
|
||||
// we only sync user's marking as un/verified. Never sync the conflicted state, the sibling device
|
||||
// will figure that out on it's own.
|
||||
OWSAssert(verificationState != OWSVerificationStateNoLongerVerified);
|
||||
|
||||
self = [super init];
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
_verificationState = verificationState;
|
||||
_identityKey = identityKey;
|
||||
_verificationForRecipientId = verificationForRecipientId;
|
||||
|
||||
// This sync message should be 1-512 bytes longer than the corresponding NullMessage
|
||||
// we store this values so the corresponding NullMessage can subtract it from the total length.
|
||||
_paddingBytesLength = arc4random_uniform(512) + 1;
|
||||
|
||||
_tuples = [NSMutableArray new];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (OWSSignalServiceProtosSyncMessageBuilder *)syncMessageBuilder
|
||||
- (void)addVerificationState:(OWSVerificationState)verificationState
|
||||
identityKey:(NSData *)identityKey
|
||||
recipientId:(NSString *)recipientId
|
||||
{
|
||||
OWSAssert(self.identityKey.length == kIdentityKeyLength);
|
||||
OWSAssert(self.verificationForRecipientId.length > 0);
|
||||
OWSAssert(identityKey.length == kIdentityKeyLength);
|
||||
OWSAssert(recipientId.length > 0);
|
||||
OWSAssert(self.tuples);
|
||||
|
||||
// we only sync user's marking as un/verified. Never sync the conflicted state, the sibling device
|
||||
// will figure that out on it's own.
|
||||
OWSAssert(self.verificationState != OWSVerificationStateNoLongerVerified);
|
||||
|
||||
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
|
||||
|
||||
OWSSignalServiceProtosVerifiedBuilder *verifiedBuilder = [OWSSignalServiceProtosVerifiedBuilder new];
|
||||
verifiedBuilder.destination = self.verificationForRecipientId;
|
||||
verifiedBuilder.identityKey = self.identityKey;
|
||||
verifiedBuilder.state = OWSVerificationStateToProtoState(self.verificationState);
|
||||
|
||||
OWSAssert(self.paddingBytesLength != 0);
|
||||
|
||||
// We add the same amount of padding in the VerificationStateSync message and it's coresponding NullMessage so that
|
||||
// the sync message is indistinguishable from an outgoing Sent transcript corresponding to the NullMessage. We pad
|
||||
// the NullMessage so as to obscure it's content. The sync message (like all sync messages) will be *additionally*
|
||||
// padded by the superclass while being sent. The end result is we send a NullMessage of a non-distinct size, and a
|
||||
// verification sync which is ~1-512 bytes larger then that.
|
||||
verifiedBuilder.nullMessage = [Cryptography generateRandomBytes:self.paddingBytesLength];
|
||||
|
||||
syncMessageBuilder.verifiedBuilder = verifiedBuilder;
|
||||
|
||||
return syncMessageBuilder;
|
||||
OWSVerificationStateTuple *tuple = [OWSVerificationStateTuple new];
|
||||
tuple.verificationState = verificationState;
|
||||
tuple.identityKey = identityKey;
|
||||
tuple.recipientId = recipientId;
|
||||
[self.tuples addObject:tuple];
|
||||
}
|
||||
|
||||
- (size_t)unpaddedVerifiedLength
|
||||
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
|
||||
{
|
||||
OWSAssert(self.identityKey.length == kIdentityKeyLength);
|
||||
OWSAssert(self.verificationForRecipientId.length > 0);
|
||||
OWSAssert(self.tuples.count > 0);
|
||||
|
||||
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
|
||||
for (OWSVerificationStateTuple *tuple in self.tuples) {
|
||||
OWSSignalServiceProtosSyncMessageVerifiedBuilder *verifiedBuilder = [OWSSignalServiceProtosSyncMessageVerifiedBuilder new];
|
||||
verifiedBuilder.destination = tuple.recipientId;
|
||||
verifiedBuilder.identityKey = tuple.identityKey;
|
||||
switch (tuple.verificationState) {
|
||||
case OWSVerificationStateDefault:
|
||||
verifiedBuilder.state = OWSSignalServiceProtosSyncMessageVerifiedStateDefault;
|
||||
break;
|
||||
case OWSVerificationStateVerified:
|
||||
verifiedBuilder.state = OWSSignalServiceProtosSyncMessageVerifiedStateVerified;
|
||||
break;
|
||||
case OWSVerificationStateNoLongerVerified:
|
||||
verifiedBuilder.state = OWSSignalServiceProtosSyncMessageVerifiedStateUnverified;
|
||||
break;
|
||||
}
|
||||
[syncMessageBuilder addVerified:[verifiedBuilder build]];
|
||||
}
|
||||
|
||||
// we only sync user's marking as un/verified. Never sync the conflicted state, the sibling device
|
||||
// will figure that out on it's own.
|
||||
OWSAssert(self.verificationState != OWSVerificationStateNoLongerVerified);
|
||||
// Add 1-512 bytes of random padding bytes.
|
||||
size_t paddingLengthBytes = arc4random_uniform(512) + 1;
|
||||
[syncMessageBuilder setPadding:[Cryptography generateRandomBytes:paddingLengthBytes]];
|
||||
|
||||
OWSSignalServiceProtosVerifiedBuilder *verifiedBuilder = [OWSSignalServiceProtosVerifiedBuilder new];
|
||||
verifiedBuilder.destination = self.verificationForRecipientId;
|
||||
verifiedBuilder.identityKey = self.identityKey;
|
||||
verifiedBuilder.state = OWSVerificationStateToProtoState(self.verificationState);
|
||||
return [syncMessageBuilder build];
|
||||
}
|
||||
|
||||
return [verifiedBuilder build].data.length;
|
||||
- (NSArray<NSString *> *)recipientIds
|
||||
{
|
||||
NSMutableArray<NSString *> *result = [NSMutableArray new];
|
||||
for (OWSVerificationStateTuple *tuple in self.tuples) {
|
||||
OWSAssert(tuple.recipientId.length > 0);
|
||||
[result addObject:tuple.recipientId];
|
||||
}
|
||||
|
||||
return [result copy];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -27,8 +27,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
// This only applies for attachments being uploaded.
|
||||
@property (atomic) BOOL isUploaded;
|
||||
|
||||
@property (nonatomic, readonly) NSDate *creationTimestamp;
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
- (nullable UIImage *)image;
|
||||
#endif
|
||||
@ -46,6 +44,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
+ (void)deleteAttachments;
|
||||
+ (NSString *)attachmentsFolder;
|
||||
+ (NSUInteger)numberOfItemsInAttachmentsFolder;
|
||||
|
||||
- (CGSize)imageSizeWithTransaction:(YapDatabaseReadWriteTransaction *)transaction;
|
||||
- (CGSize)imageSizeWithoutTransaction;
|
||||
|
||||
@ -41,7 +41,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
// state, but this constructor is used only for new outgoing
|
||||
// attachments which haven't been uploaded yet.
|
||||
_isUploaded = NO;
|
||||
_creationTimestamp = [NSDate new];
|
||||
|
||||
[self ensureFilePath];
|
||||
|
||||
@ -63,7 +62,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
// attachments which don't need to be uploaded.
|
||||
_isUploaded = YES;
|
||||
self.attachmentType = pointer.attachmentType;
|
||||
_creationTimestamp = [NSDate new];
|
||||
|
||||
[self ensureFilePath];
|
||||
|
||||
@ -77,14 +75,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return self;
|
||||
}
|
||||
|
||||
// OWS105AttachmentFilePaths will ensure the file path is saved if necessary.
|
||||
[self ensureFilePath];
|
||||
|
||||
// OWS105AttachmentFilePaths will ensure the creation timestamp is saved if necessary.
|
||||
if (!_creationTimestamp) {
|
||||
_creationTimestamp = [NSDate new];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -189,6 +181,19 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return attachmentsFolder;
|
||||
}
|
||||
|
||||
+ (NSUInteger)numberOfItemsInAttachmentsFolder
|
||||
{
|
||||
NSError *error;
|
||||
NSUInteger count =
|
||||
[[[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self attachmentsFolder] error:&error] count];
|
||||
|
||||
if (error) {
|
||||
DDLogError(@"Unable to count attachments in attachments folder. Error: %@", error);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
- (nullable NSString *)filePath
|
||||
{
|
||||
if (!self.localRelativeFilePath) {
|
||||
@ -281,28 +286,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
+ (void)deleteAttachments
|
||||
{
|
||||
NSError *error;
|
||||
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
|
||||
NSURL *fileURL = [NSURL fileURLWithPath:self.attachmentsFolder];
|
||||
NSArray<NSURL *> *contents =
|
||||
[fileManager contentsOfDirectoryAtURL:fileURL includingPropertiesForKeys:nil options:0 error:&error];
|
||||
|
||||
[[NSFileManager defaultManager] removeItemAtPath:[self attachmentsFolder] error:&error];
|
||||
if (error) {
|
||||
OWSFail(@"failed to get contents of attachments folder: %@ with error: %@", self.attachmentsFolder, error);
|
||||
return;
|
||||
DDLogError(@"Failed to delete attachment folder with error: %@", error.debugDescription);
|
||||
}
|
||||
|
||||
for (NSURL *url in contents) {
|
||||
NSError *deletionError;
|
||||
[fileManager removeItemAtURL:url error:&deletionError];
|
||||
if (deletionError) {
|
||||
OWSFail(@"failed to remove item at path: %@ with error: %@", url, deletionError);
|
||||
// continue to try to delete remaining items.
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
- (CGSize)calculateImageSize
|
||||
@ -374,7 +361,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
if (transaction) {
|
||||
updateDataStore(transaction);
|
||||
} else {
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
updateDataStore(transaction);
|
||||
}];
|
||||
}
|
||||
@ -445,7 +432,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
if (transaction) {
|
||||
updateDataStore(transaction);
|
||||
} else {
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
updateDataStore(transaction);
|
||||
}];
|
||||
}
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSOutgoingSentMessageTranscript.h"
|
||||
#import "OWSSignalServiceProtos.pb.h"
|
||||
@ -39,7 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return self;
|
||||
}
|
||||
|
||||
- (OWSSignalServiceProtosSyncMessageBuilder *)syncMessageBuilder
|
||||
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
|
||||
{
|
||||
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
|
||||
|
||||
@ -51,7 +49,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
[syncMessageBuilder setSentBuilder:sentBuilder];
|
||||
|
||||
return syncMessageBuilder;
|
||||
return [syncMessageBuilder build];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
|
||||
#import "OWSOutgoingSyncMessage.h"
|
||||
#import "OWSSignalServiceProtos.pb.h"
|
||||
#import "Cryptography.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@ -22,22 +21,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return NO;
|
||||
}
|
||||
|
||||
// This method should not be overridden, since we want to add random padding to *every* sync message
|
||||
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
|
||||
{
|
||||
OWSSignalServiceProtosSyncMessageBuilder *builder = [self syncMessageBuilder];
|
||||
|
||||
// Add a random 1-512 bytes to obscure sync message type
|
||||
size_t paddingBytesLength = arc4random_uniform(512) + 1;
|
||||
builder.padding = [Cryptography generateRandomBytes:paddingBytesLength];
|
||||
|
||||
return [builder build];
|
||||
}
|
||||
NSAssert(NO, @"buildSyncMessage must be overridden in subclass");
|
||||
|
||||
- (OWSSignalServiceProtosSyncMessageBuilder *)syncMessageBuilder
|
||||
{
|
||||
OWSFail(@"Abstract method should be overridden in subclass.");
|
||||
return [OWSSignalServiceProtosSyncMessageBuilder new];
|
||||
// e.g.
|
||||
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
|
||||
return [syncMessageBuilder build];
|
||||
}
|
||||
|
||||
- (NSData *)buildPlainTextData
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSOutgoingSyncMessage.h"
|
||||
|
||||
@ -8,13 +6,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class YapDatabaseReadWriteTransaction;
|
||||
@protocol ContactsManagerProtocol;
|
||||
@class OWSIdentityManager;
|
||||
|
||||
@interface OWSSyncContactsMessage : OWSOutgoingSyncMessage
|
||||
|
||||
- (instancetype)initWithContactsManager:(id<ContactsManagerProtocol>)contactsManager
|
||||
identityManager:(OWSIdentityManager *)identityManager;
|
||||
|
||||
- (instancetype)initWithContactsManager:(id<ContactsManagerProtocol>)contactsManager;
|
||||
- (NSData *)buildPlainTextAttachmentData;
|
||||
|
||||
@end
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
#import "NSDate+millisecondTimeStamp.h"
|
||||
#import "OWSContactsOutputStream.h"
|
||||
#import "OWSSignalServiceProtos.pb.h"
|
||||
#import "OWSIdentityManager.h"
|
||||
#import "SignalAccount.h"
|
||||
#import "TSAttachment.h"
|
||||
#import "TSAttachmentStream.h"
|
||||
@ -18,14 +17,12 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@interface OWSSyncContactsMessage ()
|
||||
|
||||
@property (nonatomic, readonly) id<ContactsManagerProtocol> contactsManager;
|
||||
@property (nonatomic, readonly) OWSIdentityManager *identityManager;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OWSSyncContactsMessage
|
||||
|
||||
- (instancetype)initWithContactsManager:(id<ContactsManagerProtocol>)contactsManager
|
||||
identityManager:(OWSIdentityManager *)identityManager
|
||||
{
|
||||
self = [super initWithTimestamp:[NSDate ows_millisecondTimeStamp]];
|
||||
if (!self) {
|
||||
@ -33,12 +30,11 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
}
|
||||
|
||||
_contactsManager = contactsManager;
|
||||
_identityManager = identityManager;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (OWSSignalServiceProtosSyncMessageBuilder *)syncMessageBuilder
|
||||
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
|
||||
{
|
||||
if (self.attachmentIds.count != 1) {
|
||||
DDLogError(@"expected sync contact message to have exactly one attachment, but found %lu",
|
||||
@ -57,7 +53,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
|
||||
[syncMessageBuilder setContactsBuilder:contactsBuilder];
|
||||
|
||||
return syncMessageBuilder;
|
||||
return [syncMessageBuilder build];
|
||||
}
|
||||
|
||||
- (NSData *)buildPlainTextAttachmentData
|
||||
@ -70,9 +66,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
OWSContactsOutputStream *contactsOutputStream = [OWSContactsOutputStream streamWithOutputStream:dataOutputStream];
|
||||
|
||||
for (SignalAccount *signalAccount in self.contactsManager.signalAccounts) {
|
||||
OWSRecipientIdentity *recipientIdentity = [self.identityManager recipientIdentityForRecipientId:signalAccount.recipientId];
|
||||
|
||||
[contactsOutputStream writeSignalAccount:signalAccount recipientIdentity:recipientIdentity];
|
||||
[contactsOutputStream writeSignalAccount:signalAccount];
|
||||
}
|
||||
|
||||
[contactsOutputStream flush];
|
||||
|
||||
@ -19,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return [super initWithTimestamp:[NSDate ows_millisecondTimeStamp]];
|
||||
}
|
||||
|
||||
- (OWSSignalServiceProtosSyncMessageBuilder *)syncMessageBuilder
|
||||
- (OWSSignalServiceProtosSyncMessage *)buildSyncMessage
|
||||
{
|
||||
|
||||
if (self.attachmentIds.count != 1) {
|
||||
@ -37,7 +37,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
OWSSignalServiceProtosSyncMessageBuilder *syncMessageBuilder = [OWSSignalServiceProtosSyncMessageBuilder new];
|
||||
[syncMessageBuilder setGroupsBuilder:groupsBuilder];
|
||||
|
||||
return syncMessageBuilder;
|
||||
return [syncMessageBuilder build];
|
||||
}
|
||||
|
||||
- (NSData *)buildPlainTextAttachmentData
|
||||
|
||||
@ -180,7 +180,7 @@ NSUInteger TSErrorMessageSchemaVersion = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
DDLogDebug(@"%@ marking as read uniqueId: %@ which has timestamp: %llu", self.tag, self.uniqueId, self.timestamp);
|
||||
DDLogInfo(@"%@ marking as read uniqueId: %@ which has timestamp: %llu", self.tag, self.uniqueId, self.timestamp);
|
||||
_read = YES;
|
||||
[self saveWithTransaction:transaction];
|
||||
[self touchThreadWithTransaction:transaction];
|
||||
|
||||
@ -78,7 +78,7 @@ NSString *const TSIncomingMessageWasReadOnThisDeviceNotification = @"TSIncomingM
|
||||
+ (nullable instancetype)findMessageWithAuthorId:(NSString *)authorId timestamp:(uint64_t)timestamp
|
||||
{
|
||||
__block TSIncomingMessage *foundMessage;
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
// In theory we could build a new secondaryIndex for (authorId,timestamp), but in practice there should
|
||||
// be *very* few (millisecond) timestamps with multiple authors.
|
||||
[TSDatabaseSecondaryIndexes
|
||||
@ -127,7 +127,7 @@ NSString *const TSIncomingMessageWasReadOnThisDeviceNotification = @"TSIncomingM
|
||||
return;
|
||||
}
|
||||
|
||||
DDLogDebug(@"%@ marking as read uniqueId: %@ which has timestamp: %llu", self.tag, self.uniqueId, self.timestamp);
|
||||
DDLogInfo(@"%@ marking as read uniqueId: %@ which has timestamp: %llu", self.tag, self.uniqueId, self.timestamp);
|
||||
_read = YES;
|
||||
[self saveWithTransaction:transaction];
|
||||
[self touchThreadWithTransaction:transaction];
|
||||
|
||||
@ -119,7 +119,7 @@ NSUInteger TSInfoMessageSchemaVersion = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
DDLogDebug(@"%@ marking as read uniqueId: %@ which has timestamp: %llu", self.tag, self.uniqueId, self.timestamp);
|
||||
DDLogInfo(@"%@ marking as read uniqueId: %@ which has timestamp: %llu", self.tag, self.uniqueId, self.timestamp);
|
||||
_read = YES;
|
||||
[self saveWithTransaction:transaction];
|
||||
[self touchThreadWithTransaction:transaction];
|
||||
|
||||
@ -245,7 +245,7 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
|
||||
{
|
||||
OWSAssert(error);
|
||||
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self applyChangeToSelfAndLatestOutgoingMessage:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message setMessageState:TSOutgoingMessageStateUnsent];
|
||||
@ -256,7 +256,7 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
|
||||
|
||||
- (void)updateWithMessageState:(TSOutgoingMessageState)messageState
|
||||
{
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self updateWithMessageState:messageState transaction:transaction];
|
||||
}];
|
||||
}
|
||||
@ -274,7 +274,7 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
|
||||
|
||||
- (void)updateWithHasSyncedTranscript:(BOOL)hasSyncedTranscript
|
||||
{
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self applyChangeToSelfAndLatestOutgoingMessage:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message setHasSyncedTranscript:hasSyncedTranscript];
|
||||
@ -295,7 +295,7 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
|
||||
|
||||
- (void)updateWithCustomMessage:(NSString *)customMessage
|
||||
{
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self updateWithCustomMessage:customMessage transaction:transaction];
|
||||
}];
|
||||
}
|
||||
@ -312,14 +312,14 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
|
||||
|
||||
- (void)updateWithWasDelivered
|
||||
{
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self updateWithWasDeliveredWithTransaction:transaction];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)updateWithWasSentAndDelivered
|
||||
{
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self applyChangeToSelfAndLatestOutgoingMessage:transaction
|
||||
changeBlock:^(TSOutgoingMessage *message) {
|
||||
[message setMessageState:TSOutgoingMessageStateSentToService];
|
||||
@ -397,7 +397,7 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
|
||||
|
||||
- (void)updateWithSentRecipient:(NSString *)contactId
|
||||
{
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self updateWithSentRecipient:contactId transaction:transaction];
|
||||
}];
|
||||
}
|
||||
@ -455,6 +455,8 @@ NSString *const kTSOutgoingMessageSentRecipientAll = @"kTSOutgoingMessageSentRec
|
||||
return [[self dataMessageBuilder] build];
|
||||
}
|
||||
|
||||
// For legacy message this is a serialized DataMessage.
|
||||
// For modern messages, e.g. Sync and Call messages, this is a serialized Contact
|
||||
- (NSData *)buildPlainTextData
|
||||
{
|
||||
OWSSignalServiceProtosContentBuilder *contentBuilder = [OWSSignalServiceProtosContentBuilder new];
|
||||
|
||||
@ -17,7 +17,7 @@ extern NSString *const kNSNotificationName_IdentityStateDidChange;
|
||||
extern const NSUInteger kIdentityKeyLength;
|
||||
|
||||
@class OWSRecipientIdentity;
|
||||
@class OWSSignalServiceProtosVerified;
|
||||
@class OWSSignalServiceProtosSyncMessageVerified;
|
||||
|
||||
// This class can be safely accessed and used from any thread.
|
||||
@interface OWSIdentityManager : NSObject <IdentityKeyStore>
|
||||
@ -46,7 +46,10 @@ extern const NSUInteger kIdentityKeyLength;
|
||||
*/
|
||||
- (nullable OWSRecipientIdentity *)untrustedIdentityForSendingToRecipientId:(NSString *)recipientId;
|
||||
|
||||
- (void)processIncomingSyncMessage:(OWSSignalServiceProtosVerified *)verified;
|
||||
// Will try to send a sync message with all verification states.
|
||||
- (void)syncAllVerificationStates;
|
||||
|
||||
- (void)processIncomingSyncMessage:(NSArray<OWSSignalServiceProtosSyncMessageVerified *> *)verifieds;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@ -5,9 +5,7 @@
|
||||
#import "OWSIdentityManager.h"
|
||||
#import "NSDate+millisecondTimeStamp.h"
|
||||
#import "NotificationsProtocol.h"
|
||||
#import "OWSError.h"
|
||||
#import "OWSMessageSender.h"
|
||||
#import "OWSOutgoingNullMessage.h"
|
||||
#import "OWSRecipientIdentity.h"
|
||||
#import "OWSVerificationStateChangeMessage.h"
|
||||
#import "OWSVerificationStateSyncMessage.h"
|
||||
@ -16,7 +14,6 @@
|
||||
#import "TSErrorMessage.h"
|
||||
#import "TSGroupThread.h"
|
||||
#import "TSStorageManager+keyingMaterial.h"
|
||||
#import "TSStorageManager+sessionStore.h"
|
||||
#import "TSStorageManager.h"
|
||||
#import "TextSecureKitEnv.h"
|
||||
#import <25519/Curve25519.h>
|
||||
@ -93,8 +90,12 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
||||
|
||||
OWSSingletonAssert();
|
||||
|
||||
[self observeNotifications];
|
||||
|
||||
// We want to observe these notifications lazily to avoid accessing
|
||||
// the data store in [application: didFinishLaunchingWithOptions:].
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)1.f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
|
||||
[self tryToSyncQueuedVerificationStates];
|
||||
[self observeNotifications];
|
||||
});
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -195,10 +196,6 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
||||
createdAt:[NSDate new]
|
||||
verificationState:verificationState] save];
|
||||
|
||||
dispatch_async([OWSDispatch sessionStoreQueue], ^{
|
||||
[self.storageManager archiveAllSessionsForContact:recipientId];
|
||||
});
|
||||
|
||||
// Cancel any pending verification state sync messages for this recipient.
|
||||
[self clearSyncMessageForRecipientId:recipientId];
|
||||
|
||||
@ -207,6 +204,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
||||
return YES;
|
||||
}
|
||||
|
||||
DDLogDebug(@"%@ no changes for identity saved for recipient: %@", self.tag, recipientId);
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
@ -364,6 +362,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
||||
@synchronized(self)
|
||||
{
|
||||
if (recipientIdentity == nil) {
|
||||
DDLogDebug(@"%@ Trusting previously unknown recipient: %@", self.tag, recipientIdentity.recipientId);
|
||||
return YES;
|
||||
}
|
||||
|
||||
@ -374,6 +373,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
||||
}
|
||||
|
||||
if ([recipientIdentity isFirstKnownKey]) {
|
||||
DDLogDebug(@"%@ trusting first known key for recipient: %@", self.tag, recipientIdentity.recipientId);
|
||||
return YES;
|
||||
}
|
||||
|
||||
@ -385,10 +385,12 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
||||
DDLogWarn(@"%@ not trusting new identity for recipient: %@", self.tag, recipientIdentity.recipientId);
|
||||
return NO;
|
||||
} else {
|
||||
DDLogWarn(@"%@ trusting existing identity for recipient: %@", self.tag, recipientIdentity.recipientId);
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
case OWSVerificationStateVerified:
|
||||
DDLogWarn(@"%@ trusting verified identity for recipient: %@", self.tag, recipientIdentity.recipientId);
|
||||
return YES;
|
||||
case OWSVerificationStateNoLongerVerified:
|
||||
DDLogWarn(@"%@ not trusting no longer verified identity for recipient: %@", self.tag, recipientIdentity.recipientId);
|
||||
@ -415,7 +417,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
||||
[messages addObject:[TSErrorMessage nonblockingIdentityChangeInThread:groupThread recipientId:recipientId]];
|
||||
}
|
||||
|
||||
[self.storageManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.storageManager.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
for (TSMessage *message in messages) {
|
||||
[message saveWithTransaction:transaction];
|
||||
}
|
||||
@ -434,29 +436,17 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
||||
inCollection:OWSIdentityManager_QueuedVerificationStateSyncMessages];
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self tryToSyncQueuedVerificationStates];
|
||||
});
|
||||
[self tryToSyncQueuedVerificationStates];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)tryToSyncQueuedVerificationStates
|
||||
{
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
|
||||
if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive) {
|
||||
// Only try to sync if the app is active to avoid interfering with startup.
|
||||
//
|
||||
// applicationDidBecomeActive: will try to sync again when the app becomes active.
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
@synchronized(self)
|
||||
{
|
||||
NSMutableArray<NSString *> *recipientIds = [NSMutableArray new];
|
||||
[self.storageManager.dbReadWriteConnection readWriteWithBlock:^(
|
||||
YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.storageManager.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction enumerateKeysAndObjectsInCollection:OWSIdentityManager_QueuedVerificationStateSyncMessages
|
||||
usingBlock:^(NSString *_Nonnull recipientId,
|
||||
id _Nonnull object,
|
||||
@ -465,7 +455,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
||||
}];
|
||||
}];
|
||||
|
||||
NSMutableArray<OWSVerificationStateSyncMessage *> *messages = [NSMutableArray new];
|
||||
OWSVerificationStateSyncMessage *message = [OWSVerificationStateSyncMessage new];
|
||||
for (NSString *recipientId in recipientIds) {
|
||||
OWSRecipientIdentity *recipientIdentity = [OWSRecipientIdentity fetchObjectWithUniqueID:recipientId];
|
||||
if (!recipientIdentity) {
|
||||
@ -493,17 +483,53 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
||||
recipientId);
|
||||
continue;
|
||||
}
|
||||
OWSVerificationStateSyncMessage *message = [[OWSVerificationStateSyncMessage alloc]
|
||||
initWithVerificationState:recipientIdentity.verificationState
|
||||
identityKey:identityKey
|
||||
verificationForRecipientId:recipientIdentity.recipientId];
|
||||
[messages addObject:message];
|
||||
[message addVerificationState:recipientIdentity.verificationState
|
||||
identityKey:identityKey
|
||||
recipientId:recipientId];
|
||||
}
|
||||
if (messages.count > 0) {
|
||||
if (message.recipientIds.count > 0) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
for (OWSVerificationStateSyncMessage *message in messages) {
|
||||
[self sendSyncVerificationStateMessage:message];
|
||||
}
|
||||
[self sendSyncVerificationStateMessage:message];
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)syncAllVerificationStates
|
||||
{
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
@synchronized(self)
|
||||
{
|
||||
OWSVerificationStateSyncMessage *message =
|
||||
[OWSVerificationStateSyncMessage new];
|
||||
[OWSRecipientIdentity enumerateCollectionObjectsUsingBlock:^(OWSRecipientIdentity *recipientIdentity, BOOL *stop) {
|
||||
OWSAssert(recipientIdentity);
|
||||
OWSAssert(recipientIdentity.recipientId.length > 0);
|
||||
OWSAssert(recipientIdentity.identityKey.length == kStoredIdentityKeyLength);
|
||||
|
||||
if (recipientIdentity.recipientId.length < 1) {
|
||||
OWSFail(@"Invalid recipient identity for recipientId: %@", recipientIdentity.recipientId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepend key type for transit.
|
||||
// TODO we should just be storing the key type so we don't have to juggle re-adding it.
|
||||
NSData *identityKey = [recipientIdentity.identityKey prependKeyType];
|
||||
if (identityKey.length != kIdentityKeyLength) {
|
||||
OWSFail(@"Invalid recipient identitykey for recipientId: %@ key: %@",
|
||||
recipientIdentity.recipientId,
|
||||
identityKey);
|
||||
return;
|
||||
}
|
||||
|
||||
[message addVerificationState:recipientIdentity.verificationState
|
||||
identityKey:identityKey
|
||||
recipientId:recipientIdentity.recipientId];
|
||||
}];
|
||||
if (message.recipientIds.count > 0) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self sendSyncVerificationStateMessage:message];
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -513,41 +539,18 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
||||
- (void)sendSyncVerificationStateMessage:(OWSVerificationStateSyncMessage *)message
|
||||
{
|
||||
OWSAssert(message);
|
||||
OWSAssert(message.verificationForRecipientId.length > 0);
|
||||
OWSAssert(message.recipientIds.count > 0);
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
|
||||
TSContactThread *contactThread = [TSContactThread getOrCreateThreadWithContactId:message.verificationForRecipientId];
|
||||
|
||||
// Send null message to appear as though we're sending a normal message to cover the sync messsage sent
|
||||
// subsequently
|
||||
OWSOutgoingNullMessage *nullMessage = [[OWSOutgoingNullMessage alloc] initWithContactThread:contactThread
|
||||
verificationStateSyncMessage:message];
|
||||
[self.messageSender sendMessage:nullMessage
|
||||
[self.messageSender sendMessage:message
|
||||
success:^{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
DDLogInfo(@"%@ Successfully sent verification state NullMessage", self.tag);
|
||||
[self.messageSender sendMessage:message
|
||||
success:^{
|
||||
DDLogInfo(@"%@ Successfully sent verification state sync message", self.tag);
|
||||
DDLogInfo(@"%@ Successfully sent verification state sync message", self.tag);
|
||||
|
||||
// Record that this verification state was successfully synced.
|
||||
[self clearSyncMessageForRecipientId:message.verificationForRecipientId];
|
||||
}
|
||||
failure:^(NSError *error) {
|
||||
DDLogError(
|
||||
@"%@ Failed to send verification state sync message with error: %@", self.tag, error);
|
||||
}];
|
||||
});
|
||||
// Record that this verification state was successfully synced.
|
||||
[self clearSyncMessageForRecipientIds:message.recipientIds];
|
||||
}
|
||||
failure:^(NSError *_Nonnull error) {
|
||||
DDLogError(@"%@ Failed to send verification state NullMessage with error: %@", self.tag, error);
|
||||
if (error.code == OWSErrorCodeNoSuchSignalRecipient) {
|
||||
DDLogInfo(@"%@ Removing retries for syncing verification state, since user is no longer registered: %@",
|
||||
self.tag,
|
||||
message.verificationForRecipientId);
|
||||
// Otherwise this will fail forever.
|
||||
[self clearSyncMessageForRecipientId:message.verificationForRecipientId];
|
||||
}
|
||||
failure:^(NSError *error) {
|
||||
DDLogError(@"%@ Failed to send verification state sync message with error: %@", self.tag, error);
|
||||
}];
|
||||
}
|
||||
|
||||
@ -555,52 +558,65 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
||||
{
|
||||
OWSAssert(recipientId.length > 0);
|
||||
|
||||
[self clearSyncMessageForRecipientIds:@[recipientId]];
|
||||
}
|
||||
|
||||
- (void)clearSyncMessageForRecipientIds:(NSArray<NSString *> *)recipientIds
|
||||
{
|
||||
OWSAssert(recipientIds.count > 0);
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
@synchronized(self)
|
||||
{
|
||||
[self.storageManager removeObjectForKey:recipientId
|
||||
inCollection:OWSIdentityManager_QueuedVerificationStateSyncMessages];
|
||||
for (NSString *recipientId in recipientIds) {
|
||||
[self.storageManager removeObjectForKey:recipientId
|
||||
inCollection:OWSIdentityManager_QueuedVerificationStateSyncMessages];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)processIncomingSyncMessage:(OWSSignalServiceProtosVerified *)verified
|
||||
- (void)processIncomingSyncMessage:(NSArray<OWSSignalServiceProtosSyncMessageVerified *> *)verifieds
|
||||
{
|
||||
|
||||
NSString *recipientId = verified.destination;
|
||||
if (recipientId.length < 1) {
|
||||
OWSFail(@"Verification state sync message missing recipientId.");
|
||||
return;
|
||||
}
|
||||
NSData *rawIdentityKey = verified.identityKey;
|
||||
if (rawIdentityKey.length != kIdentityKeyLength) {
|
||||
OWSFail(@"Verification state sync message for recipient: %@ with malformed identityKey: %@",
|
||||
recipientId,
|
||||
rawIdentityKey);
|
||||
return;
|
||||
}
|
||||
NSData *identityKey = [rawIdentityKey removeKeyType];
|
||||
|
||||
switch (verified.state) {
|
||||
case OWSSignalServiceProtosVerifiedStateDefault:
|
||||
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateDefault
|
||||
recipientId:recipientId
|
||||
identityKey:identityKey
|
||||
overwriteOnConflict:NO];
|
||||
break;
|
||||
case OWSSignalServiceProtosVerifiedStateVerified:
|
||||
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateVerified
|
||||
recipientId:recipientId
|
||||
identityKey:identityKey
|
||||
overwriteOnConflict:YES];
|
||||
break;
|
||||
case OWSSignalServiceProtosVerifiedStateUnverified:
|
||||
OWSFail(@"Verification state sync message for recipientId: %@ has unexpected value: %@.",
|
||||
for (OWSSignalServiceProtosSyncMessageVerified *verified in verifieds) {
|
||||
NSString *recipientId = verified.destination;
|
||||
if (recipientId.length < 1) {
|
||||
OWSFail(@"Verification state sync message missing recipientId.");
|
||||
continue;
|
||||
}
|
||||
NSData *rawIdentityKey = verified.identityKey;
|
||||
if (rawIdentityKey.length != kIdentityKeyLength) {
|
||||
OWSFail(@"Verification state sync message for recipient: %@ with malformed identityKey: %@",
|
||||
recipientId,
|
||||
OWSVerificationStateToString(OWSVerificationStateNoLongerVerified));
|
||||
return;
|
||||
rawIdentityKey);
|
||||
continue;
|
||||
}
|
||||
NSData *identityKey = [rawIdentityKey removeKeyType];
|
||||
|
||||
switch (verified.state) {
|
||||
case OWSSignalServiceProtosSyncMessageVerifiedStateDefault:
|
||||
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateDefault
|
||||
recipientId:recipientId
|
||||
identityKey:identityKey
|
||||
overwriteOnConflict:NO];
|
||||
break;
|
||||
case OWSSignalServiceProtosSyncMessageVerifiedStateVerified:
|
||||
[self tryToApplyVerificationStateFromSyncMessage:OWSVerificationStateVerified
|
||||
recipientId:recipientId
|
||||
identityKey:identityKey
|
||||
overwriteOnConflict:YES];
|
||||
break;
|
||||
case OWSSignalServiceProtosSyncMessageVerifiedStateUnverified:
|
||||
OWSFail(@"Verification state sync message for recipientId: %@ has unexpected value: %@.",
|
||||
recipientId,
|
||||
OWSVerificationStateToString(OWSVerificationStateNoLongerVerified));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (verifieds.count > 0) {
|
||||
[self fireIdentityStateChangeNotification];
|
||||
}
|
||||
[self fireIdentityStateChangeNotification];
|
||||
}
|
||||
|
||||
- (void)tryToApplyVerificationStateFromSyncMessage:(OWSVerificationState)verificationState
|
||||
@ -742,7 +758,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
||||
isLocalChange:isLocalChange]];
|
||||
}
|
||||
|
||||
[self.storageManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.storageManager.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
for (TSMessage *message in messages) {
|
||||
[message saveWithTransaction:transaction];
|
||||
}
|
||||
@ -755,11 +771,7 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
|
||||
{
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
|
||||
// We want to defer this so that we never call this method until
|
||||
// [UIApplicationDelegate applicationDidBecomeActive:] is complete.
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)1.f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
|
||||
[self tryToSyncQueuedVerificationStates];
|
||||
});
|
||||
[self tryToSyncQueuedVerificationStates];
|
||||
}
|
||||
|
||||
#pragma mark - Logging
|
||||
|
||||
@ -192,6 +192,7 @@ NSUInteger const OWSSendMessageOperationMaxRetries = 4;
|
||||
|
||||
[message updateWithMessageState:TSOutgoingMessageStateSentToService];
|
||||
|
||||
DDLogDebug(@"%@ succeeded.", strongSelf.tag);
|
||||
aSuccessHandler();
|
||||
|
||||
[strongSelf markAsComplete];
|
||||
@ -280,10 +281,12 @@ NSUInteger const OWSSendMessageOperationMaxRetries = 4;
|
||||
|
||||
- (void)tryWithRemainingRetries:(NSUInteger)remainingRetries
|
||||
{
|
||||
DDLogDebug(@"%@ remainingRetries: %lu", self.tag, (unsigned long)remainingRetries);
|
||||
|
||||
// Use this flag to ensure a given operation only succeeds or fails once.
|
||||
__block BOOL onceFlag = NO;
|
||||
RetryableFailureHandler retryableFailureHandler = ^(NSError *_Nonnull error) {
|
||||
DDLogInfo(@"%@ Sending failed. Remaining retries: %lu", self.tag, (unsigned long)remainingRetries);
|
||||
DDLogInfo(@"%@ Sending failed.", self.tag);
|
||||
|
||||
OWSAssert(!onceFlag);
|
||||
onceFlag = YES;
|
||||
@ -447,6 +450,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
||||
success:(void (^)())successHandler
|
||||
failure:(RetryableFailureHandler)failureHandler
|
||||
{
|
||||
DDLogDebug(@"%@ sending message: %@", self.tag, message.debugDescription);
|
||||
|
||||
[self ensureAnyAttachmentsUploaded:message
|
||||
success:^() {
|
||||
[self deliverMessage:message
|
||||
@ -467,6 +472,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
||||
failure:(RetryableFailureHandler)failureHandler
|
||||
{
|
||||
if (!message.hasAttachments) {
|
||||
DDLogDebug(@"%@ No attachments for message: %@", self.tag, message);
|
||||
return successHandler();
|
||||
}
|
||||
|
||||
@ -588,6 +594,19 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
||||
{
|
||||
TSThread *thread = message.thread;
|
||||
|
||||
#ifdef DEBUG
|
||||
// Assert that we're only sending sync messages when necessary
|
||||
if ([message isKindOfClass:[OWSOutgoingSyncMessage class]]) {
|
||||
__block BOOL hasSecondaryDevices = NO;
|
||||
[self.storageManager.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
hasSecondaryDevices = [OWSDevice hasSecondaryDevicesWithTransaction:transaction];
|
||||
}];
|
||||
if (!hasSecondaryDevices) {
|
||||
OWSFail(@"Sending sync message when we have no devices to sync to.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
dispatch_async([OWSDispatch sendingQueue], ^{
|
||||
if ([thread isKindOfClass:[TSGroupThread class]]) {
|
||||
TSGroupThread *gThread = (TSGroupThread *)thread;
|
||||
@ -1083,10 +1102,16 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
||||
- (void)handleMessageSentLocally:(TSOutgoingMessage *)message
|
||||
{
|
||||
if (message.shouldSyncTranscript) {
|
||||
// TODO: I suspect we shouldn't optimistically set hasSyncedTranscript.
|
||||
// We could set this in a success handler for [sendSyncTranscriptForMessage:].
|
||||
[message updateWithHasSyncedTranscript:YES];
|
||||
[self sendSyncTranscriptForMessage:message];
|
||||
__block BOOL hasSecondaryDevices = NO;
|
||||
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
hasSecondaryDevices = [OWSDevice hasSecondaryDevicesWithTransaction:transaction];
|
||||
}];
|
||||
if (hasSecondaryDevices) {
|
||||
// TODO: I suspect we shouldn't optimistically set hasSyncedTranscript.
|
||||
// We could set this in a success handler for [sendSyncTranscriptForMessage:].
|
||||
[message updateWithHasSyncedTranscript:YES];
|
||||
[self sendSyncTranscriptForMessage:message];
|
||||
}
|
||||
}
|
||||
|
||||
[OWSDisappearingMessagesJob setExpirationForMessage:message];
|
||||
@ -1161,9 +1186,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
||||
inThread:(TSThread *)thread
|
||||
{
|
||||
NSMutableArray *messagesArray = [NSMutableArray arrayWithCapacity:recipient.devices.count];
|
||||
|
||||
NSData *plainText = [message buildPlainTextData];
|
||||
DDLogDebug(@"%@ built message: %@ plainTextData.length: %lu", self.tag, [message class], plainText.length);
|
||||
|
||||
for (NSNumber *deviceNumber in recipient.devices) {
|
||||
@try {
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TSOutgoingMessage.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class OWSVerificationStateSyncMessage;
|
||||
@class TSContactThread;
|
||||
|
||||
@interface OWSOutgoingNullMessage : TSOutgoingMessage
|
||||
|
||||
- (instancetype)initWithContactThread:(TSContactThread *)contactThread
|
||||
verificationStateSyncMessage:(OWSVerificationStateSyncMessage *)verificationStateSyncMessage;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -1,76 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSOutgoingNullMessage.h"
|
||||
#import "OWSSignalServiceProtos.pb.h"
|
||||
#import "Cryptography.h"
|
||||
#import "OWSVerificationStateSyncMessage.h"
|
||||
#import "NSDate+millisecondTimeStamp.h"
|
||||
#import "TSContactThread.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSOutgoingNullMessage ()
|
||||
|
||||
@property (nonatomic, readonly) OWSVerificationStateSyncMessage *verificationStateSyncMessage;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OWSOutgoingNullMessage
|
||||
|
||||
- (instancetype)initWithContactThread:(TSContactThread *)contactThread
|
||||
verificationStateSyncMessage:(OWSVerificationStateSyncMessage *)verificationStateSyncMessage
|
||||
{
|
||||
self = [super initWithTimestamp:[NSDate ows_millisecondTimeStamp]
|
||||
inThread:contactThread];
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
_verificationStateSyncMessage = verificationStateSyncMessage;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - override TSOutgoingMessage
|
||||
|
||||
- (NSData *)buildPlainTextData
|
||||
{
|
||||
OWSSignalServiceProtosContentBuilder *contentBuilder = [OWSSignalServiceProtosContentBuilder new];
|
||||
OWSSignalServiceProtosNullMessageBuilder *nullMessageBuilder = [OWSSignalServiceProtosNullMessageBuilder new];
|
||||
|
||||
NSUInteger contentLength = self.verificationStateSyncMessage.unpaddedVerifiedLength;
|
||||
|
||||
OWSAssert(self.verificationStateSyncMessage.paddingBytesLength > 0);
|
||||
|
||||
// We add the same amount of padding in the VerificationStateSync message and it's coresponding NullMessage so that
|
||||
// the sync message is indistinguishable from an outgoing Sent transcript corresponding to the NullMessage. We pad
|
||||
// the NullMessage so as to obscure it's content. The sync message (like all sync messages) will be *additionally*
|
||||
// padded by the superclass while being sent. The end result is we send a NullMessage of a non-distinct size, and a
|
||||
// verification sync which is ~1-512 bytes larger then that.
|
||||
contentLength += self.verificationStateSyncMessage.paddingBytesLength;
|
||||
|
||||
OWSAssert(contentLength > 0)
|
||||
|
||||
nullMessageBuilder.padding = [Cryptography generateRandomBytes:contentLength];
|
||||
|
||||
contentBuilder.nullMessage = [nullMessageBuilder build];
|
||||
|
||||
return [contentBuilder build].data;
|
||||
}
|
||||
|
||||
- (BOOL)shouldSyncTranscript
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)saveWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||
{
|
||||
// No-op as we don't want to actually display this as an outgoing message in our thread.
|
||||
return;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@ -36,8 +36,6 @@
|
||||
@class OWSSignalServiceProtosGroupDetailsAvatar;
|
||||
@class OWSSignalServiceProtosGroupDetailsAvatarBuilder;
|
||||
@class OWSSignalServiceProtosGroupDetailsBuilder;
|
||||
@class OWSSignalServiceProtosNullMessage;
|
||||
@class OWSSignalServiceProtosNullMessageBuilder;
|
||||
@class OWSSignalServiceProtosSyncMessage;
|
||||
@class OWSSignalServiceProtosSyncMessageBlocked;
|
||||
@class OWSSignalServiceProtosSyncMessageBlockedBuilder;
|
||||
@ -52,8 +50,8 @@
|
||||
@class OWSSignalServiceProtosSyncMessageRequestBuilder;
|
||||
@class OWSSignalServiceProtosSyncMessageSent;
|
||||
@class OWSSignalServiceProtosSyncMessageSentBuilder;
|
||||
@class OWSSignalServiceProtosVerified;
|
||||
@class OWSSignalServiceProtosVerifiedBuilder;
|
||||
@class OWSSignalServiceProtosSyncMessageVerified;
|
||||
@class OWSSignalServiceProtosSyncMessageVerifiedBuilder;
|
||||
@class ObjectiveCFileOptions;
|
||||
@class ObjectiveCFileOptionsBuilder;
|
||||
@class PBDescriptorProto;
|
||||
@ -111,15 +109,6 @@ typedef NS_ENUM(SInt32, OWSSignalServiceProtosEnvelopeType) {
|
||||
BOOL OWSSignalServiceProtosEnvelopeTypeIsValidValue(OWSSignalServiceProtosEnvelopeType value);
|
||||
NSString *NSStringFromOWSSignalServiceProtosEnvelopeType(OWSSignalServiceProtosEnvelopeType value);
|
||||
|
||||
typedef NS_ENUM(SInt32, OWSSignalServiceProtosVerifiedState) {
|
||||
OWSSignalServiceProtosVerifiedStateDefault = 0,
|
||||
OWSSignalServiceProtosVerifiedStateVerified = 1,
|
||||
OWSSignalServiceProtosVerifiedStateUnverified = 2,
|
||||
};
|
||||
|
||||
BOOL OWSSignalServiceProtosVerifiedStateIsValidValue(OWSSignalServiceProtosVerifiedState value);
|
||||
NSString *NSStringFromOWSSignalServiceProtosVerifiedState(OWSSignalServiceProtosVerifiedState value);
|
||||
|
||||
typedef NS_ENUM(SInt32, OWSSignalServiceProtosDataMessageFlags) {
|
||||
OWSSignalServiceProtosDataMessageFlagsEndSession = 1,
|
||||
OWSSignalServiceProtosDataMessageFlagsExpirationTimerUpdate = 2,
|
||||
@ -138,6 +127,15 @@ typedef NS_ENUM(SInt32, OWSSignalServiceProtosSyncMessageRequestType) {
|
||||
BOOL OWSSignalServiceProtosSyncMessageRequestTypeIsValidValue(OWSSignalServiceProtosSyncMessageRequestType value);
|
||||
NSString *NSStringFromOWSSignalServiceProtosSyncMessageRequestType(OWSSignalServiceProtosSyncMessageRequestType value);
|
||||
|
||||
typedef NS_ENUM(SInt32, OWSSignalServiceProtosSyncMessageVerifiedState) {
|
||||
OWSSignalServiceProtosSyncMessageVerifiedStateDefault = 0,
|
||||
OWSSignalServiceProtosSyncMessageVerifiedStateVerified = 1,
|
||||
OWSSignalServiceProtosSyncMessageVerifiedStateUnverified = 2,
|
||||
};
|
||||
|
||||
BOOL OWSSignalServiceProtosSyncMessageVerifiedStateIsValidValue(OWSSignalServiceProtosSyncMessageVerifiedState value);
|
||||
NSString *NSStringFromOWSSignalServiceProtosSyncMessageVerifiedState(OWSSignalServiceProtosSyncMessageVerifiedState value);
|
||||
|
||||
typedef NS_ENUM(SInt32, OWSSignalServiceProtosAttachmentPointerFlags) {
|
||||
OWSSignalServiceProtosAttachmentPointerFlagsVoiceMessage = 1,
|
||||
};
|
||||
@ -276,26 +274,21 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
|
||||
#define Content_dataMessage @"dataMessage"
|
||||
#define Content_syncMessage @"syncMessage"
|
||||
#define Content_callMessage @"callMessage"
|
||||
#define Content_nullMessage @"nullMessage"
|
||||
@interface OWSSignalServiceProtosContent : PBGeneratedMessage<GeneratedMessageProtocol> {
|
||||
@private
|
||||
BOOL hasDataMessage_:1;
|
||||
BOOL hasSyncMessage_:1;
|
||||
BOOL hasCallMessage_:1;
|
||||
BOOL hasNullMessage_:1;
|
||||
OWSSignalServiceProtosDataMessage* dataMessage;
|
||||
OWSSignalServiceProtosSyncMessage* syncMessage;
|
||||
OWSSignalServiceProtosCallMessage* callMessage;
|
||||
OWSSignalServiceProtosNullMessage* nullMessage;
|
||||
}
|
||||
- (BOOL) hasDataMessage;
|
||||
- (BOOL) hasSyncMessage;
|
||||
- (BOOL) hasCallMessage;
|
||||
- (BOOL) hasNullMessage;
|
||||
@property (readonly, strong) OWSSignalServiceProtosDataMessage* dataMessage;
|
||||
@property (readonly, strong) OWSSignalServiceProtosSyncMessage* syncMessage;
|
||||
@property (readonly, strong) OWSSignalServiceProtosCallMessage* callMessage;
|
||||
@property (readonly, strong) OWSSignalServiceProtosNullMessage* nullMessage;
|
||||
|
||||
+ (instancetype) defaultInstance;
|
||||
- (instancetype) defaultInstance;
|
||||
@ -352,143 +345,6 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
|
||||
- (OWSSignalServiceProtosContentBuilder*) setCallMessageBuilder:(OWSSignalServiceProtosCallMessageBuilder*) builderForValue;
|
||||
- (OWSSignalServiceProtosContentBuilder*) mergeCallMessage:(OWSSignalServiceProtosCallMessage*) value;
|
||||
- (OWSSignalServiceProtosContentBuilder*) clearCallMessage;
|
||||
|
||||
- (BOOL) hasNullMessage;
|
||||
- (OWSSignalServiceProtosNullMessage*) nullMessage;
|
||||
- (OWSSignalServiceProtosContentBuilder*) setNullMessage:(OWSSignalServiceProtosNullMessage*) value;
|
||||
- (OWSSignalServiceProtosContentBuilder*) setNullMessageBuilder:(OWSSignalServiceProtosNullMessageBuilder*) builderForValue;
|
||||
- (OWSSignalServiceProtosContentBuilder*) mergeNullMessage:(OWSSignalServiceProtosNullMessage*) value;
|
||||
- (OWSSignalServiceProtosContentBuilder*) clearNullMessage;
|
||||
@end
|
||||
|
||||
#define NullMessage_padding @"padding"
|
||||
@interface OWSSignalServiceProtosNullMessage : PBGeneratedMessage<GeneratedMessageProtocol> {
|
||||
@private
|
||||
BOOL hasPadding_:1;
|
||||
NSData* padding;
|
||||
}
|
||||
- (BOOL) hasPadding;
|
||||
@property (readonly, strong) NSData* padding;
|
||||
|
||||
+ (instancetype) defaultInstance;
|
||||
- (instancetype) defaultInstance;
|
||||
|
||||
- (BOOL) isInitialized;
|
||||
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output;
|
||||
- (OWSSignalServiceProtosNullMessageBuilder*) builder;
|
||||
+ (OWSSignalServiceProtosNullMessageBuilder*) builder;
|
||||
+ (OWSSignalServiceProtosNullMessageBuilder*) builderWithPrototype:(OWSSignalServiceProtosNullMessage*) prototype;
|
||||
- (OWSSignalServiceProtosNullMessageBuilder*) toBuilder;
|
||||
|
||||
+ (OWSSignalServiceProtosNullMessage*) parseFromData:(NSData*) data;
|
||||
+ (OWSSignalServiceProtosNullMessage*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
+ (OWSSignalServiceProtosNullMessage*) parseFromInputStream:(NSInputStream*) input;
|
||||
+ (OWSSignalServiceProtosNullMessage*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
+ (OWSSignalServiceProtosNullMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input;
|
||||
+ (OWSSignalServiceProtosNullMessage*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
@end
|
||||
|
||||
@interface OWSSignalServiceProtosNullMessageBuilder : PBGeneratedMessageBuilder {
|
||||
@private
|
||||
OWSSignalServiceProtosNullMessage* resultNullMessage;
|
||||
}
|
||||
|
||||
- (OWSSignalServiceProtosNullMessage*) defaultInstance;
|
||||
|
||||
- (OWSSignalServiceProtosNullMessageBuilder*) clear;
|
||||
- (OWSSignalServiceProtosNullMessageBuilder*) clone;
|
||||
|
||||
- (OWSSignalServiceProtosNullMessage*) build;
|
||||
- (OWSSignalServiceProtosNullMessage*) buildPartial;
|
||||
|
||||
- (OWSSignalServiceProtosNullMessageBuilder*) mergeFrom:(OWSSignalServiceProtosNullMessage*) other;
|
||||
- (OWSSignalServiceProtosNullMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input;
|
||||
- (OWSSignalServiceProtosNullMessageBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
|
||||
- (BOOL) hasPadding;
|
||||
- (NSData*) padding;
|
||||
- (OWSSignalServiceProtosNullMessageBuilder*) setPadding:(NSData*) value;
|
||||
- (OWSSignalServiceProtosNullMessageBuilder*) clearPadding;
|
||||
@end
|
||||
|
||||
#define Verified_destination @"destination"
|
||||
#define Verified_identityKey @"identityKey"
|
||||
#define Verified_state @"state"
|
||||
#define Verified_nullMessage @"nullMessage"
|
||||
@interface OWSSignalServiceProtosVerified : PBGeneratedMessage<GeneratedMessageProtocol> {
|
||||
@private
|
||||
BOOL hasDestination_:1;
|
||||
BOOL hasIdentityKey_:1;
|
||||
BOOL hasNullMessage_:1;
|
||||
BOOL hasState_:1;
|
||||
NSString* destination;
|
||||
NSData* identityKey;
|
||||
NSData* nullMessage;
|
||||
OWSSignalServiceProtosVerifiedState state;
|
||||
}
|
||||
- (BOOL) hasDestination;
|
||||
- (BOOL) hasIdentityKey;
|
||||
- (BOOL) hasState;
|
||||
- (BOOL) hasNullMessage;
|
||||
@property (readonly, strong) NSString* destination;
|
||||
@property (readonly, strong) NSData* identityKey;
|
||||
@property (readonly) OWSSignalServiceProtosVerifiedState state;
|
||||
@property (readonly, strong) NSData* nullMessage;
|
||||
|
||||
+ (instancetype) defaultInstance;
|
||||
- (instancetype) defaultInstance;
|
||||
|
||||
- (BOOL) isInitialized;
|
||||
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output;
|
||||
- (OWSSignalServiceProtosVerifiedBuilder*) builder;
|
||||
+ (OWSSignalServiceProtosVerifiedBuilder*) builder;
|
||||
+ (OWSSignalServiceProtosVerifiedBuilder*) builderWithPrototype:(OWSSignalServiceProtosVerified*) prototype;
|
||||
- (OWSSignalServiceProtosVerifiedBuilder*) toBuilder;
|
||||
|
||||
+ (OWSSignalServiceProtosVerified*) parseFromData:(NSData*) data;
|
||||
+ (OWSSignalServiceProtosVerified*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
+ (OWSSignalServiceProtosVerified*) parseFromInputStream:(NSInputStream*) input;
|
||||
+ (OWSSignalServiceProtosVerified*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
+ (OWSSignalServiceProtosVerified*) parseFromCodedInputStream:(PBCodedInputStream*) input;
|
||||
+ (OWSSignalServiceProtosVerified*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
@end
|
||||
|
||||
@interface OWSSignalServiceProtosVerifiedBuilder : PBGeneratedMessageBuilder {
|
||||
@private
|
||||
OWSSignalServiceProtosVerified* resultVerified;
|
||||
}
|
||||
|
||||
- (OWSSignalServiceProtosVerified*) defaultInstance;
|
||||
|
||||
- (OWSSignalServiceProtosVerifiedBuilder*) clear;
|
||||
- (OWSSignalServiceProtosVerifiedBuilder*) clone;
|
||||
|
||||
- (OWSSignalServiceProtosVerified*) build;
|
||||
- (OWSSignalServiceProtosVerified*) buildPartial;
|
||||
|
||||
- (OWSSignalServiceProtosVerifiedBuilder*) mergeFrom:(OWSSignalServiceProtosVerified*) other;
|
||||
- (OWSSignalServiceProtosVerifiedBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input;
|
||||
- (OWSSignalServiceProtosVerifiedBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
|
||||
- (BOOL) hasDestination;
|
||||
- (NSString*) destination;
|
||||
- (OWSSignalServiceProtosVerifiedBuilder*) setDestination:(NSString*) value;
|
||||
- (OWSSignalServiceProtosVerifiedBuilder*) clearDestination;
|
||||
|
||||
- (BOOL) hasIdentityKey;
|
||||
- (NSData*) identityKey;
|
||||
- (OWSSignalServiceProtosVerifiedBuilder*) setIdentityKey:(NSData*) value;
|
||||
- (OWSSignalServiceProtosVerifiedBuilder*) clearIdentityKey;
|
||||
|
||||
- (BOOL) hasState;
|
||||
- (OWSSignalServiceProtosVerifiedState) state;
|
||||
- (OWSSignalServiceProtosVerifiedBuilder*) setState:(OWSSignalServiceProtosVerifiedState) value;
|
||||
- (OWSSignalServiceProtosVerifiedBuilder*) clearState;
|
||||
|
||||
- (BOOL) hasNullMessage;
|
||||
- (NSData*) nullMessage;
|
||||
- (OWSSignalServiceProtosVerifiedBuilder*) setNullMessage:(NSData*) value;
|
||||
- (OWSSignalServiceProtosVerifiedBuilder*) clearNullMessage;
|
||||
@end
|
||||
|
||||
#define CallMessage_offer @"offer"
|
||||
@ -996,23 +852,21 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
|
||||
BOOL hasGroups_:1;
|
||||
BOOL hasRequest_:1;
|
||||
BOOL hasBlocked_:1;
|
||||
BOOL hasVerified_:1;
|
||||
BOOL hasPadding_:1;
|
||||
OWSSignalServiceProtosSyncMessageSent* sent;
|
||||
OWSSignalServiceProtosSyncMessageContacts* contacts;
|
||||
OWSSignalServiceProtosSyncMessageGroups* groups;
|
||||
OWSSignalServiceProtosSyncMessageRequest* request;
|
||||
OWSSignalServiceProtosSyncMessageBlocked* blocked;
|
||||
OWSSignalServiceProtosVerified* verified;
|
||||
NSData* padding;
|
||||
NSMutableArray * readArray;
|
||||
NSMutableArray * verifiedArray;
|
||||
}
|
||||
- (BOOL) hasSent;
|
||||
- (BOOL) hasContacts;
|
||||
- (BOOL) hasGroups;
|
||||
- (BOOL) hasRequest;
|
||||
- (BOOL) hasBlocked;
|
||||
- (BOOL) hasVerified;
|
||||
- (BOOL) hasPadding;
|
||||
@property (readonly, strong) OWSSignalServiceProtosSyncMessageSent* sent;
|
||||
@property (readonly, strong) OWSSignalServiceProtosSyncMessageContacts* contacts;
|
||||
@ -1020,9 +874,10 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
|
||||
@property (readonly, strong) OWSSignalServiceProtosSyncMessageRequest* request;
|
||||
@property (readonly, strong) NSArray<OWSSignalServiceProtosSyncMessageRead*> * read;
|
||||
@property (readonly, strong) OWSSignalServiceProtosSyncMessageBlocked* blocked;
|
||||
@property (readonly, strong) OWSSignalServiceProtosVerified* verified;
|
||||
@property (readonly, strong) NSArray<OWSSignalServiceProtosSyncMessageVerified*> * verified;
|
||||
@property (readonly, strong) NSData* padding;
|
||||
- (OWSSignalServiceProtosSyncMessageRead*)readAtIndex:(NSUInteger)index;
|
||||
- (OWSSignalServiceProtosSyncMessageVerified*)verifiedAtIndex:(NSUInteger)index;
|
||||
|
||||
+ (instancetype) defaultInstance;
|
||||
- (instancetype) defaultInstance;
|
||||
@ -1398,6 +1253,76 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
|
||||
- (OWSSignalServiceProtosSyncMessageReadBuilder*) clearTimestamp;
|
||||
@end
|
||||
|
||||
#define Verified_destination @"destination"
|
||||
#define Verified_identityKey @"identityKey"
|
||||
#define Verified_state @"state"
|
||||
@interface OWSSignalServiceProtosSyncMessageVerified : PBGeneratedMessage<GeneratedMessageProtocol> {
|
||||
@private
|
||||
BOOL hasDestination_:1;
|
||||
BOOL hasIdentityKey_:1;
|
||||
BOOL hasState_:1;
|
||||
NSString* destination;
|
||||
NSData* identityKey;
|
||||
OWSSignalServiceProtosSyncMessageVerifiedState state;
|
||||
}
|
||||
- (BOOL) hasDestination;
|
||||
- (BOOL) hasIdentityKey;
|
||||
- (BOOL) hasState;
|
||||
@property (readonly, strong) NSString* destination;
|
||||
@property (readonly, strong) NSData* identityKey;
|
||||
@property (readonly) OWSSignalServiceProtosSyncMessageVerifiedState state;
|
||||
|
||||
+ (instancetype) defaultInstance;
|
||||
- (instancetype) defaultInstance;
|
||||
|
||||
- (BOOL) isInitialized;
|
||||
- (void) writeToCodedOutputStream:(PBCodedOutputStream*) output;
|
||||
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) builder;
|
||||
+ (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) builder;
|
||||
+ (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) builderWithPrototype:(OWSSignalServiceProtosSyncMessageVerified*) prototype;
|
||||
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) toBuilder;
|
||||
|
||||
+ (OWSSignalServiceProtosSyncMessageVerified*) parseFromData:(NSData*) data;
|
||||
+ (OWSSignalServiceProtosSyncMessageVerified*) parseFromData:(NSData*) data extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
+ (OWSSignalServiceProtosSyncMessageVerified*) parseFromInputStream:(NSInputStream*) input;
|
||||
+ (OWSSignalServiceProtosSyncMessageVerified*) parseFromInputStream:(NSInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
+ (OWSSignalServiceProtosSyncMessageVerified*) parseFromCodedInputStream:(PBCodedInputStream*) input;
|
||||
+ (OWSSignalServiceProtosSyncMessageVerified*) parseFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
@end
|
||||
|
||||
@interface OWSSignalServiceProtosSyncMessageVerifiedBuilder : PBGeneratedMessageBuilder {
|
||||
@private
|
||||
OWSSignalServiceProtosSyncMessageVerified* resultVerified;
|
||||
}
|
||||
|
||||
- (OWSSignalServiceProtosSyncMessageVerified*) defaultInstance;
|
||||
|
||||
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) clear;
|
||||
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) clone;
|
||||
|
||||
- (OWSSignalServiceProtosSyncMessageVerified*) build;
|
||||
- (OWSSignalServiceProtosSyncMessageVerified*) buildPartial;
|
||||
|
||||
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) mergeFrom:(OWSSignalServiceProtosSyncMessageVerified*) other;
|
||||
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input;
|
||||
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) mergeFromCodedInputStream:(PBCodedInputStream*) input extensionRegistry:(PBExtensionRegistry*) extensionRegistry;
|
||||
|
||||
- (BOOL) hasDestination;
|
||||
- (NSString*) destination;
|
||||
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) setDestination:(NSString*) value;
|
||||
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) clearDestination;
|
||||
|
||||
- (BOOL) hasIdentityKey;
|
||||
- (NSData*) identityKey;
|
||||
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) setIdentityKey:(NSData*) value;
|
||||
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) clearIdentityKey;
|
||||
|
||||
- (BOOL) hasState;
|
||||
- (OWSSignalServiceProtosSyncMessageVerifiedState) state;
|
||||
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) setState:(OWSSignalServiceProtosSyncMessageVerifiedState) value;
|
||||
- (OWSSignalServiceProtosSyncMessageVerifiedBuilder*) clearState;
|
||||
@end
|
||||
|
||||
@interface OWSSignalServiceProtosSyncMessageBuilder : PBGeneratedMessageBuilder {
|
||||
@private
|
||||
OWSSignalServiceProtosSyncMessage* resultSyncMessage;
|
||||
@ -1456,12 +1381,11 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
|
||||
- (OWSSignalServiceProtosSyncMessageBuilder*) mergeBlocked:(OWSSignalServiceProtosSyncMessageBlocked*) value;
|
||||
- (OWSSignalServiceProtosSyncMessageBuilder*) clearBlocked;
|
||||
|
||||
- (BOOL) hasVerified;
|
||||
- (OWSSignalServiceProtosVerified*) verified;
|
||||
- (OWSSignalServiceProtosSyncMessageBuilder*) setVerified:(OWSSignalServiceProtosVerified*) value;
|
||||
- (OWSSignalServiceProtosSyncMessageBuilder*) setVerifiedBuilder:(OWSSignalServiceProtosVerifiedBuilder*) builderForValue;
|
||||
- (OWSSignalServiceProtosSyncMessageBuilder*) mergeVerified:(OWSSignalServiceProtosVerified*) value;
|
||||
- (OWSSignalServiceProtosSyncMessageBuilder*) clearVerified;
|
||||
- (NSMutableArray<OWSSignalServiceProtosSyncMessageVerified*> *)verified;
|
||||
- (OWSSignalServiceProtosSyncMessageVerified*)verifiedAtIndex:(NSUInteger)index;
|
||||
- (OWSSignalServiceProtosSyncMessageBuilder *)addVerified:(OWSSignalServiceProtosSyncMessageVerified*)value;
|
||||
- (OWSSignalServiceProtosSyncMessageBuilder *)setVerifiedArray:(NSArray<OWSSignalServiceProtosSyncMessageVerified*> *)array;
|
||||
- (OWSSignalServiceProtosSyncMessageBuilder *)clearVerified;
|
||||
|
||||
- (BOOL) hasPadding;
|
||||
- (NSData*) padding;
|
||||
@ -1685,30 +1609,25 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
|
||||
#define ContactDetails_name @"name"
|
||||
#define ContactDetails_avatar @"avatar"
|
||||
#define ContactDetails_color @"color"
|
||||
#define ContactDetails_verified @"verified"
|
||||
@interface OWSSignalServiceProtosContactDetails : PBGeneratedMessage<GeneratedMessageProtocol> {
|
||||
@private
|
||||
BOOL hasNumber_:1;
|
||||
BOOL hasName_:1;
|
||||
BOOL hasColor_:1;
|
||||
BOOL hasAvatar_:1;
|
||||
BOOL hasVerified_:1;
|
||||
NSString* number;
|
||||
NSString* name;
|
||||
NSString* color;
|
||||
OWSSignalServiceProtosContactDetailsAvatar* avatar;
|
||||
OWSSignalServiceProtosVerified* verified;
|
||||
}
|
||||
- (BOOL) hasNumber;
|
||||
- (BOOL) hasName;
|
||||
- (BOOL) hasAvatar;
|
||||
- (BOOL) hasColor;
|
||||
- (BOOL) hasVerified;
|
||||
@property (readonly, strong) NSString* number;
|
||||
@property (readonly, strong) NSString* name;
|
||||
@property (readonly, strong) OWSSignalServiceProtosContactDetailsAvatar* avatar;
|
||||
@property (readonly, strong) NSString* color;
|
||||
@property (readonly, strong) OWSSignalServiceProtosVerified* verified;
|
||||
|
||||
+ (instancetype) defaultInstance;
|
||||
- (instancetype) defaultInstance;
|
||||
@ -1826,13 +1745,6 @@ NSString *NSStringFromOWSSignalServiceProtosGroupContextType(OWSSignalServicePro
|
||||
- (NSString*) color;
|
||||
- (OWSSignalServiceProtosContactDetailsBuilder*) setColor:(NSString*) value;
|
||||
- (OWSSignalServiceProtosContactDetailsBuilder*) clearColor;
|
||||
|
||||
- (BOOL) hasVerified;
|
||||
- (OWSSignalServiceProtosVerified*) verified;
|
||||
- (OWSSignalServiceProtosContactDetailsBuilder*) setVerified:(OWSSignalServiceProtosVerified*) value;
|
||||
- (OWSSignalServiceProtosContactDetailsBuilder*) setVerifiedBuilder:(OWSSignalServiceProtosVerifiedBuilder*) builderForValue;
|
||||
- (OWSSignalServiceProtosContactDetailsBuilder*) mergeVerified:(OWSSignalServiceProtosVerified*) value;
|
||||
- (OWSSignalServiceProtosContactDetailsBuilder*) clearVerified;
|
||||
@end
|
||||
|
||||
#define GroupDetails_id @"id"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -17,7 +17,6 @@ typedef enum {
|
||||
RPRecentCallTypeOutgoingIncomplete,
|
||||
RPRecentCallTypeIncomingIncomplete,
|
||||
RPRecentCallTypeMissedBecauseOfChangedIdentity,
|
||||
RPRecentCallTypeIncomingDeclined
|
||||
} RPRecentCallType;
|
||||
|
||||
@interface TSCall : TSInteraction <OWSReadTracking>
|
||||
|
||||
@ -76,9 +76,6 @@ NSUInteger TSCallCurrentSchemaVersion = 1;
|
||||
return NSLocalizedString(@"INCOMING_INCOMPLETE_CALL", @"");
|
||||
case RPRecentCallTypeMissedBecauseOfChangedIdentity:
|
||||
return NSLocalizedString(@"INFO_MESSAGE_MISSED_CALL_DUE_TO_CHANGED_IDENITY", @"info message text shown in conversation view");
|
||||
case RPRecentCallTypeIncomingDeclined:
|
||||
return NSLocalizedString(@"INCOMING_DECLINED_CALL",
|
||||
@"info message recorded in conversation history when local user declined a call");
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,7 +96,7 @@ NSUInteger TSCallCurrentSchemaVersion = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
DDLogDebug(@"%@ marking as read uniqueId: %@ which has timestamp: %llu", self.tag, self.uniqueId, self.timestamp);
|
||||
DDLogInfo(@"%@ marking as read uniqueId: %@ which has timestamp: %llu", self.tag, self.uniqueId, self.timestamp);
|
||||
_read = YES;
|
||||
[self saveWithTransaction:transaction];
|
||||
[self touchThreadWithTransaction:transaction];
|
||||
@ -119,7 +116,7 @@ NSUInteger TSCallCurrentSchemaVersion = 1;
|
||||
|
||||
_callType = callType;
|
||||
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
[self saveWithTransaction:transaction];
|
||||
|
||||
// redraw any thread-related unread count UI.
|
||||
|
||||
@ -50,7 +50,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (nonatomic, readonly) OWSMessageSender *messageSender;
|
||||
@property (nonatomic, readonly) OWSIncomingMessageFinder *incomingMessageFinder;
|
||||
@property (nonatomic, readonly) OWSBlockingManager *blockingManager;
|
||||
@property (nonatomic, readonly) OWSIdentityManager *identityManager;
|
||||
|
||||
@end
|
||||
|
||||
@ -74,16 +73,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
id<ContactsManagerProtocol> contactsManager = [TextSecureKitEnv sharedEnv].contactsManager;
|
||||
id<OWSCallMessageHandler> callMessageHandler = [TextSecureKitEnv sharedEnv].callMessageHandler;
|
||||
ContactsUpdater *contactsUpdater = [ContactsUpdater sharedUpdater];
|
||||
OWSIdentityManager *identityManager = [OWSIdentityManager sharedManager];
|
||||
OWSMessageSender *messageSender = [TextSecureKitEnv sharedEnv].messageSender;
|
||||
|
||||
|
||||
return [self initWithNetworkManager:networkManager
|
||||
storageManager:storageManager
|
||||
callMessageHandler:callMessageHandler
|
||||
contactsManager:contactsManager
|
||||
contactsUpdater:contactsUpdater
|
||||
identityManager:identityManager
|
||||
messageSender:messageSender];
|
||||
}
|
||||
|
||||
@ -92,7 +88,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
callMessageHandler:(id<OWSCallMessageHandler>)callMessageHandler
|
||||
contactsManager:(id<ContactsManagerProtocol>)contactsManager
|
||||
contactsUpdater:(ContactsUpdater *)contactsUpdater
|
||||
identityManager:(OWSIdentityManager *)identityManager
|
||||
messageSender:(OWSMessageSender *)messageSender
|
||||
{
|
||||
self = [super init];
|
||||
@ -106,7 +101,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
_callMessageHandler = callMessageHandler;
|
||||
_contactsManager = contactsManager;
|
||||
_contactsUpdater = contactsUpdater;
|
||||
_identityManager = identityManager;
|
||||
_messageSender = messageSender;
|
||||
|
||||
_dbConnection = storageManager.newDatabaseConnection;
|
||||
@ -115,24 +109,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
OWSSingletonAssert();
|
||||
|
||||
[self startObserving];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)startObserving
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(yapDatabaseModified:)
|
||||
name:YapDatabaseModifiedNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
- (void)yapDatabaseModified:(NSNotification *)notification
|
||||
{
|
||||
[self updateApplicationBadgeCount];
|
||||
}
|
||||
|
||||
#pragma mark - Debugging
|
||||
|
||||
- (NSString *)descriptionForEnvelope:(OWSSignalServiceProtosEnvelope *)envelope
|
||||
@ -186,8 +165,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return [NSString stringWithFormat:@"<DataMessage: %@ />", [self descriptionForDataMessage:content.dataMessage]];
|
||||
} else if (content.hasCallMessage) {
|
||||
return [NSString stringWithFormat:@"<CallMessage: %@ />", content.callMessage];
|
||||
} else if (content.hasNullMessage) {
|
||||
return [NSString stringWithFormat:@"<NullMessage: %@ />", content.nullMessage];
|
||||
} else {
|
||||
OWSAssert(NO);
|
||||
return @"UnknownContent";
|
||||
@ -242,9 +219,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
[description appendString:@"Blocked"];
|
||||
} else if (syncMessage.read.count > 0) {
|
||||
[description appendString:@"ReadReceipt"];
|
||||
} else if (syncMessage.hasVerified) {
|
||||
NSString *verifiedString =
|
||||
[NSString stringWithFormat:@"Verification for: %@", syncMessage.verified.destination];
|
||||
} else if (syncMessage.verified.count > 0){
|
||||
NSString *verifiedString = [NSString stringWithFormat:@"Verifications: (%lu)", (unsigned long)syncMessage.verified.count];
|
||||
[description appendString:verifiedString];
|
||||
} else {
|
||||
// Shouldn't happen
|
||||
@ -387,7 +363,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:storageManager
|
||||
preKeyStore:storageManager
|
||||
signedPreKeyStore:storageManager
|
||||
identityKeyStore:self.identityManager
|
||||
identityKeyStore:[OWSIdentityManager sharedManager]
|
||||
recipientId:recipientId
|
||||
deviceId:deviceId];
|
||||
|
||||
@ -439,7 +415,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
SessionCipher *cipher = [[SessionCipher alloc] initWithSessionStore:storageManager
|
||||
preKeyStore:storageManager
|
||||
signedPreKeyStore:storageManager
|
||||
identityKeyStore:self.identityManager
|
||||
identityKeyStore:[OWSIdentityManager sharedManager]
|
||||
recipientId:recipientId
|
||||
deviceId:deviceId];
|
||||
|
||||
@ -473,7 +449,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
sourceId:envelope.source
|
||||
sourceDeviceId:envelope.sourceDevice];
|
||||
if (duplicateEnvelope) {
|
||||
DDLogInfo(@"%@ Ignoring previously received envelope from %@.%d with timestamp: %llu", self.tag, envelope.source, (unsigned int)envelope.sourceDevice, envelope.timestamp);
|
||||
DDLogInfo(@"%@ Ignoring previously received envelope with timestamp: %llu", self.tag, envelope.timestamp);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -486,8 +462,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
[self handleIncomingEnvelope:envelope withDataMessage:content.dataMessage];
|
||||
} else if (content.hasCallMessage) {
|
||||
[self handleIncomingEnvelope:envelope withCallMessage:content.callMessage];
|
||||
} else if (content.hasNullMessage) {
|
||||
DDLogInfo(@"%@ Received null message.", self.tag);
|
||||
} else {
|
||||
DDLogWarn(@"%@ Ignoring envelope. Content with no known payload", self.tag);
|
||||
}
|
||||
@ -525,7 +499,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
NSString *recipientId = incomingEnvelope.source;
|
||||
|
||||
__block TSThread *thread;
|
||||
[[TSStorageManager sharedManager].dbReadWriteConnection
|
||||
[[TSStorageManager sharedManager].dbConnection
|
||||
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
thread = [TSContactThread getOrCreateThreadWithContactId:recipientId transaction:transaction];
|
||||
}];
|
||||
@ -674,8 +648,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
} else if (syncMessage.hasRequest) {
|
||||
if (syncMessage.request.type == OWSSignalServiceProtosSyncMessageRequestTypeContacts) {
|
||||
OWSSyncContactsMessage *syncContactsMessage =
|
||||
[[OWSSyncContactsMessage alloc] initWithContactsManager:self.contactsManager
|
||||
identityManager:self.identityManager];
|
||||
[[OWSSyncContactsMessage alloc] initWithContactsManager:self.contactsManager];
|
||||
|
||||
[self.messageSender sendTemporaryAttachmentData:[syncContactsMessage buildPlainTextAttachmentData]
|
||||
contentType:OWSMimeTypeApplicationOctetStream
|
||||
@ -686,6 +659,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
failure:^(NSError *error) {
|
||||
DDLogError(@"%@ Failed to send Contacts response syncMessage with error: %@", self.tag, error);
|
||||
}];
|
||||
|
||||
// Also sync all verification state after syncing contacts.
|
||||
[[OWSIdentityManager sharedManager] syncAllVerificationStates];
|
||||
} else if (syncMessage.request.type == OWSSignalServiceProtosSyncMessageRequestTypeGroups) {
|
||||
OWSSyncGroupsMessage *syncGroupsMessage = [[OWSSyncGroupsMessage alloc] init];
|
||||
|
||||
@ -711,9 +687,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
[[OWSReadReceiptsProcessor alloc] initWithReadReceiptProtos:syncMessage.read
|
||||
storageManager:self.storageManager];
|
||||
[readReceiptsProcessor process];
|
||||
} else if (syncMessage.hasVerified) {
|
||||
DDLogInfo(@"%@ Received verification state for %@", self.tag, syncMessage.verified.destination);
|
||||
[self.identityManager processIncomingSyncMessage:syncMessage.verified];
|
||||
} else if (syncMessage.verified.count > 0) {
|
||||
DDLogInfo(@"%@ Received %ld verification state(s)", self.tag, (u_long)syncMessage.verified.count);
|
||||
|
||||
[[OWSIdentityManager sharedManager] processIncomingSyncMessage:syncMessage.verified];
|
||||
} else {
|
||||
DDLogWarn(@"%@ Ignoring unsupported sync message.", self.tag);
|
||||
}
|
||||
@ -1083,12 +1060,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return numberOfItems;
|
||||
}
|
||||
|
||||
- (void)updateApplicationBadgeCount
|
||||
{
|
||||
NSUInteger numberOfItems = [self unreadMessagesCount];
|
||||
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:numberOfItems];
|
||||
}
|
||||
|
||||
- (NSUInteger)unreadMessagesInThread:(TSThread *)thread {
|
||||
__block NSUInteger numberOfItems;
|
||||
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
|
||||
@ -30,7 +30,7 @@ extern NSString *const TSNetworkManagerDomain;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
+ (instancetype)sharedManager;
|
||||
+ (id)sharedManager;
|
||||
|
||||
- (void)makeRequest:(TSRequest *)request
|
||||
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
|
||||
|
||||
@ -22,8 +22,7 @@ typedef void (^failureBlock)(NSURLSessionDataTask *task, NSError *error);
|
||||
|
||||
#pragma mark Singleton implementation
|
||||
|
||||
+ (instancetype)sharedManager
|
||||
{
|
||||
+ (id)sharedManager {
|
||||
static TSNetworkManager *sharedMyManager = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
|
||||
@ -160,6 +160,7 @@ NSString *const kNSNotificationName_IsCensorshipCircumventionActiveDidChange =
|
||||
DDLogInfo(@"%@ using reflector HTTPSessionManager", self.tag);
|
||||
return self.reflectorHTTPSessionManager;
|
||||
} else {
|
||||
DDLogDebug(@"%@ using default HTTPSessionManager", self.tag);
|
||||
return self.defaultHTTPSessionManager;
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,6 +156,7 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
|
||||
if (self.websocket) {
|
||||
switch ([self.websocket readyState]) {
|
||||
case SR_OPEN:
|
||||
DDLogVerbose(@"WebSocket already open on connection request");
|
||||
self.state = SocketManagerStateOpen;
|
||||
return;
|
||||
case SR_CONNECTING:
|
||||
@ -233,7 +234,7 @@ NSString *const kNSNotification_SocketManagerStateDidChange = @"kNSNotification_
|
||||
return;
|
||||
}
|
||||
|
||||
DDLogWarn(@"%@ Socket state: %@ -> %@",
|
||||
DDLogWarn(@"%@ Socket state change: %@ -> %@",
|
||||
self.tag,
|
||||
[self stringFromSocketManagerState:_state],
|
||||
[self stringFromSocketManagerState:state]);
|
||||
|
||||
@ -2,8 +2,7 @@
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSSignalServiceProtos.pb.h"
|
||||
#import "TSYapDatabaseObject.h"
|
||||
#import <SignalServiceKit/TSYapDatabaseObject.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@ -14,7 +13,6 @@ typedef NS_ENUM(NSUInteger, OWSVerificationState) {
|
||||
};
|
||||
|
||||
NSString *OWSVerificationStateToString(OWSVerificationState verificationState);
|
||||
OWSSignalServiceProtosVerifiedState OWSVerificationStateToProtoState(OWSVerificationState verificationState);
|
||||
|
||||
@interface OWSRecipientIdentity : TSYapDatabaseObject
|
||||
|
||||
|
||||
@ -20,18 +20,6 @@ NSString *OWSVerificationStateToString(OWSVerificationState verificationState)
|
||||
}
|
||||
}
|
||||
|
||||
OWSSignalServiceProtosVerifiedState OWSVerificationStateToProtoState(OWSVerificationState verificationState)
|
||||
{
|
||||
switch (verificationState) {
|
||||
case OWSVerificationStateDefault:
|
||||
return OWSSignalServiceProtosVerifiedStateDefault;
|
||||
case OWSVerificationStateVerified:
|
||||
return OWSSignalServiceProtosVerifiedStateVerified;
|
||||
case OWSVerificationStateNoLongerVerified:
|
||||
return OWSSignalServiceProtosVerifiedStateUnverified;
|
||||
}
|
||||
}
|
||||
|
||||
@interface OWSRecipientIdentity ()
|
||||
|
||||
@property (atomic) OWSVerificationState verificationState;
|
||||
@ -91,7 +79,7 @@ OWSSignalServiceProtosVerifiedState OWSVerificationStateToProtoState(OWSVerifica
|
||||
{
|
||||
changeBlock(self);
|
||||
|
||||
[[self class].dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
[[self class].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
OWSRecipientIdentity *latest = [[self class] fetchObjectWithUniqueID:self.uniqueId transaction:transaction];
|
||||
if (latest == nil) {
|
||||
[self saveWithTransaction:transaction];
|
||||
|
||||
@ -170,6 +170,7 @@ void AssertIsOnSessionStoreQueue()
|
||||
sessionRecords =
|
||||
[transaction objectForKey:contactIdentifier inCollection:TSStorageManagerSessionStoreCollection];
|
||||
|
||||
|
||||
for (id deviceId in sessionRecords) {
|
||||
id object = sessionRecords[deviceId];
|
||||
if (![object isKindOfClass:[SessionRecord class]]) {
|
||||
|
||||
@ -148,7 +148,7 @@ NSString *const TSStorageManagerKeyPrekeyCurrentSignedPrekeyId = @"currentSigned
|
||||
NSDate *firstPrekeyUpdateFailureDate = [self firstPrekeyUpdateFailureDate];
|
||||
NSUInteger prekeyUpdateFailureCount = [self prekeyUpdateFailureCount];
|
||||
|
||||
[self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
__block int i = 0;
|
||||
|
||||
DDLogInfo(@"%@ SignedPreKeys Report:", tag);
|
||||
|
||||
@ -1,30 +1,10 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Copyright (c) 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// Notes:
|
||||
//
|
||||
// * On disk, we only bother cleaning up files, not directories.
|
||||
// * For code simplicity, we don't guarantee that everything is
|
||||
// cleaned up in a single pass. If an interaction is cleaned up,
|
||||
// it's attachments might not be cleaned up until the next pass.
|
||||
// If an attachment is cleaned up, it's file on disk might not
|
||||
// be cleaned up until the next pass.
|
||||
@interface OWSOrphanedDataCleaner : NSObject
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
+ (void)auditAsync;
|
||||
|
||||
// completion, if present, will be invoked on the main thread.
|
||||
+ (void)auditAndCleanupAsync:(void (^_Nullable)())completion;
|
||||
|
||||
+ (NSSet<NSString *> *)filePathsInAttachmentsFolder;
|
||||
|
||||
+ (long long)fileSizeOfFilePaths:(NSArray<NSString *> *)filePaths;
|
||||
/**
|
||||
* Remove any inaccessible data left behind due to application bugs.
|
||||
*/
|
||||
- (void)removeOrphanedData;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Copyright (c) 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSOrphanedDataCleaner.h"
|
||||
#import "TSAttachmentStream.h"
|
||||
@ -9,256 +7,84 @@
|
||||
#import "TSStorageManager.h"
|
||||
#import "TSThread.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
#ifdef SSK_BUILDING_FOR_TESTS
|
||||
#define CleanupLogDebug NSLog
|
||||
#define CleanupLogInfo NSLog
|
||||
#else
|
||||
#define CleanupLogDebug DDLogDebug
|
||||
#define CleanupLogInfo DDLogInfo
|
||||
#endif
|
||||
|
||||
@implementation OWSOrphanedDataCleaner
|
||||
|
||||
+ (void)auditAsync
|
||||
- (void)removeOrphanedData
|
||||
{
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[OWSOrphanedDataCleaner auditAndCleanup:NO completion:nil];
|
||||
});
|
||||
}
|
||||
|
||||
+ (void)auditAndCleanupAsync:(void (^_Nullable)())completion
|
||||
{
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[OWSOrphanedDataCleaner auditAndCleanup:YES completion:completion];
|
||||
});
|
||||
}
|
||||
|
||||
// This method finds and optionally cleans up:
|
||||
//
|
||||
// * Orphan messages (with no thread).
|
||||
// * Orphan attachments (with no message).
|
||||
// * Orphan attachment files (with no attachment).
|
||||
// * Missing attachment files (cannot be cleaned up).
|
||||
// These are attachments which have no file on disk. They should be extremely rare -
|
||||
// the only cases I have seen are probably due to debugging.
|
||||
// They can't be cleaned up - we don't want to delete the TSAttachmentStream or
|
||||
// its corresponding message. Better that the broken message shows up in the
|
||||
// conversation view.
|
||||
+ (void)auditAndCleanup:(BOOL)shouldCleanup completion:(void (^_Nullable)())completion
|
||||
{
|
||||
NSSet<NSString *> *diskFilePaths = [self filePathsInAttachmentsFolder];
|
||||
long long totalFileSize = [self fileSizeOfFilePaths:diskFilePaths.allObjects];
|
||||
NSUInteger fileCount = diskFilePaths.count;
|
||||
|
||||
TSStorageManager *storageManager = [TSStorageManager sharedManager];
|
||||
YapDatabaseConnection *databaseConnection = storageManager.newDatabaseConnection;
|
||||
|
||||
__block int attachmentStreamCount = 0;
|
||||
NSMutableSet<NSString *> *attachmentFilePaths = [NSMutableSet new];
|
||||
NSMutableSet<NSString *> *attachmentIds = [NSMutableSet new];
|
||||
[databaseConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
[transaction enumerateKeysAndObjectsInCollection:TSAttachmentStream.collection
|
||||
usingBlock:^(NSString *key, TSAttachment *attachment, BOOL *stop) {
|
||||
[attachmentIds addObject:attachment.uniqueId];
|
||||
if (![attachment isKindOfClass:[TSAttachmentStream class]]) {
|
||||
return;
|
||||
}
|
||||
TSAttachmentStream *attachmentStream
|
||||
= (TSAttachmentStream *)attachment;
|
||||
attachmentStreamCount++;
|
||||
NSString *_Nullable filePath = [attachmentStream filePath];
|
||||
OWSAssert(filePath);
|
||||
[attachmentFilePaths addObject:filePath];
|
||||
}];
|
||||
}];
|
||||
|
||||
CleanupLogDebug(@"fileCount: %zd", fileCount);
|
||||
CleanupLogDebug(@"totalFileSize: %lld", totalFileSize);
|
||||
CleanupLogDebug(@"attachmentStreams: %d", attachmentStreamCount);
|
||||
CleanupLogDebug(@"attachmentStreams with file paths: %zd", attachmentFilePaths.count);
|
||||
|
||||
NSMutableSet<NSString *> *orphanDiskFilePaths = [diskFilePaths mutableCopy];
|
||||
[orphanDiskFilePaths minusSet:attachmentFilePaths];
|
||||
NSMutableSet<NSString *> *missingAttachmentFilePaths = [attachmentFilePaths mutableCopy];
|
||||
[missingAttachmentFilePaths minusSet:diskFilePaths];
|
||||
|
||||
CleanupLogDebug(@"orphan disk file paths: %zd", orphanDiskFilePaths.count);
|
||||
CleanupLogDebug(@"missing attachment file paths: %zd", missingAttachmentFilePaths.count);
|
||||
|
||||
[self printPaths:orphanDiskFilePaths.allObjects label:@"orphan disk file paths"];
|
||||
[self printPaths:missingAttachmentFilePaths.allObjects label:@"missing attachment file paths"];
|
||||
|
||||
NSMutableSet *threadIds = [NSMutableSet new];
|
||||
[databaseConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
[transaction enumerateKeysInCollection:TSThread.collection
|
||||
usingBlock:^(NSString *_Nonnull key, BOOL *_Nonnull stop) {
|
||||
[threadIds addObject:key];
|
||||
}];
|
||||
}];
|
||||
|
||||
NSMutableSet<NSString *> *orphanInteractionIds = [NSMutableSet new];
|
||||
NSMutableSet<NSString *> *messageAttachmentIds = [NSMutableSet new];
|
||||
[databaseConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
[transaction enumerateKeysAndObjectsInCollection:TSMessage.collection
|
||||
usingBlock:^(NSString *key, TSInteraction *interaction, BOOL *stop) {
|
||||
if (![threadIds containsObject:interaction.uniqueThreadId]) {
|
||||
[orphanInteractionIds addObject:interaction.uniqueId];
|
||||
}
|
||||
|
||||
if (![interaction isKindOfClass:[TSMessage class]]) {
|
||||
return;
|
||||
}
|
||||
TSMessage *message = (TSMessage *)interaction;
|
||||
if (message.attachmentIds.count > 0) {
|
||||
[messageAttachmentIds addObjectsFromArray:message.attachmentIds];
|
||||
}
|
||||
}];
|
||||
}];
|
||||
|
||||
CleanupLogDebug(@"attachmentIds: %zd", attachmentIds.count);
|
||||
CleanupLogDebug(@"messageAttachmentIds: %zd", messageAttachmentIds.count);
|
||||
|
||||
NSMutableSet<NSString *> *orphanAttachmentIds = [attachmentIds mutableCopy];
|
||||
[orphanAttachmentIds minusSet:messageAttachmentIds];
|
||||
NSMutableSet<NSString *> *missingAttachmentIds = [messageAttachmentIds mutableCopy];
|
||||
[missingAttachmentIds minusSet:attachmentIds];
|
||||
|
||||
CleanupLogDebug(@"orphan attachmentIds: %zd", orphanAttachmentIds.count);
|
||||
CleanupLogDebug(@"missing attachmentIds: %zd", missingAttachmentIds.count);
|
||||
CleanupLogDebug(@"orphan interactions: %zd", orphanInteractionIds.count);
|
||||
|
||||
// We need to avoid cleaning up new attachments and files that are still in the process of
|
||||
// being created/written, so we don't clean up anything recent.
|
||||
#ifdef SSK_BUILDING_FOR_TESTS
|
||||
const NSTimeInterval kMinimumOrphanAge = 0.f;
|
||||
#else
|
||||
const NSTimeInterval kMinimumOrphanAge = 15 * 60.f;
|
||||
#endif
|
||||
|
||||
if (!shouldCleanup) {
|
||||
return;
|
||||
// Remove interactions whose threads have been deleted
|
||||
for (NSString *interactionId in [self orphanedInteractionIds]) {
|
||||
DDLogWarn(@"Removing orphaned interaction with id: %@", interactionId);
|
||||
TSInteraction *interaction = [TSInteraction fetchObjectWithUniqueID:interactionId];
|
||||
[interaction remove];
|
||||
}
|
||||
|
||||
[databaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) {
|
||||
for (NSString *interactionId in orphanInteractionIds) {
|
||||
TSInteraction *interaction = [TSInteraction fetchObjectWithUniqueID:interactionId transaction:transaction];
|
||||
if (!interaction) {
|
||||
// This could just be a race condition, but it should be very unlikely.
|
||||
OWSFail(@"Could not load interaction: %@", interactionId);
|
||||
continue;
|
||||
}
|
||||
CleanupLogInfo(@"Removing orphan message: %@", interaction.uniqueId);
|
||||
[interaction removeWithTransaction:transaction];
|
||||
}
|
||||
for (NSString *attachmentId in orphanAttachmentIds) {
|
||||
TSAttachment *attachment = [TSAttachment fetchObjectWithUniqueID:attachmentId transaction:transaction];
|
||||
if (!attachment) {
|
||||
// This could just be a race condition, but it should be very unlikely.
|
||||
OWSFail(@"Could not load attachment: %@", attachmentId);
|
||||
continue;
|
||||
}
|
||||
if (![attachment isKindOfClass:[TSAttachmentStream class]]) {
|
||||
continue;
|
||||
}
|
||||
TSAttachmentStream *attachmentStream = (TSAttachmentStream *)attachment;
|
||||
// Don't delete attachments which were created in the last N minutes.
|
||||
if (fabs([attachmentStream.creationTimestamp timeIntervalSinceNow]) < kMinimumOrphanAge) {
|
||||
CleanupLogInfo(@"Skipping orphan attachment due to age: %f",
|
||||
fabs([attachmentStream.creationTimestamp timeIntervalSinceNow]));
|
||||
continue;
|
||||
}
|
||||
CleanupLogInfo(@"Removing orphan attachment: %@", attachmentStream.uniqueId);
|
||||
[attachmentStream removeWithTransaction:transaction];
|
||||
}
|
||||
}];
|
||||
|
||||
for (NSString *filePath in orphanDiskFilePaths) {
|
||||
// Remove any lingering attachments
|
||||
for (NSString *path in [self orphanedFilePaths]) {
|
||||
DDLogWarn(@"Removing orphaned file attachment at path: %@", path);
|
||||
NSError *error;
|
||||
NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&error];
|
||||
if (!attributes || error) {
|
||||
OWSFail(@"Could not get attributes of file at: %@", filePath);
|
||||
continue;
|
||||
}
|
||||
// Don't delete files which were created in the last N minutes.
|
||||
if (fabs([attributes.fileModificationDate timeIntervalSinceNow]) < kMinimumOrphanAge) {
|
||||
CleanupLogInfo(@"Skipping orphan attachment file due to age: %f",
|
||||
fabs([attributes.fileModificationDate timeIntervalSinceNow]));
|
||||
continue;
|
||||
}
|
||||
|
||||
CleanupLogInfo(@"Removing orphan attachment file: %@", filePath);
|
||||
[[NSFileManager defaultManager] removeItemAtPath:filePath error:&error];
|
||||
[[NSFileManager defaultManager] removeItemAtPath:path error:&error];
|
||||
if (error) {
|
||||
OWSFail(@"Could not remove orphan file at: %@", filePath);
|
||||
DDLogError(@"Unable to remove orphaned file attachment at path:%@", path);
|
||||
}
|
||||
}
|
||||
|
||||
if (completion) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
completion();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)printPaths:(NSArray<NSString *> *)paths label:(NSString *)label
|
||||
- (NSArray<NSString *> *)orphanedInteractionIds
|
||||
{
|
||||
for (NSString *path in [paths sortedArrayUsingSelector:@selector(compare:)]) {
|
||||
CleanupLogDebug(@"%@: %@", label, path);
|
||||
}
|
||||
NSMutableArray *interactionIds = [NSMutableArray new];
|
||||
[[TSInteraction dbConnection] readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
[TSInteraction enumerateCollectionObjectsWithTransaction:transaction
|
||||
usingBlock:^(TSInteraction *interaction, BOOL *stop) {
|
||||
TSThread *thread = [TSThread
|
||||
fetchObjectWithUniqueID:interaction.uniqueThreadId
|
||||
transaction:transaction];
|
||||
if (!thread) {
|
||||
[interactionIds addObject:interaction.uniqueId];
|
||||
}
|
||||
}];
|
||||
}];
|
||||
|
||||
|
||||
return [interactionIds copy];
|
||||
}
|
||||
|
||||
+ (NSSet<NSString *> *)filePathsInAttachmentsFolder
|
||||
- (NSArray<NSString *> *)orphanedFilePaths
|
||||
{
|
||||
NSString *attachmentsFolder = [TSAttachmentStream attachmentsFolder];
|
||||
CleanupLogDebug(@"attachmentsFolder: %@", attachmentsFolder);
|
||||
|
||||
return [self filePathsInDirectory:attachmentsFolder];
|
||||
}
|
||||
|
||||
+ (NSSet<NSString *> *)filePathsInDirectory:(NSString *)dirPath
|
||||
{
|
||||
NSMutableSet *filePaths = [NSMutableSet new];
|
||||
NSError *error;
|
||||
NSArray<NSString *> *fileNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dirPath error:&error];
|
||||
NSMutableArray<NSString *> *filenames =
|
||||
[[[NSFileManager defaultManager] contentsOfDirectoryAtPath:[TSAttachmentStream attachmentsFolder] error:&error]
|
||||
mutableCopy];
|
||||
if (error) {
|
||||
OWSFail(@"contentsOfDirectoryAtPath error: %@", error);
|
||||
return [NSSet new];
|
||||
DDLogError(@"error getting orphanedFilePaths:%@", error);
|
||||
return @[];
|
||||
}
|
||||
for (NSString *fileName in fileNames) {
|
||||
NSString *filePath = [dirPath stringByAppendingPathComponent:fileName];
|
||||
BOOL isDirectory;
|
||||
[[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDirectory];
|
||||
if (isDirectory) {
|
||||
[filePaths addObjectsFromArray:[self filePathsInDirectory:filePath].allObjects];
|
||||
} else {
|
||||
[filePaths addObject:filePath];
|
||||
|
||||
NSMutableDictionary<NSString *, NSString *> *attachmentIdFilenames = [NSMutableDictionary new];
|
||||
for (NSString *filename in filenames) {
|
||||
// Remove extension from (e.g.) 1234.png to get the attachmentId "1234"
|
||||
NSString *attachmentId = [filename stringByDeletingPathExtension];
|
||||
attachmentIdFilenames[attachmentId] = filename;
|
||||
}
|
||||
|
||||
[TSInteraction enumerateCollectionObjectsUsingBlock:^(TSInteraction *interaction, BOOL *stop) {
|
||||
if ([interaction isKindOfClass:[TSMessage class]]) {
|
||||
TSMessage *message = (TSMessage *)interaction;
|
||||
if ([message hasAttachments]) {
|
||||
for (NSString *attachmentId in message.attachmentIds) {
|
||||
[attachmentIdFilenames removeObjectForKey:attachmentId];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return filePaths;
|
||||
}
|
||||
}];
|
||||
|
||||
+ (long long)fileSizeOfFilePath:(NSString *)filePath
|
||||
{
|
||||
NSError *error;
|
||||
NSNumber *fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&error][NSFileSize];
|
||||
if (error) {
|
||||
OWSFail(@"attributesOfItemAtPath: %@ error: %@", filePath, error);
|
||||
return 0;
|
||||
NSArray<NSString *> *filenamesToDelete = [attachmentIdFilenames allValues];
|
||||
NSMutableArray<NSString *> *absolutePathsToDelete = [NSMutableArray arrayWithCapacity:[filenamesToDelete count]];
|
||||
for (NSString *filename in filenamesToDelete) {
|
||||
NSString *absolutePath = [[TSAttachmentStream attachmentsFolder] stringByAppendingFormat:@"/%@", filename];
|
||||
[absolutePathsToDelete addObject:absolutePath];
|
||||
}
|
||||
return fileSize.longLongValue;
|
||||
}
|
||||
|
||||
+ (long long)fileSizeOfFilePaths:(NSArray<NSString *> *)filePaths
|
||||
{
|
||||
long long result = 0;
|
||||
for (NSString *filePath in filePaths) {
|
||||
result += [self fileSizeOfFilePath:filePath];
|
||||
}
|
||||
return result;
|
||||
return [absolutePathsToDelete copy];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@ -21,9 +21,7 @@ NSString *const TSArchiveGroup = @"TSArchiveGroup";
|
||||
NSString *const TSUnreadIncomingMessagesGroup = @"TSUnreadIncomingMessagesGroup";
|
||||
NSString *const TSSecondaryDevicesGroup = @"TSSecondaryDevicesGroup";
|
||||
|
||||
// YAPDB BUG: when changing from non-persistent to persistent view, we had to rename TSThreadDatabaseViewExtensionName
|
||||
// -> TSThreadDatabaseViewExtensionName2 to work around https://github.com/yapstudios/YapDatabase/issues/324
|
||||
NSString *const TSThreadDatabaseViewExtensionName = @"TSThreadDatabaseViewExtensionName2";
|
||||
NSString *const TSThreadDatabaseViewExtensionName = @"TSThreadDatabaseViewExtensionName";
|
||||
NSString *const TSMessageDatabaseViewExtensionName = @"TSMessageDatabaseViewExtensionName";
|
||||
NSString *const TSThreadOutgoingMessageDatabaseViewExtensionName = @"TSThreadOutgoingMessageDatabaseViewExtensionName";
|
||||
NSString *const TSUnreadDatabaseViewExtensionName = @"TSUnreadDatabaseViewExtensionName";
|
||||
@ -233,7 +231,7 @@ NSString *const TSSecondaryDevicesDatabaseViewExtensionName = @"TSSecondaryDevic
|
||||
YapDatabaseViewSorting *viewSorting = [self threadSorting];
|
||||
|
||||
YapDatabaseViewOptions *options = [[YapDatabaseViewOptions alloc] init];
|
||||
options.isPersistent = YES;
|
||||
options.isPersistent = NO;
|
||||
options.allowedCollections =
|
||||
[[YapWhitelistBlacklist alloc] initWithWhitelist:[NSSet setWithObject:[TSThread collection]]];
|
||||
|
||||
|
||||
@ -53,7 +53,7 @@
|
||||
|
||||
- (void)storePhoneNumber:(NSString *)phoneNumber
|
||||
{
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction setObject:phoneNumber
|
||||
forKey:TSStorageRegisteredNumberKey
|
||||
inCollection:TSStorageUserAccountCollection];
|
||||
@ -61,12 +61,13 @@
|
||||
}
|
||||
|
||||
+ (void)storeServerToken:(NSString *)authToken signalingKey:(NSString *)signalingKey {
|
||||
TSStorageManager *sharedManager = self.sharedManager;
|
||||
[sharedManager.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction setObject:authToken forKey:TSStorageServerAuthToken inCollection:TSStorageUserAccountCollection];
|
||||
[transaction setObject:signalingKey
|
||||
forKey:TSStorageServerSignalingKey
|
||||
inCollection:TSStorageUserAccountCollection];
|
||||
YapDatabaseConnection *dbConn = [[self sharedManager] dbConnection];
|
||||
|
||||
[dbConn readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction setObject:authToken forKey:TSStorageServerAuthToken inCollection:TSStorageUserAccountCollection];
|
||||
[transaction setObject:signalingKey
|
||||
forKey:TSStorageServerSignalingKey
|
||||
inCollection:TSStorageUserAccountCollection];
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
@ -61,8 +61,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (nullable SignedPreKeyRecord *)signedPreKeyRecordForKey:(NSString *)key inCollection:(NSString *)collection;
|
||||
- (void)purgeCollection:(NSString *)collection;
|
||||
|
||||
@property (nullable, nonatomic, readonly) YapDatabaseConnection *dbReadConnection;
|
||||
@property (nullable, nonatomic, readonly) YapDatabaseConnection *dbReadWriteConnection;
|
||||
@property (nullable, nonatomic, readonly) YapDatabaseConnection *dbConnection;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@ -156,8 +156,7 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass";
|
||||
if (!_database) {
|
||||
return NO;
|
||||
}
|
||||
_dbReadConnection = self.newDatabaseConnection;
|
||||
_dbReadWriteConnection = self.newDatabaseConnection;
|
||||
_dbConnection = self.newDatabaseConnection;
|
||||
|
||||
return YES;
|
||||
}
|
||||
@ -389,19 +388,19 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass";
|
||||
#pragma mark - convenience methods
|
||||
|
||||
- (void)purgeCollection:(NSString *)collection {
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction removeAllObjectsInCollection:collection];
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction removeAllObjectsInCollection:collection];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)setObject:(id)object forKey:(NSString *)key inCollection:(NSString *)collection {
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction setObject:object forKey:key inCollection:collection];
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction setObject:object forKey:key inCollection:collection];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)removeObjectForKey:(NSString *)string inCollection:(NSString *)collection {
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction removeObjectForKey:string inCollection:collection];
|
||||
}];
|
||||
}
|
||||
@ -409,8 +408,8 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass";
|
||||
- (id)objectForKey:(NSString *)key inCollection:(NSString *)collection {
|
||||
__block NSString *object;
|
||||
|
||||
[self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
object = [transaction objectForKey:key inCollection:collection];
|
||||
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
object = [transaction objectForKey:key inCollection:collection];
|
||||
}];
|
||||
|
||||
return object;
|
||||
@ -420,8 +419,8 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass";
|
||||
{
|
||||
__block NSDictionary *object;
|
||||
|
||||
[self.dbReadConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
object = [transaction objectForKey:key inCollection:collection];
|
||||
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
object = [transaction objectForKey:key inCollection:collection];
|
||||
}];
|
||||
|
||||
return object;
|
||||
@ -480,7 +479,7 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass";
|
||||
- (int)incrementIntForKey:(NSString *)key inCollection:(NSString *)collection
|
||||
{
|
||||
__block int value = 0;
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
value = [[transaction objectForKey:key inCollection:collection] intValue];
|
||||
value++;
|
||||
[transaction setObject:@(value) forKey:key inCollection:collection];
|
||||
@ -504,11 +503,11 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass";
|
||||
}
|
||||
|
||||
- (void)deleteThreadsAndMessages {
|
||||
[self.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction removeAllObjectsInCollection:[TSThread collection]];
|
||||
[transaction removeAllObjectsInCollection:[SignalRecipient collection]];
|
||||
[transaction removeAllObjectsInCollection:[TSInteraction collection]];
|
||||
[transaction removeAllObjectsInCollection:[TSAttachment collection]];
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction removeAllObjectsInCollection:[TSThread collection]];
|
||||
[transaction removeAllObjectsInCollection:[SignalRecipient collection]];
|
||||
[transaction removeAllObjectsInCollection:[TSInteraction collection]];
|
||||
[transaction removeAllObjectsInCollection:[TSAttachment collection]];
|
||||
}];
|
||||
[TSAttachmentStream deleteAttachments];
|
||||
}
|
||||
@ -530,8 +529,7 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass";
|
||||
- (void)resetSignalStorage
|
||||
{
|
||||
self.database = nil;
|
||||
_dbReadConnection = nil;
|
||||
_dbReadWriteConnection = nil;
|
||||
_dbConnection = nil;
|
||||
|
||||
[self deletePasswordFromKeychain];
|
||||
|
||||
|
||||
@ -58,12 +58,10 @@
|
||||
usingBlock:(void (^)(id object, BOOL *stop))block;
|
||||
|
||||
/**
|
||||
* @return Shared database connections for reading and writing.
|
||||
* @return A shared database connection.
|
||||
*/
|
||||
- (YapDatabaseConnection *)dbReadConnection;
|
||||
+ (YapDatabaseConnection *)dbReadConnection;
|
||||
- (YapDatabaseConnection *)dbReadWriteConnection;
|
||||
+ (YapDatabaseConnection *)dbReadWriteConnection;
|
||||
- (YapDatabaseConnection *)dbConnection;
|
||||
+ (YapDatabaseConnection *)dbConnection;
|
||||
|
||||
- (TSStorageManager *)storageManager;
|
||||
+ (TSStorageManager *)storageManager;
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Created by Frederic Jacobs on 16/11/14.
|
||||
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "TSYapDatabaseObject.h"
|
||||
#import "TSStorageManager.h"
|
||||
@ -32,7 +31,7 @@
|
||||
|
||||
- (void)save
|
||||
{
|
||||
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[[self dbConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self saveWithTransaction:transaction];
|
||||
}];
|
||||
}
|
||||
@ -44,7 +43,7 @@
|
||||
|
||||
- (void)touch
|
||||
{
|
||||
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[[self dbConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self touchWithTransaction:transaction];
|
||||
}];
|
||||
}
|
||||
@ -56,19 +55,14 @@
|
||||
|
||||
- (void)remove
|
||||
{
|
||||
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[[self dbConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[self removeWithTransaction:transaction];
|
||||
}];
|
||||
}
|
||||
|
||||
- (YapDatabaseConnection *)dbReadConnection
|
||||
- (YapDatabaseConnection *)dbConnection
|
||||
{
|
||||
return [[self class] dbReadConnection];
|
||||
}
|
||||
|
||||
- (YapDatabaseConnection *)dbReadWriteConnection
|
||||
{
|
||||
return [[self class] dbReadWriteConnection];
|
||||
return [[self class] dbConnection];
|
||||
}
|
||||
|
||||
- (TSStorageManager *)storageManager
|
||||
@ -78,26 +72,9 @@
|
||||
|
||||
#pragma mark Class Methods
|
||||
|
||||
+ (YapDatabaseConnection *)dbReadConnection
|
||||
+ (YapDatabaseConnection *)dbConnection
|
||||
{
|
||||
// We use TSYapDatabaseObject's dbReadWriteConnection (not TSStorageManager's
|
||||
// dbReadConnection) for consistency, since we tend to [TSYapDatabaseObject
|
||||
// save] and want to write to the same connection we read from. To get true
|
||||
// consistency, we'd want to update entities by reading & writing from within
|
||||
// the same transaction, but that'll be a big refactor.
|
||||
|
||||
return self.dbReadWriteConnection;
|
||||
}
|
||||
|
||||
+ (YapDatabaseConnection *)dbReadWriteConnection
|
||||
{
|
||||
// Use a dedicated connection for model reads & writes.
|
||||
static YapDatabaseConnection *dbReadWriteConnection = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
dbReadWriteConnection = [self storageManager].newDatabaseConnection;
|
||||
});
|
||||
return dbReadWriteConnection;
|
||||
return [self storageManager].dbConnection;
|
||||
}
|
||||
|
||||
+ (TSStorageManager *)storageManager
|
||||
@ -113,7 +90,7 @@
|
||||
+ (NSUInteger)numberOfKeysInCollection
|
||||
{
|
||||
__block NSUInteger count;
|
||||
[[self dbReadConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
[[self dbConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
count = [self numberOfKeysInCollectionWithTransaction:transaction];
|
||||
}];
|
||||
return count;
|
||||
@ -135,7 +112,7 @@
|
||||
|
||||
+ (void)enumerateCollectionObjectsUsingBlock:(void (^)(id object, BOOL *stop))block
|
||||
{
|
||||
[[self dbReadConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
[[self dbConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
[self enumerateCollectionObjectsWithTransaction:transaction usingBlock:block];
|
||||
}];
|
||||
}
|
||||
@ -154,7 +131,7 @@
|
||||
|
||||
+ (void)removeAllObjectsInCollection
|
||||
{
|
||||
[[self dbReadWriteConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[[self dbConnection] readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction removeAllObjectsInCollection:[self collection]];
|
||||
}];
|
||||
}
|
||||
@ -167,7 +144,7 @@
|
||||
+ (instancetype)fetchObjectWithUniqueID:(NSString *)uniqueID
|
||||
{
|
||||
__block id object;
|
||||
[[self dbReadConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
[[self dbConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
object = [transaction objectForKey:uniqueID inCollection:[self collection]];
|
||||
}];
|
||||
return object;
|
||||
|
||||
@ -70,17 +70,8 @@
|
||||
//
|
||||
// 1. Use OWSSingletonAssertFlag() outside the class definition.
|
||||
// 2. Use OWSSingletonAssertInit() in each initializer.
|
||||
|
||||
#ifndef SSK_BUILDING_FOR_TESTS
|
||||
#ifdef DEBUG
|
||||
|
||||
#define ENFORCE_SINGLETONS
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ENFORCE_SINGLETONS
|
||||
|
||||
#define OWSSingletonAssertFlag() static BOOL _isSingletonCreated = NO;
|
||||
|
||||
#define OWSSingletonAssertInit() \
|
||||
|
||||
@ -153,6 +153,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
DDLogWarn(@"%@ Bad digest on decrypting payload. Their digest: %@, our digest: %@", self.tag, digest, ourDigest);
|
||||
return nil;
|
||||
}
|
||||
} else {
|
||||
DDLogVerbose(@"%@ %s no digest to verify", self.tag, __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
// decrypt
|
||||
|
||||
@ -420,12 +420,6 @@ NSString *const OWSMimeTypeUnknownForTests = @"unknown/mimetype";
|
||||
|
||||
+ (nullable NSString *)fileExtensionForUTIType:(NSString *)utiType
|
||||
{
|
||||
// Special-case the "aac" filetype we use for voice messages (for legacy reasons)
|
||||
// to use a .m4a file extension, not .aac, since AVAudioPlayer can't handle .aac
|
||||
// properly. Doesn't affect file contents.
|
||||
if ([utiType isEqualToString:@"public.aac-audio"]) {
|
||||
return @"m4a";
|
||||
}
|
||||
CFStringRef fileExtension
|
||||
= UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)utiType, kUTTagClassFilenameExtension);
|
||||
return (__bridge_transfer NSString *)fileExtension;
|
||||
|
||||
@ -30,10 +30,9 @@
|
||||
}
|
||||
|
||||
- (void)testSignedPreKeyDeletion {
|
||||
[[TSStorageManager sharedManager].dbReadWriteConnection
|
||||
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction removeAllObjectsInCollection:TSStorageManagerSignedPreKeyStoreCollection];
|
||||
}];
|
||||
[[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction removeAllObjectsInCollection:TSStorageManagerSignedPreKeyStoreCollection];
|
||||
}];
|
||||
|
||||
int days = 20;
|
||||
int lastPreKeyId = days;
|
||||
@ -70,10 +69,9 @@
|
||||
|
||||
- (void)testSignedPreKeyDeletionKeepsSomeOldKeys
|
||||
{
|
||||
[[TSStorageManager sharedManager].dbReadWriteConnection
|
||||
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction removeAllObjectsInCollection:TSStorageManagerSignedPreKeyStoreCollection];
|
||||
}];
|
||||
[[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction removeAllObjectsInCollection:TSStorageManagerSignedPreKeyStoreCollection];
|
||||
}];
|
||||
|
||||
int lastPreKeyId = 10;
|
||||
for (int i = 0; i <= 10; i++) {
|
||||
@ -115,11 +113,10 @@
|
||||
}
|
||||
|
||||
- (void)testOlderRecordsNotDeletedIfNoReplacement {
|
||||
[[TSStorageManager sharedManager].dbReadWriteConnection
|
||||
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction removeAllObjectsInCollection:TSStorageManagerSignedPreKeyStoreCollection];
|
||||
}];
|
||||
|
||||
[[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction removeAllObjectsInCollection:TSStorageManagerSignedPreKeyStoreCollection];
|
||||
}];
|
||||
|
||||
int days = 3;
|
||||
int lastPreKeyId = days;
|
||||
|
||||
|
||||
@ -26,7 +26,10 @@
|
||||
{
|
||||
// Sanity Check
|
||||
XCTAssertNotNil(self.localNumber);
|
||||
[[[SignalRecipient alloc] initWithTextSecureIdentifier:self.localNumber relay:nil] save];
|
||||
[[[SignalRecipient alloc] initWithTextSecureIdentifier:self.localNumber
|
||||
relay:nil
|
||||
supportsVoice:YES
|
||||
supportsWebRTC:YES] save];
|
||||
XCTAssertNotNil([SignalRecipient recipientWithTextSecureIdentifier:self.localNumber]);
|
||||
|
||||
SignalRecipient *me = [SignalRecipient selfRecipient];
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Created by Michael Kirk on 11/7/16.
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "TSContactThread.h"
|
||||
#import "OWSIdentityManager.h"
|
||||
#import "OWSUnitTestEnvironment.h"
|
||||
#import "TSStorageManager+identityKeyStore.h"
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
@ -19,9 +17,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[OWSUnitTestEnvironment ensureSetup];
|
||||
self.contactThread = [TSContactThread getOrCreateThreadWithContactId:@"fake-contact-id"];
|
||||
[OWSRecipientIdentity removeAllObjectsInCollection];
|
||||
[self.contactThread.storageManager removeIdentityKeyForRecipient:self.contactThread.contactIdentifier];
|
||||
}
|
||||
|
||||
- (void)testHasSafetyNumbersWithoutRemoteIdentity
|
||||
@ -31,8 +28,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (void)testHasSafetyNumbersWithRemoteIdentity
|
||||
{
|
||||
[[OWSIdentityManager sharedManager] saveRemoteIdentity:[NSData new]
|
||||
recipientId:self.contactThread.contactIdentifier];
|
||||
[self.contactThread.storageManager saveRemoteIdentity:[NSData new]
|
||||
recipientId:self.contactThread.contactIdentifier];
|
||||
XCTAssert(self.contactThread.hasSafetyNumbers);
|
||||
}
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
[super setUp];
|
||||
|
||||
// Register views, etc.
|
||||
[[TSStorageManager sharedManager] setupDatabaseWithSafeBlockingMigrations:^{}];
|
||||
[[TSStorageManager sharedManager] setupDatabase];
|
||||
}
|
||||
|
||||
- (void)tearDown
|
||||
@ -66,8 +66,7 @@
|
||||
XCTAssertEqual(0, [thread numberOfInteractions]);
|
||||
|
||||
NSError *error;
|
||||
TSAttachmentStream *incomingAttachment = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg"
|
||||
sourceFilename:nil];
|
||||
TSAttachmentStream *incomingAttachment = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg"];
|
||||
[incomingAttachment writeData:[NSData new] error:&error];
|
||||
[incomingAttachment save];
|
||||
|
||||
@ -84,8 +83,7 @@
|
||||
expiresInSeconds:0];
|
||||
[incomingMessage save];
|
||||
|
||||
TSAttachmentStream *outgoingAttachment = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg"
|
||||
sourceFilename:nil];
|
||||
TSAttachmentStream *outgoingAttachment = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg"];
|
||||
[outgoingAttachment writeData:[NSData new] error:&error];
|
||||
[outgoingAttachment save];
|
||||
|
||||
@ -96,7 +94,7 @@
|
||||
TSOutgoingMessage *outgoingMessage = [[TSOutgoingMessage alloc] initWithTimestamp:10000
|
||||
inThread:thread
|
||||
messageBody:@"outgoing message body"
|
||||
attachmentIds:[@[ outgoingAttachment.uniqueId ] mutableCopy]];
|
||||
attachmentIds:@[ outgoingAttachment.uniqueId ]];
|
||||
[outgoingMessage save];
|
||||
|
||||
// Sanity check
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "NSDate+millisecondTimeStamp.h"
|
||||
#import "TSAttachmentStream.h"
|
||||
@ -77,7 +75,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (void)testDescriptionWithPhotoAttachmentId
|
||||
{
|
||||
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg" sourceFilename:nil];
|
||||
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg"];
|
||||
[attachment save];
|
||||
|
||||
TSMessage *message = [[TSMessage alloc] initWithTimestamp:1
|
||||
@ -91,7 +89,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (void)testDescriptionWithVideoAttachmentId
|
||||
{
|
||||
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"video/mp4" sourceFilename:nil];
|
||||
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"video/mp4"];
|
||||
[attachment save];
|
||||
|
||||
TSMessage *message = [[TSMessage alloc] initWithTimestamp:1
|
||||
@ -102,9 +100,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
XCTAssertEqualObjects(@"📽 ATTACHMENT", actualDescription);
|
||||
}
|
||||
|
||||
|
||||
- (void)testDescriptionWithAudioAttachmentId
|
||||
{
|
||||
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"audio/mp3" sourceFilename:@"some-file.mp3"];
|
||||
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"audio/mp3"];
|
||||
[attachment save];
|
||||
|
||||
TSMessage *message = [[TSMessage alloc] initWithTimestamp:1
|
||||
@ -115,22 +114,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
XCTAssertEqualObjects(@"📻 ATTACHMENT", actualDescription);
|
||||
}
|
||||
|
||||
- (void)testDescriptionWithVoiceMessageAttachmentId
|
||||
{
|
||||
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"audio/mp3" sourceFilename:nil];
|
||||
[attachment save];
|
||||
|
||||
TSMessage *message = [[TSMessage alloc] initWithTimestamp:1
|
||||
inThread:self.thread
|
||||
messageBody:@"My message body"
|
||||
attachmentIds:@[ attachment.uniqueId ]];
|
||||
NSString *actualDescription = [message description];
|
||||
XCTAssertEqualObjects(@"🎤 ATTACHMENT_TYPE_VOICE_MESSAGE", actualDescription);
|
||||
}
|
||||
|
||||
- (void)testDescriptionWithUnkownAudioContentType
|
||||
{
|
||||
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"non/sense" sourceFilename:nil];
|
||||
TSAttachment *attachment = [[TSAttachmentStream alloc] initWithContentType:@"non/sense"];
|
||||
[attachment save];
|
||||
|
||||
TSMessage *message = [[TSMessage alloc] initWithTimestamp:1
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Created by Michael Kirk on 10/7/16.
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "TSContactThread.h"
|
||||
#import "TSOutgoingMessage.h"
|
||||
@ -35,7 +34,18 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
messageBody:nil
|
||||
attachmentIds:[NSMutableArray new]
|
||||
expiresInSeconds:10];
|
||||
[message updateWithMessageState:TSOutgoingMessageStateSentToService];
|
||||
message.messageState = TSOutgoingMessageStateSent;
|
||||
XCTAssert(message.shouldStartExpireTimer);
|
||||
}
|
||||
|
||||
- (void)testShouldStartExpireTimerWithDeliveredMessage
|
||||
{
|
||||
TSOutgoingMessage *message = [[TSOutgoingMessage alloc] initWithTimestamp:100
|
||||
inThread:self.thread
|
||||
messageBody:nil
|
||||
attachmentIds:[NSMutableArray new]
|
||||
expiresInSeconds:10];
|
||||
message.messageState = TSOutgoingMessageStateDelivered;
|
||||
XCTAssert(message.shouldStartExpireTimer);
|
||||
}
|
||||
|
||||
@ -46,7 +56,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
messageBody:nil
|
||||
attachmentIds:[NSMutableArray new]
|
||||
expiresInSeconds:10];
|
||||
[message updateWithMessageState:TSOutgoingMessageStateUnsent];
|
||||
message.messageState = TSOutgoingMessageStateUnsent;
|
||||
XCTAssertFalse(message.shouldStartExpireTimer);
|
||||
}
|
||||
|
||||
@ -57,7 +67,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
messageBody:nil
|
||||
attachmentIds:[NSMutableArray new]
|
||||
expiresInSeconds:10];
|
||||
[message updateWithMessageState:TSOutgoingMessageStateAttemptingOut];
|
||||
message.messageState = TSOutgoingMessageStateAttemptingOut;
|
||||
XCTAssertFalse(message.shouldStartExpireTimer);
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Created by Michael Kirk on 9/23/16.
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "NSDate+millisecondTimeStamp.h"
|
||||
#import "OWSDisappearingMessagesFinder.h"
|
||||
@ -13,18 +12,16 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSDisappearingMessagesFinder (Testing)
|
||||
|
||||
- (NSArray<TSMessage *> *)fetchExpiredMessagesWithTransaction:(YapDatabaseReadTransaction *)transaction;
|
||||
- (NSArray<TSMessage *> *)fetchUnstartedExpiringMessagesInThread:(TSThread *)thread
|
||||
transaction:(YapDatabaseReadTransaction *)transaction;
|
||||
- (NSArray<TSMessage *> *)fetchExpiredMessages;
|
||||
- (NSArray<TSMessage *> *)fetchUnstartedExpiringMessagesInThread:(TSThread *)thread;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface OWSDisappearingMessageFinderTest : XCTestCase
|
||||
|
||||
@property YapDatabaseConnection *dbConnection;
|
||||
@property OWSDisappearingMessagesFinder *finder;
|
||||
@property TSStorageManager *storageManager;
|
||||
@property OWSDisappearingMessagesFinder *finder;
|
||||
@property TSThread *thread;
|
||||
@property uint64_t now;
|
||||
|
||||
@ -38,14 +35,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
[TSMessage removeAllObjectsInCollection];
|
||||
|
||||
self.storageManager = [TSStorageManager sharedManager];
|
||||
self.dbConnection = self.storageManager.newDatabaseConnection;
|
||||
self.thread = [TSThread new];
|
||||
[self.thread save];
|
||||
self.now = [NSDate ows_millisecondTimeStamp];
|
||||
|
||||
// Test subject
|
||||
self.finder = [OWSDisappearingMessagesFinder new];
|
||||
[OWSDisappearingMessagesFinder blockingRegisterDatabaseExtensions:self.storageManager];
|
||||
self.finder = [[OWSDisappearingMessagesFinder alloc] initWithStorageManager:self.storageManager];
|
||||
[self.finder blockingRegisterDatabaseExtensions];
|
||||
}
|
||||
|
||||
- (void)testExpiredMessages
|
||||
@ -94,11 +90,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
[[TSMessage alloc] initWithTimestamp:1 inThread:self.thread messageBody:@"unexpiringMessage2"];
|
||||
[unExpiringMessage2 save];
|
||||
|
||||
__block NSArray<TSMessage *> *actualMessages;
|
||||
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction * _Nonnull transaction) {
|
||||
actualMessages = [self.finder fetchExpiredMessagesWithTransaction:transaction];
|
||||
}];
|
||||
|
||||
NSArray<TSMessage *> *actualMessages = [self.finder fetchExpiredMessages];
|
||||
NSArray<TSMessage *> *expectedMessages = @[ expiredMessage1, expiredMessage2 ];
|
||||
XCTAssertEqualObjects(expectedMessages, actualMessages);
|
||||
}
|
||||
@ -141,33 +133,15 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
[[TSMessage alloc] initWithTimestamp:1 inThread:self.thread messageBody:@"unexpiringMessage2"];
|
||||
[unExpiringMessage2 save];
|
||||
|
||||
__block NSArray<TSMessage *> *actualMessages;
|
||||
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction * _Nonnull transaction) {
|
||||
actualMessages = [self.finder fetchUnstartedExpiringMessagesInThread:self.thread
|
||||
transaction:transaction];
|
||||
}];
|
||||
|
||||
NSArray<TSMessage *> *actualMessages = [self.finder fetchUnstartedExpiringMessagesInThread:self.thread];
|
||||
NSArray<TSMessage *> *expectedMessages = @[ unreadExpiringMessage ];
|
||||
XCTAssertEqualObjects(expectedMessages, actualMessages);
|
||||
}
|
||||
|
||||
- (NSNumber *)nextExpirationTimestamp
|
||||
{
|
||||
__block NSNumber *nextExpirationTimestamp;
|
||||
|
||||
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction * _Nonnull transaction) {
|
||||
XCTAssertNotNil(self.finder);
|
||||
nextExpirationTimestamp = [self.finder nextExpirationTimestampWithTransaction:transaction];
|
||||
}];
|
||||
|
||||
return nextExpirationTimestamp;
|
||||
}
|
||||
|
||||
- (void)testNextExpirationTimestampNilWhenNoExpiringMessages
|
||||
{
|
||||
// Sanity check.
|
||||
|
||||
XCTAssertNil(self.nextExpirationTimestamp);
|
||||
XCTAssertNil(self.finder.nextExpirationTimestamp);
|
||||
|
||||
TSMessage *unExpiringMessage = [[TSMessage alloc] initWithTimestamp:1
|
||||
inThread:self.thread
|
||||
@ -176,7 +150,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
expiresInSeconds:0
|
||||
expireStartedAt:0];
|
||||
[unExpiringMessage save];
|
||||
XCTAssertNil(self.nextExpirationTimestamp);
|
||||
XCTAssertNil(self.finder.nextExpirationTimestamp);
|
||||
}
|
||||
|
||||
- (void)testNextExpirationTimestampNotNilWithUpcomingExpiringMessages
|
||||
@ -189,8 +163,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
expireStartedAt:self.now - 9000];
|
||||
[soonToExpireMessage save];
|
||||
|
||||
XCTAssertNotNil(self.nextExpirationTimestamp);
|
||||
XCTAssertEqual(self.now + 1000, [self.nextExpirationTimestamp unsignedLongLongValue]);
|
||||
XCTAssertNotNil(self.finder.nextExpirationTimestamp);
|
||||
XCTAssertEqual(self.now + 1000, [self.finder.nextExpirationTimestamp unsignedLongLongValue]);
|
||||
|
||||
// expired message should take precedence
|
||||
TSMessage *expiredMessage = [[TSMessage alloc] initWithTimestamp:1
|
||||
@ -201,10 +175,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
expireStartedAt:self.now - 11000];
|
||||
[expiredMessage save];
|
||||
|
||||
//FIXME remove sleep hack in favor of expiringMessage completion handler
|
||||
// sleep(2);
|
||||
XCTAssertNotNil(self.nextExpirationTimestamp);
|
||||
XCTAssertEqual(self.now - 1000, [self.nextExpirationTimestamp unsignedLongLongValue]);
|
||||
XCTAssertNotNil(self.finder.nextExpirationTimestamp);
|
||||
XCTAssertEqual(self.now - 1000, [self.finder.nextExpirationTimestamp unsignedLongLongValue]);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Created by Michael Kirk on 9/23/16.
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "NSDate+millisecondTimeStamp.h"
|
||||
#import "OWSDisappearingMessagesConfiguration.h"
|
||||
@ -14,14 +13,6 @@
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSDisappearingMessagesJob (Testing)
|
||||
|
||||
- (void)run;
|
||||
- (void)becomeConsistentWithConfigurationForMessage:(TSMessage *)message
|
||||
contactsManager:(id<ContactsManagerProtocol>)contactsManager;
|
||||
|
||||
@end
|
||||
|
||||
@interface OWSDisappearingMessagesJobTest : XCTestCase
|
||||
|
||||
@end
|
||||
@ -70,15 +61,12 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
expireStartedAt:0];
|
||||
[unExpiringMessage save];
|
||||
|
||||
|
||||
OWSDisappearingMessagesJob *job = [OWSDisappearingMessagesJob sharedJob];
|
||||
OWSDisappearingMessagesJob *job =
|
||||
[[OWSDisappearingMessagesJob alloc] initWithStorageManager:[TSStorageManager sharedManager]];
|
||||
|
||||
// Sanity Check.
|
||||
XCTAssertEqual(4, [TSMessage numberOfKeysInCollection]);
|
||||
[job run];
|
||||
|
||||
//FIXME remove sleep hack in favor of expiringMessage completion handler
|
||||
sleep(4);
|
||||
XCTAssertEqual(2, [TSMessage numberOfKeysInCollection]);
|
||||
}
|
||||
|
||||
@ -87,8 +75,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
TSThread *thread = [[TSThread alloc] initWithUniqueId:@"fake-thread-id"];
|
||||
[thread save];
|
||||
|
||||
OWSDisappearingMessagesJob *job = [OWSDisappearingMessagesJob sharedJob];
|
||||
|
||||
OWSDisappearingMessagesJob *job =
|
||||
[[OWSDisappearingMessagesJob alloc] initWithStorageManager:[TSStorageManager sharedManager]];
|
||||
|
||||
OWSDisappearingMessagesConfiguration *configuration =
|
||||
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId];
|
||||
[configuration remove];
|
||||
@ -101,6 +90,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
expireStartedAt:0];
|
||||
[expiringMessage save];
|
||||
|
||||
|
||||
[job becomeConsistentWithConfigurationForMessage:expiringMessage contactsManager:[OWSFakeContactsManager new]];
|
||||
configuration = [OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId];
|
||||
|
||||
@ -114,10 +104,14 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
TSThread *thread = [[TSThread alloc] initWithUniqueId:@"fake-thread-id"];
|
||||
[thread save];
|
||||
|
||||
OWSDisappearingMessagesJob *job =
|
||||
[[OWSDisappearingMessagesJob alloc] initWithStorageManager:[TSStorageManager sharedManager]];
|
||||
|
||||
OWSDisappearingMessagesConfiguration *configuration =
|
||||
[OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId];
|
||||
[configuration remove];
|
||||
|
||||
|
||||
TSMessage *unExpiringMessage = [[TSMessage alloc] initWithTimestamp:1
|
||||
inThread:thread
|
||||
messageBody:@"unexpiringMessage"
|
||||
@ -125,7 +119,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
expiresInSeconds:0
|
||||
expireStartedAt:0];
|
||||
[unExpiringMessage save];
|
||||
[OWSDisappearingMessagesJob becomeConsistentWithConfigurationForMessage:unExpiringMessage contactsManager:[OWSFakeContactsManager new]];
|
||||
[job becomeConsistentWithConfigurationForMessage:unExpiringMessage contactsManager:[OWSFakeContactsManager new]];
|
||||
XCTAssertNil([OWSDisappearingMessagesConfiguration fetchObjectWithUniqueID:thread.uniqueId]);
|
||||
}
|
||||
|
||||
|
||||
@ -94,10 +94,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
if (self.shouldSucceed) {
|
||||
successHandler();
|
||||
} else {
|
||||
NSError *error = OWSErrorMakeFailedToSendOutgoingMessageError();
|
||||
[error setIsRetryable:NO];
|
||||
|
||||
failureHandler(error);
|
||||
failureHandler(OWSErrorMakeFailedToSendOutgoingMessageError());
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,7 +130,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSMessageSenderFakeNetworkManager : OWSFakeNetworkManager
|
||||
|
||||
- (instancetype)init;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
- (instancetype)initWithSuccess:(BOOL)shouldSucceed NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@property (nonatomic, readonly) BOOL shouldSucceed;
|
||||
@ -144,7 +141,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (instancetype)initWithSuccess:(BOOL)shouldSucceed
|
||||
{
|
||||
self = [self init];
|
||||
self = [super init];
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
@ -243,8 +240,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
XCTestExpectation *messageStartedExpiration = [self expectationWithDescription:@"messageStartedExpiration"];
|
||||
[messageSender sendMessage:self.expiringMessage
|
||||
success:^() {
|
||||
//FIXME remove sleep hack in favor of expiringMessage completion handler
|
||||
sleep(2);
|
||||
if (self.expiringMessage.expiresAt > 0) {
|
||||
[messageStartedExpiration fulfill];
|
||||
} else {
|
||||
@ -321,7 +316,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
XCTestExpectation *markedAsSent = [self expectationWithDescription:@"markedAsSent"];
|
||||
[messageSender sendMessage:message
|
||||
success:^() {
|
||||
if (message.messageState == TSOutgoingMessageStateSentToService) {
|
||||
if (message.messageState == TSOutgoingMessageStateSent) {
|
||||
[markedAsSent fulfill];
|
||||
} else {
|
||||
XCTFail(@"Unexpected message state");
|
||||
@ -346,10 +341,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
XCTestExpectation *markedAsSent = [self expectationWithDescription:@"markedAsSent"];
|
||||
[messageSender sendAttachmentData:[NSData new]
|
||||
contentType:@"image/gif"
|
||||
sourceFilename:nil
|
||||
inMessage:message
|
||||
success:^() {
|
||||
if (message.messageState == TSOutgoingMessageStateSentToService) {
|
||||
if (message.messageState == TSOutgoingMessageStateSent) {
|
||||
[markedAsSent fulfill];
|
||||
} else {
|
||||
XCTFail(@"Unexpected message state");
|
||||
@ -400,7 +394,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
XCTestExpectation *markedAsUnsent = [self expectationWithDescription:@"markedAsUnsent"];
|
||||
[messageSender sendAttachmentData:[NSData new]
|
||||
contentType:@"image/gif"
|
||||
sourceFilename:nil
|
||||
inMessage:message
|
||||
success:^{
|
||||
XCTFail(@"sendMessage should fail.");
|
||||
@ -429,7 +422,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
XCTestExpectation *markedAsUnsent = [self expectationWithDescription:@"markedAsUnsent"];
|
||||
[messageSender sendAttachmentData:[NSData new]
|
||||
contentType:@"image/gif"
|
||||
sourceFilename:nil
|
||||
inMessage:message
|
||||
success:^{
|
||||
XCTFail(@"sendMessage should fail.");
|
||||
@ -452,9 +444,15 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NSData *groupIdData = [Cryptography generateRandomBytes:32];
|
||||
SignalRecipient *successfulRecipient =
|
||||
[[SignalRecipient alloc] initWithTextSecureIdentifier:@"successful-recipient-id" relay:nil];
|
||||
[[SignalRecipient alloc] initWithTextSecureIdentifier:@"successful-recipient-id"
|
||||
relay:nil
|
||||
supportsVoice:YES
|
||||
supportsWebRTC:YES];
|
||||
SignalRecipient *successfulRecipient2 =
|
||||
[[SignalRecipient alloc] initWithTextSecureIdentifier:@"successful-recipient-id2" relay:nil];
|
||||
[[SignalRecipient alloc] initWithTextSecureIdentifier:@"successful-recipient-id2"
|
||||
relay:nil
|
||||
supportsVoice:YES
|
||||
supportsWebRTC:YES];
|
||||
|
||||
TSGroupModel *groupModel = [[TSGroupModel alloc]
|
||||
initWithTitle:@"group title"
|
||||
@ -469,7 +467,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
XCTestExpectation *markedAsSent = [self expectationWithDescription:@"markedAsSent"];
|
||||
[messageSender sendMessage:message
|
||||
success:^{
|
||||
if (message.messageState == TSOutgoingMessageStateSentToService) {
|
||||
if (message.messageState == TSOutgoingMessageStateSent) {
|
||||
[markedAsSent fulfill];
|
||||
} else {
|
||||
XCTFail(@"Unexpected message state");
|
||||
@ -485,7 +483,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (void)testGetRecipients
|
||||
{
|
||||
SignalRecipient *recipient = [[SignalRecipient alloc] initWithTextSecureIdentifier:@"fake-recipient-id" relay:nil];
|
||||
SignalRecipient *recipient = [[SignalRecipient alloc] initWithTextSecureIdentifier:@"fake-recipient-id"
|
||||
relay:nil
|
||||
supportsVoice:YES
|
||||
supportsWebRTC:YES];
|
||||
[recipient save];
|
||||
|
||||
OWSMessageSender *messageSender = self.successfulMessageSender;
|
||||
|
||||
@ -17,9 +17,7 @@
|
||||
#import "TSGroupThread.h"
|
||||
#import "TSMessagesManager.h"
|
||||
#import "TSNetworkManager.h"
|
||||
#import "OWSIdentityManager.h"
|
||||
#import "TSStorageManager.h"
|
||||
#import "OWSUnitTestEnvironment.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@ -32,7 +30,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
callMessageHandler:(id<OWSCallMessageHandler>)callMessageHandler
|
||||
contactsManager:(id<ContactsManagerProtocol>)contactsManager
|
||||
contactsUpdater:(ContactsUpdater *)contactsUpdater
|
||||
identityManager:(OWSIdentityManager *)identityManager
|
||||
messageSender:(OWSMessageSender *)messageSender;
|
||||
|
||||
// private method we are testing
|
||||
@ -57,17 +54,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
callMessageHandler:[OWSFakeCallMessageHandler new]
|
||||
contactsManager:[OWSFakeContactsManager new]
|
||||
contactsUpdater:[OWSFakeContactsUpdater new]
|
||||
identityManager:[OWSIdentityManager sharedManager]
|
||||
messageSender:messageSender];
|
||||
}
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
|
||||
[OWSUnitTestEnvironment ensureSetup];
|
||||
}
|
||||
|
||||
- (void)testIncomingSyncContactMessage
|
||||
{
|
||||
XCTestExpectation *messageWasSent = [self expectationWithDescription:@"message was sent"];
|
||||
|
||||
@ -14,19 +14,17 @@
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@implementation OWSOrphanedDataCleanerTest
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
// Register views, etc.
|
||||
[[TSStorageManager sharedManager] setupDatabaseWithSafeBlockingMigrations:^{}];
|
||||
[[TSStorageManager sharedManager] setupDatabase];
|
||||
|
||||
// Set up initial conditions & Sanity check
|
||||
[TSAttachmentStream deleteAttachments];
|
||||
XCTAssertEqual(0, [self numberOfItemsInAttachmentsFolder]);
|
||||
XCTAssertEqual(0, [TSAttachmentStream numberOfItemsInAttachmentsFolder]);
|
||||
[TSAttachmentStream removeAllObjectsInCollection];
|
||||
XCTAssertEqual(0, [TSAttachmentStream numberOfKeysInCollection]);
|
||||
[TSIncomingMessage removeAllObjectsInCollection];
|
||||
@ -40,11 +38,6 @@
|
||||
[super tearDown];
|
||||
}
|
||||
|
||||
- (NSUInteger)numberOfItemsInAttachmentsFolder
|
||||
{
|
||||
return [OWSOrphanedDataCleaner filePathsInAttachmentsFolder].count;
|
||||
}
|
||||
|
||||
- (void)testInteractionsWithoutThreadAreDeleted
|
||||
{
|
||||
// This thread is intentionally not saved. It's meant to recreate a situation we've seen where interactions exist
|
||||
@ -60,17 +53,7 @@
|
||||
[incomingMessage save];
|
||||
XCTAssertEqual(1, [TSIncomingMessage numberOfKeysInCollection]);
|
||||
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"Cleanup"];
|
||||
[OWSOrphanedDataCleaner auditAndCleanupAsync:^{
|
||||
[expectation fulfill];
|
||||
}];
|
||||
[self waitForExpectationsWithTimeout:5.0
|
||||
handler:^(NSError *error) {
|
||||
if (error) {
|
||||
XCTFail(@"Expectation Failed with error: %@", error);
|
||||
}
|
||||
}];
|
||||
|
||||
[[OWSOrphanedDataCleaner new] removeOrphanedData];
|
||||
XCTAssertEqual(0, [TSIncomingMessage numberOfKeysInCollection]);
|
||||
}
|
||||
|
||||
@ -87,51 +70,25 @@
|
||||
[incomingMessage save];
|
||||
XCTAssertEqual(1, [TSIncomingMessage numberOfKeysInCollection]);
|
||||
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"Cleanup"];
|
||||
[OWSOrphanedDataCleaner auditAndCleanupAsync:^{
|
||||
[expectation fulfill];
|
||||
}];
|
||||
[self waitForExpectationsWithTimeout:5.0
|
||||
handler:^(NSError *error) {
|
||||
if (error) {
|
||||
XCTFail(@"Expectation Failed with error: %@", error);
|
||||
}
|
||||
}];
|
||||
|
||||
[[OWSOrphanedDataCleaner new] removeOrphanedData];
|
||||
XCTAssertEqual(1, [TSIncomingMessage numberOfKeysInCollection]);
|
||||
}
|
||||
|
||||
- (void)testFilesWithoutInteractionsAreDeleted
|
||||
{
|
||||
// sanity check
|
||||
XCTAssertEqual(0, [self numberOfItemsInAttachmentsFolder]);
|
||||
|
||||
NSError *error;
|
||||
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg" sourceFilename:nil];
|
||||
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg"];
|
||||
[attachmentStream writeData:[NSData new] error:&error];
|
||||
[attachmentStream save];
|
||||
NSString *orphanedFilePath = [attachmentStream filePath];
|
||||
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:orphanedFilePath];
|
||||
XCTAssert(fileExists);
|
||||
XCTAssertEqual(1, [self numberOfItemsInAttachmentsFolder]);
|
||||
|
||||
// Do multiple cleanup passes.
|
||||
for (int i = 0; i < 2; i++) {
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"Cleanup"];
|
||||
[OWSOrphanedDataCleaner auditAndCleanupAsync:^{
|
||||
[expectation fulfill];
|
||||
}];
|
||||
[self waitForExpectationsWithTimeout:5.0
|
||||
handler:^(NSError *error) {
|
||||
if (error) {
|
||||
XCTFail(@"Expectation Failed with error: %@", error);
|
||||
}
|
||||
}];
|
||||
}
|
||||
XCTAssertEqual(1, [TSAttachmentStream numberOfItemsInAttachmentsFolder]);
|
||||
|
||||
[[OWSOrphanedDataCleaner new] removeOrphanedData];
|
||||
fileExists = [[NSFileManager defaultManager] fileExistsAtPath:orphanedFilePath];
|
||||
XCTAssertFalse(fileExists);
|
||||
XCTAssertEqual(0, [self numberOfItemsInAttachmentsFolder]);
|
||||
XCTAssertEqual(0, [TSAttachmentStream numberOfItemsInAttachmentsFolder]);
|
||||
}
|
||||
|
||||
- (void)testFilesWithInteractionsAreNotDeleted
|
||||
@ -140,7 +97,7 @@
|
||||
[savedThread save];
|
||||
|
||||
NSError *error;
|
||||
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg" sourceFilename:nil];
|
||||
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg"];
|
||||
[attachmentStream writeData:[NSData new] error:&error];
|
||||
[attachmentStream save];
|
||||
|
||||
@ -156,50 +113,32 @@
|
||||
NSString *attachmentFilePath = [attachmentStream filePath];
|
||||
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:attachmentFilePath];
|
||||
XCTAssert(fileExists);
|
||||
XCTAssertEqual(1, [self numberOfItemsInAttachmentsFolder]);
|
||||
XCTAssertEqual(1, [TSAttachmentStream numberOfItemsInAttachmentsFolder]);
|
||||
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"Cleanup"];
|
||||
[OWSOrphanedDataCleaner auditAndCleanupAsync:^{
|
||||
[expectation fulfill];
|
||||
}];
|
||||
[self waitForExpectationsWithTimeout:5.0
|
||||
handler:^(NSError *error) {
|
||||
if (error) {
|
||||
XCTFail(@"Expectation Failed with error: %@", error);
|
||||
}
|
||||
}];
|
||||
[[OWSOrphanedDataCleaner new] removeOrphanedData];
|
||||
|
||||
fileExists = [[NSFileManager defaultManager] fileExistsAtPath:attachmentFilePath];
|
||||
XCTAssert(fileExists);
|
||||
XCTAssertEqual(1, [self numberOfItemsInAttachmentsFolder]);
|
||||
XCTAssertEqual(1, [TSAttachmentStream numberOfItemsInAttachmentsFolder]);
|
||||
}
|
||||
|
||||
- (void)testFilesWithoutAttachmentStreamsAreDeleted
|
||||
{
|
||||
NSError *error;
|
||||
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg" sourceFilename:nil];
|
||||
TSAttachmentStream *attachmentStream = [[TSAttachmentStream alloc] initWithContentType:@"image/jpeg"];
|
||||
[attachmentStream writeData:[NSData new] error:&error];
|
||||
// Intentionally not saved, because we want a lingering file.
|
||||
|
||||
|
||||
NSString *orphanedFilePath = [attachmentStream filePath];
|
||||
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:orphanedFilePath];
|
||||
XCTAssert(fileExists);
|
||||
XCTAssertEqual(1, [self numberOfItemsInAttachmentsFolder]);
|
||||
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"Cleanup"];
|
||||
[OWSOrphanedDataCleaner auditAndCleanupAsync:^{
|
||||
[expectation fulfill];
|
||||
}];
|
||||
[self waitForExpectationsWithTimeout:5.0
|
||||
handler:^(NSError *error) {
|
||||
if (error) {
|
||||
XCTFail(@"Expectation Failed with error: %@", error);
|
||||
}
|
||||
}];
|
||||
XCTAssertEqual(1, [TSAttachmentStream numberOfItemsInAttachmentsFolder]);
|
||||
|
||||
[[OWSOrphanedDataCleaner new] removeOrphanedData];
|
||||
fileExists = [[NSFileManager defaultManager] fileExistsAtPath:orphanedFilePath];
|
||||
XCTAssertFalse(fileExists);
|
||||
XCTAssertEqual(0, [self numberOfItemsInAttachmentsFolder]);
|
||||
XCTAssertEqual(0, [TSAttachmentStream numberOfItemsInAttachmentsFolder]);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -27,14 +27,13 @@
|
||||
- (void)setUp
|
||||
{
|
||||
[super setUp];
|
||||
|
||||
[[TSStorageManager sharedManager].dbReadWriteConnection
|
||||
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
self.thread = [TSContactThread getOrCreateThreadWithContactId:@"aStupidId" transaction:transaction];
|
||||
|
||||
[self.thread saveWithTransaction:transaction];
|
||||
}];
|
||||
|
||||
|
||||
[[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
self.thread = [TSContactThread getOrCreateThreadWithContactId:@"aStupidId" transaction:transaction];
|
||||
|
||||
[self.thread saveWithTransaction:transaction];
|
||||
}];
|
||||
|
||||
TSStorageManager *manager = [TSStorageManager sharedManager];
|
||||
[manager purgeCollection:[TSMessage collection]];
|
||||
}
|
||||
@ -155,8 +154,7 @@
|
||||
NSString *body = @"A child born today will grow up with no conception of privacy at all. They’ll never know what it means to have a private moment to themselves an unrecorded, unanalyzed thought. And that’s a problem because privacy matters; privacy is what allows us to determine who we are and who we want to be.";
|
||||
|
||||
__block TSGroupThread *thread;
|
||||
[[TSStorageManager sharedManager].dbReadWriteConnection readWriteWithBlock:^(
|
||||
YapDatabaseReadWriteTransaction *transaction) {
|
||||
[[TSStorageManager sharedManager].dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
thread = [TSGroupThread getOrCreateThreadWithGroupModel:[[TSGroupModel alloc] initWithTitle:@"fdsfsd"
|
||||
memberIds:[@[] mutableCopy]
|
||||
image:nil
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
// TSStorageIdentityKeyStoreTests.m
|
||||
// TextSecureKit
|
||||
//
|
||||
// Created by Frederic Jacobs on 06/11/14.
|
||||
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
@ -7,8 +11,8 @@
|
||||
|
||||
#import "OWSUnitTestEnvironment.h"
|
||||
#import "SecurityUtils.h"
|
||||
#import "OWSIdentityManager.h"
|
||||
#import "OWSRecipientIdentity.h"
|
||||
#import "TSPrivacyPreferences.h"
|
||||
#import "TSStorageManager+IdentityKeyStore.h"
|
||||
#import "TSStorageManager.h"
|
||||
#import "TextSecureKitEnv.h"
|
||||
|
||||
@ -20,9 +24,8 @@
|
||||
|
||||
- (void)setUp {
|
||||
[super setUp];
|
||||
|
||||
[[TSStorageManager sharedManager] purgeCollection:@"TSStorageManagerTrustedKeysCollection"];
|
||||
[OWSRecipientIdentity removeAllObjectsInCollection];
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
- (void)tearDown {
|
||||
@ -34,42 +37,61 @@
|
||||
NSData *newKey = [SecurityUtils generateRandomBytes:32];
|
||||
NSString *recipientId = @"test@gmail.com";
|
||||
|
||||
XCTAssert([[OWSIdentityManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId direction:TSMessageDirectionOutgoing]);
|
||||
XCTAssert([[OWSIdentityManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId direction:TSMessageDirectionIncoming]);
|
||||
XCTAssert([[TSStorageManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId]);
|
||||
}
|
||||
|
||||
- (void)testAlreadyRegisteredKey {
|
||||
NSData *newKey = [SecurityUtils generateRandomBytes:32];
|
||||
NSString *recipientId = @"test@gmail.com";
|
||||
|
||||
[[OWSIdentityManager sharedManager] saveRemoteIdentity:newKey recipientId:recipientId];
|
||||
[[TSStorageManager sharedManager] saveRemoteIdentity:newKey recipientId:recipientId];
|
||||
|
||||
XCTAssert([[OWSIdentityManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId direction:TSMessageDirectionOutgoing]);
|
||||
XCTAssert([[OWSIdentityManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId direction:TSMessageDirectionIncoming]);
|
||||
XCTAssert([[TSStorageManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId]);
|
||||
}
|
||||
|
||||
|
||||
- (void)testChangedKey
|
||||
- (void)testChangedKeyWithBlockingIdentityChanges
|
||||
{
|
||||
NSData *originalKey = [SecurityUtils generateRandomBytes:32];
|
||||
NSString *recipientId = @"test@protonmail.com";
|
||||
TSPrivacyPreferences *preferences = [TSPrivacyPreferences sharedInstance];
|
||||
preferences.shouldBlockOnIdentityChange = YES;
|
||||
[preferences save];
|
||||
|
||||
[[OWSIdentityManager sharedManager] saveRemoteIdentity:originalKey recipientId:recipientId];
|
||||
NSData *newKey = [SecurityUtils generateRandomBytes:32];
|
||||
NSString *recipientId = @"test@gmail.com";
|
||||
|
||||
[[TSStorageManager sharedManager] saveRemoteIdentity:newKey recipientId:recipientId];
|
||||
|
||||
XCTAssert([[OWSIdentityManager sharedManager] isTrustedIdentityKey:originalKey recipientId:recipientId direction:TSMessageDirectionOutgoing]);
|
||||
XCTAssert([[OWSIdentityManager sharedManager] isTrustedIdentityKey:originalKey recipientId:recipientId direction:TSMessageDirectionIncoming]);
|
||||
XCTAssert([[TSStorageManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId]);
|
||||
|
||||
NSData *otherKey = [SecurityUtils generateRandomBytes:32];
|
||||
|
||||
XCTAssertFalse([[OWSIdentityManager sharedManager] isTrustedIdentityKey:otherKey recipientId:recipientId direction:TSMessageDirectionOutgoing]);
|
||||
XCTAssert([[OWSIdentityManager sharedManager] isTrustedIdentityKey:otherKey recipientId:recipientId direction:TSMessageDirectionIncoming]);
|
||||
XCTAssertFalse([[TSStorageManager sharedManager] isTrustedIdentityKey:otherKey recipientId:recipientId]);
|
||||
}
|
||||
|
||||
|
||||
- (void)testChangedKeyWithNonBlockingIdentityChanges
|
||||
{
|
||||
TSPrivacyPreferences *preferences = [TSPrivacyPreferences sharedInstance];
|
||||
preferences.shouldBlockOnIdentityChange = NO;
|
||||
[preferences save];
|
||||
|
||||
NSData *newKey = [SecurityUtils generateRandomBytes:32];
|
||||
NSString *recipientId = @"test@gmail.com";
|
||||
|
||||
[[TSStorageManager sharedManager] saveRemoteIdentity:newKey recipientId:recipientId];
|
||||
|
||||
XCTAssert([[TSStorageManager sharedManager] isTrustedIdentityKey:newKey recipientId:recipientId]);
|
||||
|
||||
NSData *otherKey = [SecurityUtils generateRandomBytes:32];
|
||||
|
||||
[TextSecureKitEnv setSharedEnv:[OWSUnitTestEnvironment new]];
|
||||
XCTAssertTrue([[TSStorageManager sharedManager] isTrustedIdentityKey:otherKey recipientId:recipientId]);
|
||||
}
|
||||
|
||||
- (void)testIdentityKey {
|
||||
[[OWSIdentityManager sharedManager] generateNewIdentityKey];
|
||||
[[TSStorageManager sharedManager] generateNewIdentityKey];
|
||||
|
||||
XCTAssert([[[OWSIdentityManager sharedManager] identityKeyPair].publicKey length] == 32);
|
||||
XCTAssert([[[TSStorageManager sharedManager] identityKeyPair].publicKey length] == 32);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Created by Michael Kirk on 10/7/16.
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSFakeContactsManager.h"
|
||||
|
||||
@ -15,12 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
return @"Fake name";
|
||||
}
|
||||
|
||||
- (NSArray<Contact *> *)signalContacts
|
||||
{
|
||||
return @[];
|
||||
}
|
||||
|
||||
- (NSArray<SignalAccount *> *)signalAccounts
|
||||
- (NSArray<Contact *> * _Nonnull)signalContacts
|
||||
{
|
||||
return @[];
|
||||
}
|
||||
|
||||
@ -13,7 +13,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
{
|
||||
NSLog(@"[OWSFakeContactsUpdater] Faking contact lookup.");
|
||||
return [[SignalRecipient alloc] initWithTextSecureIdentifier:@"fake-recipient-id"
|
||||
relay:nil];
|
||||
relay:nil
|
||||
supportsVoice:YES
|
||||
supportsWebRTC:YES];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -9,7 +9,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSFakeMessageSender : OWSMessageSender
|
||||
|
||||
- (instancetype)init;
|
||||
- (instancetype)initWithExpectation:(XCTestExpectation *)expectation;
|
||||
|
||||
@property (nonatomic, readonly) XCTestExpectation *expectation;
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Created by Michael Kirk on 12/18/16.
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSFakeNotificationsManager.h"
|
||||
|
||||
@ -9,8 +8,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@implementation OWSFakeNotificationsManager
|
||||
|
||||
- (void)notifyUserForIncomingMessage:(TSIncomingMessage *)incomingMessage
|
||||
from:(NSString *)name
|
||||
inThread:(TSThread *)thread
|
||||
contactsManager:(id<ContactsManagerProtocol>)contactsManager
|
||||
{
|
||||
NSLog(@"%s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Created by Michael Kirk on 12/18/16.
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "TextSecureKitEnv.h"
|
||||
|
||||
@ -8,7 +7,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSUnitTestEnvironment : TextSecureKitEnv
|
||||
|
||||
+ (void)ensureSetup;
|
||||
- (instancetype)initDefault;
|
||||
|
||||
@end
|
||||
|
||||
@ -12,15 +12,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation OWSUnitTestEnvironment
|
||||
|
||||
+ (void)ensureSetup
|
||||
{
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
[self setSharedEnv:[[self alloc] initDefault]];
|
||||
});
|
||||
}
|
||||
|
||||
- (instancetype)initDefault
|
||||
- (instancetype)init
|
||||
{
|
||||
return [super initWithCallMessageHandler:[OWSFakeCallMessageHandler new]
|
||||
contactsManager:[OWSFakeContactsManager new]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user