mirror of https://github.com/oxen-io/session-ios
439 changed files with 77334 additions and 114 deletions
@ -1 +1 @@
|
||||
Subproject commit 0c79ca436b633fdf1b0daf90e86fd323dcc60c55 |
||||
Subproject commit e28da414f77b9cba508c92e90b16b815847cde7e |
@ -1,20 +0,0 @@
|
||||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h> |
||||
|
||||
@interface Randomness : NSObject |
||||
|
||||
/**
|
||||
* Generates a given number of cryptographically secure bytes using SecRandomCopyBytes. |
||||
* |
||||
* @param numberBytes The number of bytes to be generated. |
||||
* |
||||
* @return Random Bytes. |
||||
*/ |
||||
|
||||
+ (NSData *)generateRandomBytes:(int)numberBytes; |
||||
|
||||
|
||||
@end |
@ -1,24 +0,0 @@
|
||||
// |
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved. |
||||
// |
||||
|
||||
#import "Randomness.h" |
||||
#import <SessionProtocolKit/OWSAsserts.h> |
||||
|
||||
@implementation Randomness |
||||
|
||||
+ (NSData *)generateRandomBytes:(int)numberBytes |
||||
{ |
||||
NSMutableData *_Nullable randomBytes = [NSMutableData dataWithLength:numberBytes]; |
||||
if (!randomBytes) { |
||||
OWSFail(@"Could not allocate buffer for random bytes."); |
||||
} |
||||
int err = 0; |
||||
err = SecRandomCopyBytes(kSecRandomDefault, numberBytes, [randomBytes mutableBytes]); |
||||
if (err != noErr || randomBytes.length != numberBytes) { |
||||
OWSFail(@"Could not generate random bytes."); |
||||
} |
||||
return [randomBytes copy]; |
||||
} |
||||
|
||||
@end |
@ -1,7 +1,7 @@
|
||||
import PromiseKit |
||||
|
||||
/// Delay the execution of the promise constructed in `body` by `delay` seconds. |
||||
internal func withDelay<T>(_ delay: TimeInterval, completionQueue: DispatchQueue, body: @escaping () -> Promise<T>) -> Promise<T> { |
||||
public func withDelay<T>(_ delay: TimeInterval, completionQueue: DispatchQueue, body: @escaping () -> Promise<T>) -> Promise<T> { |
||||
#if DEBUG |
||||
assert(Thread.current.isMainThread) // Timers don't do well on background queues |
||||
#endif |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,34 @@
|
||||
// |
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved. |
||||
// |
||||
|
||||
import Foundation |
||||
import PromiseKit |
||||
|
||||
// TODO define actual type, and validate length |
||||
public typealias IdentityKey = Data |
||||
|
||||
/// based on libsignal-service-java's AccountManager class |
||||
@objc(SSKAccountServiceClient) |
||||
public class AccountServiceClient: NSObject { |
||||
|
||||
static var shared = AccountServiceClient() |
||||
|
||||
private let serviceClient: SignalServiceClient |
||||
|
||||
override init() { |
||||
self.serviceClient = SignalServiceRestClient() |
||||
} |
||||
|
||||
public func getPreKeysCount() -> Promise<Int> { |
||||
return serviceClient.getAvailablePreKeys() |
||||
} |
||||
|
||||
public func setPreKeys(identityKey: IdentityKey, signedPreKeyRecord: SignedPreKeyRecord, preKeyRecords: [PreKeyRecord]) -> Promise<Void> { |
||||
return serviceClient.registerPreKeys(identityKey: identityKey, signedPreKeyRecord: signedPreKeyRecord, preKeyRecords: preKeyRecords) |
||||
} |
||||
|
||||
public func setSignedPreKey(_ signedPreKey: SignedPreKeyRecord) -> Promise<Void> { |
||||
return serviceClient.setCurrentSignedPreKey(signedPreKey) |
||||
} |
||||
} |
@ -0,0 +1,10 @@
|
||||
import PromiseKit |
||||
|
||||
public extension AnyPromise { |
||||
|
||||
public static func from<T : Any>(_ promise: Promise<T>) -> AnyPromise { |
||||
let result = AnyPromise(promise) |
||||
result.retainUntilComplete() |
||||
return result |
||||
} |
||||
} |
@ -0,0 +1,130 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h> |
||||
|
||||
NS_ASSUME_NONNULL_BEGIN |
||||
|
||||
static inline BOOL OWSIsDebugBuild() |
||||
{ |
||||
#ifdef DEBUG |
||||
return YES; |
||||
#else |
||||
return NO; |
||||
#endif |
||||
} |
||||
|
||||
// These are fired whenever the corresponding "main app" or "app extension"
|
||||
// notification is fired.
|
||||
//
|
||||
// 1. This saves you the work of observing both.
|
||||
// 2. This allows us to ensure that any critical work (e.g. re-opening
|
||||
// databases) has been done before app re-enters foreground, etc.
|
||||
extern NSString *const OWSApplicationDidEnterBackgroundNotification; |
||||
extern NSString *const OWSApplicationWillEnterForegroundNotification; |
||||
extern NSString *const OWSApplicationWillResignActiveNotification; |
||||
extern NSString *const OWSApplicationDidBecomeActiveNotification; |
||||
|
||||
typedef void (^BackgroundTaskExpirationHandler)(void); |
||||
typedef void (^AppActiveBlock)(void); |
||||
|
||||
NSString *NSStringForUIApplicationState(UIApplicationState value); |
||||
|
||||
@class OWSAES256Key; |
||||
|
||||
@protocol SSKKeychainStorage; |
||||
|
||||
@protocol AppContext <NSObject> |
||||
|
||||
@property (nonatomic, readonly) BOOL isMainApp; |
||||
@property (nonatomic, readonly) BOOL isMainAppAndActive; |
||||
/// Whether the app was woken up by a silent push notification. This is important for
|
||||
/// determining whether attachments should be downloaded or not.
|
||||
@property (nonatomic) BOOL wasWokenUpByPushNotification; |
||||
|
||||
// Whether the user is using a right-to-left language like Arabic.
|
||||
@property (nonatomic, readonly) BOOL isRTL; |
||||
|
||||
@property (nonatomic, readonly) BOOL isRunningTests; |
||||
|
||||
@property (atomic, nullable) UIWindow *mainWindow; |
||||
|
||||
// Unlike UIApplication.applicationState, this is thread-safe.
|
||||
// It contains the "last known" application state.
|
||||
//
|
||||
// Because it is updated in response to "will/did-style" events, it is
|
||||
// conservative and skews toward less-active and not-foreground:
|
||||
//
|
||||
// * It doesn't report "is active" until the app is active
|
||||
// and reports "inactive" as soon as it _will become_ inactive.
|
||||
// * It doesn't report "is foreground (but inactive)" until the app is
|
||||
// foreground & inactive and reports "background" as soon as it _will
|
||||
// enter_ background.
|
||||
//
|
||||
// This conservatism is useful, since we want to err on the side of
|
||||
// caution when, for example, we do work that should only be done
|
||||
// when the app is foreground and active.
|
||||
@property (atomic, readonly) UIApplicationState reportedApplicationState; |
||||
|
||||
// A convenience accessor for reportedApplicationState.
|
||||
//
|
||||
// This method is thread-safe.
|
||||
- (BOOL)isInBackground; |
||||
|
||||
// A convenience accessor for reportedApplicationState.
|
||||
//
|
||||
// This method is thread-safe.
|
||||
- (BOOL)isAppForegroundAndActive; |
||||
|
||||
// Should start a background task if isMainApp is YES.
|
||||
// Should just return UIBackgroundTaskInvalid if isMainApp is NO.
|
||||
- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler: |
||||
(BackgroundTaskExpirationHandler)expirationHandler; |
||||
|
||||
// Should be a NOOP if isMainApp is NO.
|
||||
- (void)endBackgroundTask:(UIBackgroundTaskIdentifier)backgroundTaskIdentifier; |
||||
|
||||
// Should be a NOOP if isMainApp is NO.
|
||||
- (void)ensureSleepBlocking:(BOOL)shouldBeBlocking blockingObjects:(NSArray<id> *)blockingObjects; |
||||
|
||||
// Should only be called if isMainApp is YES.
|
||||
- (void)setMainAppBadgeNumber:(NSInteger)value; |
||||
|
||||
- (void)setStatusBarHidden:(BOOL)isHidden animated:(BOOL)isAnimated; |
||||
|
||||
@property (nonatomic, readonly) CGFloat statusBarHeight; |
||||
|
||||
// Returns the VC that should be used to present alerts, modals, etc.
|
||||
- (nullable UIViewController *)frontmostViewController; |
||||
|
||||
// Returns nil if isMainApp is NO
|
||||
@property (nullable, nonatomic, readonly) UIAlertAction *openSystemSettingsAction; |
||||
|
||||
// Should be a NOOP if isMainApp is NO.
|
||||
- (void)setNetworkActivityIndicatorVisible:(BOOL)value; |
||||
|
||||
- (void)runNowOrWhenMainAppIsActive:(AppActiveBlock)block; |
||||
|
||||
@property (atomic, readonly) NSDate *appLaunchTime; |
||||
|
||||
- (id<SSKKeychainStorage>)keychainStorage; |
||||
|
||||
- (NSString *)appDocumentDirectoryPath; |
||||
|
||||
- (NSString *)appSharedDataDirectoryPath; |
||||
|
||||
- (NSUserDefaults *)appUserDefaults; |
||||
|
||||
@end |
||||
|
||||
id<AppContext> CurrentAppContext(void); |
||||
void SetCurrentAppContext(id<AppContext> appContext); |
||||
|
||||
void ExitShareExtension(void); |
||||
|
||||
#ifdef DEBUG |
||||
void ClearCurrentAppContextForTests(void); |
||||
#endif |
||||
|
||||
NS_ASSUME_NONNULL_END |
@ -0,0 +1,61 @@
|
||||
// |
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved. |
||||
// |
||||
|
||||
#import "AppContext.h" |
||||
#import <SessionProtocolKit/SessionProtocolKit.h> |
||||
|
||||
NS_ASSUME_NONNULL_BEGIN |
||||
|
||||
NSString *const OWSApplicationDidEnterBackgroundNotification = @"OWSApplicationDidEnterBackgroundNotification"; |
||||
NSString *const OWSApplicationWillEnterForegroundNotification = @"OWSApplicationWillEnterForegroundNotification"; |
||||
NSString *const OWSApplicationWillResignActiveNotification = @"OWSApplicationWillResignActiveNotification"; |
||||
NSString *const OWSApplicationDidBecomeActiveNotification = @"OWSApplicationDidBecomeActiveNotification"; |
||||
|
||||
NSString *NSStringForUIApplicationState(UIApplicationState value) |
||||
{ |
||||
switch (value) { |
||||
case UIApplicationStateActive: |
||||
return @"UIApplicationStateActive"; |
||||
case UIApplicationStateInactive: |
||||
return @"UIApplicationStateInactive"; |
||||
case UIApplicationStateBackground: |
||||
return @"UIApplicationStateBackground"; |
||||
} |
||||
} |
||||
|
||||
static id<AppContext> currentAppContext = nil; |
||||
|
||||
id<AppContext> CurrentAppContext(void) |
||||
{ |
||||
OWSCAssertDebug(currentAppContext); |
||||
|
||||
return currentAppContext; |
||||
} |
||||
|
||||
void SetCurrentAppContext(id<AppContext> appContext) |
||||
{ |
||||
// The main app context should only be set once. |
||||
// |
||||
// App extensions may be opened multiple times in the same process, |
||||
// so statics will persist. |
||||
OWSCAssertDebug(!currentAppContext || !currentAppContext.isMainApp); |
||||
|
||||
currentAppContext = appContext; |
||||
} |
||||
|
||||
#ifdef DEBUG |
||||
void ClearCurrentAppContextForTests() |
||||
{ |
||||
currentAppContext = nil; |
||||
} |
||||
#endif |
||||
|
||||
void ExitShareExtension(void) |
||||
{ |
||||
OWSLogInfo(@"ExitShareExtension"); |
||||
[DDLog flushLog]; |
||||
exit(0); |
||||
} |
||||
|
||||
NS_ASSUME_NONNULL_END |
@ -0,0 +1,38 @@
|
||||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h> |
||||
|
||||
NS_ASSUME_NONNULL_BEGIN |
||||
|
||||
typedef void (^AppReadyBlock)(void); |
||||
|
||||
@interface AppReadiness : NSObject |
||||
|
||||
- (instancetype)init NS_UNAVAILABLE; |
||||
|
||||
// This method can be called on any thread.
|
||||
+ (BOOL)isAppReady; |
||||
|
||||
// This method should only be called on the main thread.
|
||||
+ (void)setAppIsReady; |
||||
|
||||
// If the app is ready, the block is called immediately;
|
||||
// otherwise it is called when the app becomes ready.
|
||||
//
|
||||
// This method should only be called on the main thread.
|
||||
// The block will always be called on the main thread.
|
||||
//
|
||||
// * The "will become ready" blocks are called before the "did become ready" blocks.
|
||||
// * The "will become ready" blocks should be used for internal setup of components
|
||||
// so that they are ready to interact with other components of the system.
|
||||
// * The "did become ready" blocks should be used for any work that should be done
|
||||
// on app launch, especially work that uses other components.
|
||||
// * We should usually use "did become ready" blocks since they are safer.
|
||||
+ (void)runNowOrWhenAppWillBecomeReady:(AppReadyBlock)block NS_SWIFT_NAME(runNowOrWhenAppWillBecomeReady(_:)); |
||||
+ (void)runNowOrWhenAppDidBecomeReady:(AppReadyBlock)block NS_SWIFT_NAME(runNowOrWhenAppDidBecomeReady(_:)); |
||||
|
||||
@end |
||||
|
||||
NS_ASSUME_NONNULL_END |
@ -0,0 +1,144 @@
|
||||
// |
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved. |
||||
// |
||||
|
||||
#import "AppReadiness.h" |
||||
#import <SessionProtocolKit/SessionProtocolKit.h> |
||||
#import "AppContext.h" |
||||
#import "SSKAsserts.h" |
||||
|
||||
NS_ASSUME_NONNULL_BEGIN |
||||
|
||||
@interface AppReadiness () |
||||
|
||||
@property (atomic) BOOL isAppReady; |
||||
|
||||
@property (nonatomic) NSMutableArray<AppReadyBlock> *appWillBecomeReadyBlocks; |
||||
@property (nonatomic) NSMutableArray<AppReadyBlock> *appDidBecomeReadyBlocks; |
||||
|
||||
@end |
||||
|
||||
#pragma mark - |
||||
|
||||
@implementation AppReadiness |
||||
|
||||
+ (instancetype)sharedManager |
||||
{ |
||||
static AppReadiness *sharedMyManager = nil; |
||||
static dispatch_once_t onceToken; |
||||
dispatch_once(&onceToken, ^{ |
||||
sharedMyManager = [[self alloc] initDefault]; |
||||
}); |
||||
return sharedMyManager; |
||||
} |
||||
|
||||
- (instancetype)initDefault |
||||
{ |
||||
self = [super init]; |
||||
|
||||
if (!self) { |
||||
return self; |
||||
} |
||||
|
||||
OWSSingletonAssert(); |
||||
|
||||
self.appWillBecomeReadyBlocks = [NSMutableArray new]; |
||||
self.appDidBecomeReadyBlocks = [NSMutableArray new]; |
||||
|
||||
return self; |
||||
} |
||||
|
||||
+ (BOOL)isAppReady |
||||
{ |
||||
return [self.sharedManager isAppReady]; |
||||
} |
||||
|
||||
+ (void)runNowOrWhenAppWillBecomeReady:(AppReadyBlock)block |
||||
{ |
||||
DispatchMainThreadSafe(^{ |
||||
[self.sharedManager runNowOrWhenAppWillBecomeReady:block]; |
||||
}); |
||||
} |
||||
|
||||
- (void)runNowOrWhenAppWillBecomeReady:(AppReadyBlock)block |
||||
{ |
||||
OWSAssertIsOnMainThread(); |
||||
OWSAssertDebug(block); |
||||
|
||||
if (CurrentAppContext().isRunningTests) { |
||||
// We don't need to do any "on app ready" work in the tests. |
||||
return; |
||||
} |
||||
|
||||
if (self.isAppReady) { |
||||
block(); |
||||
return; |
||||
} |
||||
|
||||
[self.appWillBecomeReadyBlocks addObject:block]; |
||||
} |
||||
|
||||
+ (void)runNowOrWhenAppDidBecomeReady:(AppReadyBlock)block |
||||
{ |
||||
DispatchMainThreadSafe(^{ |
||||
[self.sharedManager runNowOrWhenAppDidBecomeReady:block]; |
||||
}); |
||||
} |
||||
|
||||
- (void)runNowOrWhenAppDidBecomeReady:(AppReadyBlock)block |
||||
{ |
||||
OWSAssertIsOnMainThread(); |
||||
OWSAssertDebug(block); |
||||
|
||||
if (CurrentAppContext().isRunningTests) { |
||||
// We don't need to do any "on app ready" work in the tests. |
||||
return; |
||||
} |
||||
|
||||
if (self.isAppReady) { |
||||
block(); |
||||
return; |
||||
} |
||||
|
||||
[self.appDidBecomeReadyBlocks addObject:block]; |
||||
} |
||||
|
||||
+ (void)setAppIsReady |
||||
{ |
||||
[self.sharedManager setAppIsReady]; |
||||
} |
||||
|
||||
- (void)setAppIsReady |
||||
{ |
||||
OWSAssertIsOnMainThread(); |
||||
OWSAssertDebug(!self.isAppReady); |
||||
|
||||
OWSLogInfo(@""); |
||||
|
||||
self.isAppReady = YES; |
||||
|
||||
[self runAppReadyBlocks]; |
||||
} |
||||
|
||||
- (void)runAppReadyBlocks |
||||
{ |
||||
OWSAssertIsOnMainThread(); |
||||
OWSAssertDebug(self.isAppReady); |
||||
|
||||
NSArray<AppReadyBlock> *appWillBecomeReadyBlocks = [self.appWillBecomeReadyBlocks copy]; |
||||
[self.appWillBecomeReadyBlocks removeAllObjects]; |
||||
NSArray<AppReadyBlock> *appDidBecomeReadyBlocks = [self.appDidBecomeReadyBlocks copy]; |
||||
[self.appDidBecomeReadyBlocks removeAllObjects]; |
||||
|
||||
// We invoke the _will become_ blocks before the _did become_ blocks. |
||||
for (AppReadyBlock block in appWillBecomeReadyBlocks) { |
||||
block(); |
||||
} |
||||
for (AppReadyBlock block in appDidBecomeReadyBlocks) { |
||||
block(); |
||||
} |
||||
} |
||||
|
||||
@end |
||||
|
||||
NS_ASSUME_NONNULL_END |
@ -0,0 +1,32 @@
|
||||
//
|
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h> |
||||
|
||||
NS_ASSUME_NONNULL_BEGIN |
||||
|
||||
@interface AppVersion : NSObject |
||||
|
||||
// The properties are updated immediately after launch.
|
||||
@property (atomic, readonly) NSString *firstAppVersion; |
||||
@property (atomic, nullable, readonly) NSString *lastAppVersion; |
||||
@property (atomic, readonly) NSString *currentAppVersion; |
||||
|
||||
// There properties aren't updated until appLaunchDidComplete is called.
|
||||
@property (atomic, nullable, readonly) NSString *lastCompletedLaunchAppVersion; |
||||
@property (atomic, nullable, readonly) NSString *lastCompletedLaunchMainAppVersion; |
||||
@property (atomic, nullable, readonly) NSString *lastCompletedLaunchSAEAppVersion; |
||||
|
||||
- (instancetype)init NS_UNAVAILABLE; |
||||
|
||||
+ (instancetype)sharedInstance; |
||||
|
||||
- (void)mainAppLaunchDidComplete; |
||||
- (void)saeLaunchDidComplete; |
||||
|
||||
- (BOOL)isFirstLaunch; |
||||
|
||||
@end |
||||
|
||||
NS_ASSUME_NONNULL_END |
@ -0,0 +1,133 @@
|
||||
// |
||||
// Copyright (c) 2019 Open Whisper Systems. All rights reserved. |
||||
// |
||||
|
||||
#import "AppVersion.h" |
||||
#import "NSUserDefaults+OWS.h" |
||||
#import <SessionProtocolKit/SessionProtocolKit.h> |
||||
|
||||
NS_ASSUME_NONNULL_BEGIN |
||||
|
||||
NSString *const kNSUserDefaults_FirstAppVersion = @"kNSUserDefaults_FirstAppVersion"; |
||||
NSString *const kNSUserDefaults_LastAppVersion = @"kNSUserDefaults_LastVersion"; |
||||
NSString *const kNSUserDefaults_LastCompletedLaunchAppVersion = @"kNSUserDefaults_LastCompletedLaunchAppVersion"; |
||||
NSString *const kNSUserDefaults_LastCompletedLaunchAppVersion_MainApp |
||||
= @"kNSUserDefaults_LastCompletedLaunchAppVersion_MainApp"; |
||||
NSString *const kNSUserDefaults_LastCompletedLaunchAppVersion_SAE |
||||
= @"kNSUserDefaults_LastCompletedLaunchAppVersion_SAE"; |
||||
|
||||
@interface AppVersion () |
||||
|
||||
@property (atomic) NSString *firstAppVersion; |
||||
@property (atomic, nullable) NSString *lastAppVersion; |
||||
@property (atomic) NSString *currentAppVersion; |
||||
|
||||
@property (atomic, nullable) NSString *lastCompletedLaunchAppVersion; |
||||
@property (atomic, nullable) NSString *lastCompletedLaunchMainAppVersion; |
||||
@property (atomic, nullable) NSString *lastCompletedLaunchSAEAppVersion; |
||||
|
||||
@end |
||||
|
||||
#pragma mark - |
||||
|
||||
@implementation AppVersion |
||||
|
||||
+ (instancetype)sharedInstance |
||||
{ |
||||
static AppVersion *instance = nil; |
||||
static dispatch_once_t onceToken; |
||||
dispatch_once(&onceToken, ^{ |
||||
instance = [AppVersion new]; |
||||
[instance configure]; |
||||
}); |
||||
return instance; |
||||
} |
||||
|
||||
- (void)configure { |
||||
OWSAssertIsOnMainThread(); |
||||
|
||||
self.currentAppVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; |
||||
|
||||
// The version of the app when it was first launched. |
||||
// nil if the app has never been launched before. |
||||
self.firstAppVersion = [[NSUserDefaults appUserDefaults] objectForKey:kNSUserDefaults_FirstAppVersion]; |
||||
// The version of the app the last time it was launched. |
||||
// nil if the app has never been launched before. |
||||
self.lastAppVersion = [[NSUserDefaults appUserDefaults] objectForKey:kNSUserDefaults_LastAppVersion]; |
||||
self.lastCompletedLaunchAppVersion = |
||||
[[NSUserDefaults appUserDefaults] objectForKey:kNSUserDefaults_LastCompletedLaunchAppVersion]; |
||||
self.lastCompletedLaunchMainAppVersion = |
||||
[[NSUserDefaults appUserDefaults] objectForKey:kNSUserDefaults_LastCompletedLaunchAppVersion_MainApp]; |
||||
self.lastCompletedLaunchSAEAppVersion = |
||||
[[NSUserDefaults appUserDefaults] objectForKey:kNSUserDefaults_LastCompletedLaunchAppVersion_SAE]; |
||||
|
||||
// Ensure the value for the "first launched version". |
||||
if (!self.firstAppVersion) { |
||||
self.firstAppVersion = self.currentAppVersion; |
||||
[[NSUserDefaults appUserDefaults] setObject:self.currentAppVersion forKey:kNSUserDefaults_FirstAppVersion]; |
||||
} |
||||
|
||||
// Update the value for the "most recently launched version". |
||||
[[NSUserDefaults appUserDefaults] setObject:self.currentAppVersion forKey:kNSUserDefaults_LastAppVersion]; |
||||
[[NSUserDefaults appUserDefaults] synchronize]; |
||||
|
||||
// The long version string looks like an IPv4 address. |
||||
// To prevent the log scrubber from scrubbing it, |
||||
// we replace . with _. |
||||
NSString *longVersionString = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"] |
||||
stringByReplacingOccurrencesOfString:@"." |
||||
withString:@"_"]; |
||||
|
||||
OWSLogInfo(@"firstAppVersion: %@", self.firstAppVersion); |
||||
OWSLogInfo(@"lastAppVersion: %@", self.lastAppVersion); |
||||
OWSLogInfo(@"currentAppVersion: %@ (%@)", self.currentAppVersion, longVersionString); |
||||
|
||||
OWSLogInfo(@"lastCompletedLaunchAppVersion: %@", self.lastCompletedLaunchAppVersion); |
||||
OWSLogInfo(@"lastCompletedLaunchMainAppVersion: %@", self.lastCompletedLaunchMainAppVersion); |
||||
OWSLogInfo(@"lastCompletedLaunchSAEAppVersion: %@", self.lastCompletedLaunchSAEAppVersion); |
||||
} |
||||
|
||||
- (void)appLaunchDidComplete |
||||
{ |
||||
OWSAssertIsOnMainThread(); |
||||
|
||||
OWSLogInfo(@"appLaunchDidComplete"); |
||||
|
||||
self.lastCompletedLaunchAppVersion = self.currentAppVersion; |
||||
|
||||
// Update the value for the "most recently launch-completed version". |
||||
[[NSUserDefaults appUserDefaults] setObject:self.currentAppVersion |
||||
forKey:kNSUserDefaults_LastCompletedLaunchAppVersion]; |
||||
[[NSUserDefaults appUserDefaults] synchronize]; |
||||
} |
||||
|
||||
- (void)mainAppLaunchDidComplete |
||||
{ |
||||
OWSAssertIsOnMainThread(); |
||||
|
||||
self.lastCompletedLaunchMainAppVersion = self.currentAppVersion; |
||||
[[NSUserDefaults appUserDefaults] setObject:self.currentAppVersion |
||||
forKey:kNSUserDefaults_LastCompletedLaunchAppVersion_MainApp]; |
||||
|
||||
[self appLaunchDidComplete]; |
||||
} |
||||
|
||||
- (void)saeLaunchDidComplete |
||||
{ |
||||
OWSAssertIsOnMainThread(); |
||||
|
||||
self.lastCompletedLaunchSAEAppVersion = self.currentAppVersion; |
||||
[[NSUserDefaults appUserDefaults] setObject:self.currentAppVersion |
||||
forKey:kNSUserDefaults_LastCompletedLaunchAppVersion_SAE]; |
||||
|
||||
[self appLaunchDidComplete]; |
||||
} |
||||
|
||||
- (BOOL)isFirstLaunch |
||||
{ |
||||
return self.firstAppVersion != nil; |
||||
} |
||||
|
||||
@end |
||||
|
||||
NS_ASSUME_NONNULL_END |
@ -0,0 +1,7 @@
|
||||
|
||||
public extension Array where Element : CustomStringConvertible { |
||||
|
||||
public var prettifiedDescription: String { |
||||
return "[ " + map { $0.description }.joined(separator: ", ") + " ]" |
||||
} |
||||
} |
@ -0,0 +1,21 @@
|
||||
|
||||
public enum BuildConfiguration : String, CustomStringConvertible { |
||||
case debug, production |
||||
|
||||
public static let current: BuildConfiguration = { |
||||
#if DEBUG |
||||
return .debug |
||||
#else |
||||
return .production |
||||
#endif |
||||
}() |
||||
|
||||
public var description: String { return rawValue } |
||||
} |
||||
|
||||
@objc public final class LKBuildConfiguration : NSObject { |
||||
|
||||
override private init() { } |
||||
|
||||
@objc public static var current: String { return BuildConfiguration.current.description } |
||||
} |
@ -0,0 +1,40 @@
|
||||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h> |
||||
|
||||
NS_ASSUME_NONNULL_BEGIN |
||||
|
||||
@interface ByteParser : NSObject |
||||
|
||||
@property (nonatomic, readonly) BOOL hasError; |
||||
|
||||
- (instancetype)init NS_UNAVAILABLE; |
||||
|
||||
- (instancetype)initWithData:(NSData *)data littleEndian:(BOOL)littleEndian; |
||||
|
||||
#pragma mark - Short |
||||
|
||||
- (uint16_t)shortAtIndex:(NSUInteger)index; |
||||
- (uint16_t)nextShort; |
||||
|
||||
#pragma mark - Int |
||||
|
||||
- (uint32_t)intAtIndex:(NSUInteger)index; |
||||
- (uint32_t)nextInt; |
||||
|
||||
#pragma mark - Long |
||||
|
||||
- (uint64_t)longAtIndex:(NSUInteger)index; |
||||
- (uint64_t)nextLong; |
||||
|
||||
#pragma mark - |
||||
|
||||
- (BOOL)readZero:(NSUInteger)length; |
||||
|
||||
- (nullable NSData *)readBytes:(NSUInteger)length; |
||||
|
||||
@end |
||||
|
||||
NS_ASSUME_NONNULL_END |
@ -0,0 +1,143 @@
|
||||
// |
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved. |
||||
// |
||||
|
||||
#import "ByteParser.h" |
||||
#import <SessionProtocolKit/SessionProtocolKit.h> |
||||
|
||||
NS_ASSUME_NONNULL_BEGIN |
||||
|
||||
@interface ByteParser () |
||||
|
||||
@property (nonatomic, readonly) BOOL littleEndian; |
||||
@property (nonatomic, readonly) NSData *data; |
||||
@property (nonatomic) NSUInteger cursor; |
||||
@property (nonatomic) BOOL hasError; |
||||
|
||||
@end |
||||
|
||||
#pragma mark - |
||||
|
||||
@implementation ByteParser |
||||
|
||||
- (instancetype)initWithData:(NSData *)data littleEndian:(BOOL)littleEndian |
||||
{ |
||||
if (self = [super init]) { |
||||
_littleEndian = littleEndian; |
||||
_data = data; |
||||
} |
||||
|
||||
return self; |
||||
} |
||||
|
||||
#pragma mark - Short |
||||
|
||||
- (uint16_t)shortAtIndex:(NSUInteger)index |
||||
{ |
||||
uint16_t value; |
||||
const size_t valueSize = sizeof(value); |
||||
OWSAssertDebug(valueSize == 2); |
||||
if (index + valueSize > self.data.length) { |
||||
self.hasError = YES; |
||||
return 0; |
||||
} |
||||
[self.data getBytes:&value range:NSMakeRange(index, valueSize)]; |
||||
if (self.littleEndian) { |
||||
return CFSwapInt16LittleToHost(value); |
||||
} else { |
||||
return CFSwapInt16BigToHost(value); |
||||
} |
||||
} |
||||
|
||||
- (uint16_t)nextShort |
||||
{ |
||||
uint16_t value = [self shortAtIndex:self.cursor]; |
||||
self.cursor += sizeof(value); |
||||
return value; |
||||
} |
||||
|
||||
#pragma mark - Int |
||||
|
||||
- (uint32_t)intAtIndex:(NSUInteger)index |
||||
{ |
||||
uint32_t value; |
||||
const size_t valueSize = sizeof(value); |
||||
OWSAssertDebug(valueSize == 4); |
||||
if (index + valueSize > self.data.length) { |
||||
self.hasError = YES; |
||||
return 0; |
||||
} |
||||
[self.data getBytes:&value range:NSMakeRange(index, valueSize)]; |
||||
if (self.littleEndian) { |
||||
return CFSwapInt32LittleToHost(value); |
||||
} else { |
||||
return CFSwapInt32BigToHost(value); |
||||
} |
||||
} |
||||
|
||||
- (uint32_t)nextInt |
||||
{ |
||||
uint32_t value = [self intAtIndex:self.cursor]; |
||||
self.cursor += sizeof(value); |
||||
return value; |
||||
} |
||||
|
||||
#pragma mark - Long |
||||
|
||||
- (uint64_t)longAtIndex:(NSUInteger)index |
||||
{ |
||||
uint64_t value; |
||||
const size_t valueSize = sizeof(value); |
||||
OWSAssertDebug(valueSize == 8); |
||||
if (index + valueSize > self.data.length) { |
||||
self.hasError = YES; |
||||
return 0; |
||||
} |
||||
[self.data getBytes:&value range:NSMakeRange(index, valueSize)]; |
||||
if (self.littleEndian) { |
||||
return CFSwapInt64LittleToHost(value); |
||||
} else { |
||||
return CFSwapInt64BigToHost(value); |
||||
} |
||||
} |
||||
|
||||
- (uint64_t)nextLong |
||||
{ |
||||
uint64_t value = [self longAtIndex:self.cursor]; |
||||
self.cursor += sizeof(value); |
||||
return value; |
||||
} |
||||
|
||||
#pragma mark - |
||||
|
||||
- (BOOL)readZero:(NSUInteger)length |
||||
{ |
||||
NSData *_Nullable subdata = [self readBytes:length]; |
||||
if (!subdata) { |
||||
return NO; |
||||
} |
||||
uint8_t bytes[length]; |
||||
[subdata getBytes:bytes range:NSMakeRange(0, length)]; |
||||
for (int i = 0; i < length; i++) { |
||||
if (bytes[i] != 0) { |
||||
return NO; |
||||
} |
||||
} |
||||
return YES; |
||||
} |
||||
|
||||
- (nullable NSData *)readBytes:(NSUInteger)length |
||||
{ |
||||
NSUInteger index = self.cursor; |
||||
if (index + length > self.data.length) { |
||||
self.hasError = YES; |
||||
return nil; |
||||
} |
||||
NSData *_Nullable subdata = [self.data subdataWithRange:NSMakeRange(index, length)]; |
||||
self.cursor += length; |
||||
return subdata; |
||||
} |
||||
|
||||
@end |
||||
|
||||
NS_ASSUME_NONNULL_END |
@ -0,0 +1,34 @@
|
||||
//
|
||||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h> |
||||
|
||||
NS_ASSUME_NONNULL_BEGIN |
||||
|
||||
@interface CDSQuote : NSObject |
||||
|
||||
@property (nonatomic, readonly) uint16_t version; |
||||
@property (nonatomic, readonly) uint16_t signType; |
||||
@property (nonatomic, readonly) BOOL isSigLinkable; |
||||
@property (nonatomic, readonly) uint32_t gid; |
||||
@property (nonatomic, readonly) uint16_t qeSvn; |
||||
@property (nonatomic, readonly) uint16_t pceSvn; |
||||
@property (nonatomic, readonly) NSData *basename; |
||||
@property (nonatomic, readonly) NSData *cpuSvn; |
||||
@property (nonatomic, readonly) uint64_t flags; |
||||
@property (nonatomic, readonly) uint64_t xfrm; |
||||
@property (nonatomic, readonly) NSData *mrenclave; |
||||
@property (nonatomic, readonly) NSData *mrsigner; |
||||
@property (nonatomic, readonly) uint16_t isvProdId; |
||||
@property (nonatomic, readonly) uint16_t isvSvn; |
||||
@property (nonatomic, readonly) NSData *reportData; |
||||
@property (nonatomic, readonly) NSData *signature; |
||||
< |