From 950ce888e24b7b6bf0daa8f980e259da27e81080 Mon Sep 17 00:00:00 2001 From: Maarten Billemont Date: Thu, 3 May 2012 16:49:15 +0200 Subject: [PATCH] Crashlytics, Localytics, TestFlight + password change warnings. [ADDED] Crashlytics, Localytics. [IMPROVED] Async TestFlight takeOff. [REMOVED] TestFlight token hidden. [FIXED] Warnings, mostly to do with sign conversions. [ADDED] Warning messages whenever site's password changes, allowing the user to cancel the operation. [ADDED] Make password counter resettable by holding down on the counter increment button. --- Crashlytics/Crashlytics.framework/Crashlytics | 1 + Crashlytics/Crashlytics.framework/Headers | 1 + Crashlytics/Crashlytics.framework/Resources | 1 + .../Versions/A/Crashlytics | Bin 0 -> 622986 bytes .../Versions/A/Headers/Crashlytics.h | 89 ++ .../Versions/A/Resources/Info.plist | 54 + .../Versions/A/Resources/Runner | 1 + .../A/Resources/en.lproj/InfoPlist.strings | Bin 0 -> 42 bytes .../Versions/A/Resources/runner.rb | 15 + .../Crashlytics.framework/Versions/Current | 1 + Crashlytics/Crashlytics.framework/run | Bin 0 -> 44596 bytes Crashlytics/Crashlytics.plist | 8 + External/Pearl | 2 +- Localytics/Localytics.plist | 10 + Localytics/LocalyticsDatabase.h | 57 + Localytics/LocalyticsDatabase.m | 743 +++++++++++ Localytics/LocalyticsSession.h | 216 ++++ Localytics/LocalyticsSession.m | 1148 +++++++++++++++++ Localytics/LocalyticsUploader.h | 42 + Localytics/LocalyticsUploader.m | 236 ++++ Localytics/UploaderThread.h | 48 + Localytics/UploaderThread.m | 260 ++++ Localytics/WebserviceConstants.h | 111 ++ MasterPassword-iOS.xcodeproj/project.pbxproj | 520 +++++--- .../MasterPassword (Development).xcscheme | 4 +- MasterPassword/MPAppDelegate_Key.m | 10 - MasterPassword/MPElementGeneratedEntity.h | 2 +- MasterPassword/MPElementGeneratedEntity.m | 2 +- MasterPassword/MPTypes.h | 5 +- MasterPassword/MPTypes.m | 2 +- MasterPassword/iOS/MPAppDelegate.m | 224 +++- MasterPassword/iOS/MPMainViewController.h | 1 + MasterPassword/iOS/MPMainViewController.m | 142 +- MasterPassword/iOS/MPSearchDelegate.m | 26 +- MasterPassword/iOS/MPUnlockViewController.m | 4 +- .../iOS/MainStoryboard_iPhone.storyboard | 15 +- MasterPassword/iOS/MasterPassword-Prefix.pch | 4 +- Pearl/Pearl-Prefix.pch | 2 +- .../TestFlightSDK => TestFlight}/README.txt | 58 +- .../TestFlightSDK => TestFlight}/TestFlight.h | 17 +- TestFlight/TestFlight.plist | 8 + .../libTestFlight.a | Bin 2829532 -> 2889820 bytes .../release_notes.txt | 7 + 43 files changed, 3751 insertions(+), 346 deletions(-) create mode 120000 Crashlytics/Crashlytics.framework/Crashlytics create mode 120000 Crashlytics/Crashlytics.framework/Headers create mode 120000 Crashlytics/Crashlytics.framework/Resources create mode 100644 Crashlytics/Crashlytics.framework/Versions/A/Crashlytics create mode 100644 Crashlytics/Crashlytics.framework/Versions/A/Headers/Crashlytics.h create mode 100644 Crashlytics/Crashlytics.framework/Versions/A/Resources/Info.plist create mode 120000 Crashlytics/Crashlytics.framework/Versions/A/Resources/Runner create mode 100644 Crashlytics/Crashlytics.framework/Versions/A/Resources/en.lproj/InfoPlist.strings create mode 100644 Crashlytics/Crashlytics.framework/Versions/A/Resources/runner.rb create mode 120000 Crashlytics/Crashlytics.framework/Versions/Current create mode 100755 Crashlytics/Crashlytics.framework/run create mode 100644 Crashlytics/Crashlytics.plist create mode 100644 Localytics/Localytics.plist create mode 100644 Localytics/LocalyticsDatabase.h create mode 100644 Localytics/LocalyticsDatabase.m create mode 100644 Localytics/LocalyticsSession.h create mode 100644 Localytics/LocalyticsSession.m create mode 100644 Localytics/LocalyticsUploader.h create mode 100644 Localytics/LocalyticsUploader.m create mode 100644 Localytics/UploaderThread.h create mode 100644 Localytics/UploaderThread.m create mode 100644 Localytics/WebserviceConstants.h rename {External/TestFlightSDK => TestFlight}/README.txt (86%) rename {External/TestFlightSDK => TestFlight}/TestFlight.h (78%) create mode 100644 TestFlight/TestFlight.plist rename {External/TestFlightSDK => TestFlight}/libTestFlight.a (52%) rename {External/TestFlightSDK => TestFlight}/release_notes.txt (91%) diff --git a/Crashlytics/Crashlytics.framework/Crashlytics b/Crashlytics/Crashlytics.framework/Crashlytics new file mode 120000 index 00000000..7074275f --- /dev/null +++ b/Crashlytics/Crashlytics.framework/Crashlytics @@ -0,0 +1 @@ +Versions/Current/Crashlytics \ No newline at end of file diff --git a/Crashlytics/Crashlytics.framework/Headers b/Crashlytics/Crashlytics.framework/Headers new file mode 120000 index 00000000..a177d2a6 --- /dev/null +++ b/Crashlytics/Crashlytics.framework/Headers @@ -0,0 +1 @@ +Versions/Current/Headers \ No newline at end of file diff --git a/Crashlytics/Crashlytics.framework/Resources b/Crashlytics/Crashlytics.framework/Resources new file mode 120000 index 00000000..953ee36f --- /dev/null +++ b/Crashlytics/Crashlytics.framework/Resources @@ -0,0 +1 @@ +Versions/Current/Resources \ No newline at end of file diff --git a/Crashlytics/Crashlytics.framework/Versions/A/Crashlytics b/Crashlytics/Crashlytics.framework/Versions/A/Crashlytics new file mode 100644 index 0000000000000000000000000000000000000000..b8def399a394c3620d2822bedb011122b14b200f GIT binary patch literal 622986 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 taFX48=ES&O^ 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

R=V|(?E`ag3mv7Tw|$~ZpNBtxp~Qsu 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 z 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�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ⅅzbSMBeq% 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 + +@protocol CrashlyticsDelegate; + +@interface Crashlytics : NSObject { +@private + NSString *_apiKey; + NSString *_dataDirectory; + NSString *_bundleIdentifier; + BOOL _installed; + NSMutableDictionary *_customAttributes; + id _user; + NSInteger _sendButtonIndex; + NSInteger _alwaysSendButtonIndex; + NSObject *_delegate; +} + +@property (nonatomic, readonly, copy) NSString *apiKey; +@property (nonatomic, readonly, copy) NSString *version; +@property (nonatomic, assign) BOOL debugMode; + +@property (nonatomic, assign) NSObject *delegate; + +/** + * + * The recommended way to install Crashlytics into your application is to place a call + * to +startWithAPIKey: in your -application:didFinishLaunchingWithOptions: method. + * + * This delay defaults to 1 second in order to generally give the application time to + * fully finish launching. + * + **/ ++ (Crashlytics *)startWithAPIKey:(NSString *)apiKey; ++ (Crashlytics *)startWithAPIKey:(NSString *)apiKey afterDelay:(NSTimeInterval)delay; + +/** + * + * If you need the functionality provided by the CrashlyticsDelegate protocol, you can use + * these convenience methods to activate the framework and set the delegate in one call. + * + **/ ++ (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(NSObject *)delegate; ++ (Crashlytics *)startWithAPIKey:(NSString *)apiKey delegate:(NSObject *)delegate afterDelay:(NSTimeInterval)delay; + +/** + * + * Access the singleton Crashlytics instance. + * + **/ ++ (Crashlytics *)sharedInstance; + +/** + * + * The easiest way to cause a crash - great for testing! + * + **/ +- (void)crash; + +@end + +/** + * + * The CrashlyticsDelegate protocol provides a mechanism for your application to take + * action on events that occur in the Crashlytics crash reporting system. You can make + * use of these calls by assigning an object to the Crashlytics' delegate property directly, + * or through the convenience startWithAPIKey:delegate:... methods. + * + **/ +@protocol CrashlyticsDelegate +@optional + +/** + * + * Called once a Crashlytics instance has determined that the last execution of the + * application ended in a crash. This is called some time after the crash reporting + * process has begun. If you have specififed a delay in one of the + * startWithAPIKey:... calls, this will take at least that long to be invoked. + * + **/ +- (void)crashlyticsDidDetectCrashDuringPreviousExecution:(Crashlytics *)crashlytics; + +@end diff --git a/Crashlytics/Crashlytics.framework/Versions/A/Resources/Info.plist b/Crashlytics/Crashlytics.framework/Versions/A/Resources/Info.plist new file mode 100644 index 00000000..f144fde6 --- /dev/null +++ b/Crashlytics/Crashlytics.framework/Versions/A/Resources/Info.plist @@ -0,0 +1,54 @@ + + + + + BuildMachineOSBuild + 11C74 + CFBundleDevelopmentRegion + English + CFBundleExecutable + Crashlytics + CFBundleIdentifier + com.crashlytics.ios + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Crashlytics + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.1.3 + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + iPhoneOS + + CFBundleVersion + 0100.01.03 + CrashlyticsAPIKey + 0d10c90776f5ef5acd01ddbeaca9a6cba4814560 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 8H7 + DTPlatformName + iphoneos + DTPlatformVersion + 4.3 + DTSDKBuild + 8H7 + DTSDKName + iphoneos4.3 + DTXcode + 0410 + DTXcodeBuild + 4B110 + MinimumOSVersion + 3.1 + UIDeviceFamily + + 1 + + + diff --git a/Crashlytics/Crashlytics.framework/Versions/A/Resources/Runner b/Crashlytics/Crashlytics.framework/Versions/A/Resources/Runner new file mode 120000 index 00000000..faa4f129 --- /dev/null +++ b/Crashlytics/Crashlytics.framework/Versions/A/Resources/Runner @@ -0,0 +1 @@ +../../../run \ No newline at end of file diff --git a/Crashlytics/Crashlytics.framework/Versions/A/Resources/en.lproj/InfoPlist.strings b/Crashlytics/Crashlytics.framework/Versions/A/Resources/en.lproj/InfoPlist.strings new file mode 100644 index 0000000000000000000000000000000000000000..3967e063f94f2b9de2fdbeb4d90be9963443c793 GIT binary patch literal 42 dcmYc)$jK}&F)+Bm!2kw~j1ZauMnky_oB)p~1JeKi literal 0 HcmV?d00001 diff --git a/Crashlytics/Crashlytics.framework/Versions/A/Resources/runner.rb b/Crashlytics/Crashlytics.framework/Versions/A/Resources/runner.rb new file mode 100644 index 00000000..b6ea201c --- /dev/null +++ b/Crashlytics/Crashlytics.framework/Versions/A/Resources/runner.rb @@ -0,0 +1,15 @@ +#!/usr/bin/ruby + +# +# WARNING: DO NOT MODIFY THIS FILE. +# +# Crashlytics +# Crashlytics Version: 1.0.0.1 +# +# Copyright Crashlytics, Inc. 2012. All rights reserved. +# + +require 'pathname' + +path = Pathname.new(__FILE__).parent +`#{path}/../../../run` \ No newline at end of file diff --git a/Crashlytics/Crashlytics.framework/Versions/Current b/Crashlytics/Crashlytics.framework/Versions/Current new file mode 120000 index 00000000..8c7e5a66 --- /dev/null +++ b/Crashlytics/Crashlytics.framework/Versions/Current @@ -0,0 +1 @@ +A \ No newline at end of file diff --git a/Crashlytics/Crashlytics.framework/run b/Crashlytics/Crashlytics.framework/run new file mode 100755 index 0000000000000000000000000000000000000000..7506e5559b22a8d7d0ab8b60d00a28c71156ba35 GIT binary patch literal 44596 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 Hy!`(FX#8B4 literal 0 HcmV?d00001 diff --git a/Crashlytics/Crashlytics.plist b/Crashlytics/Crashlytics.plist new file mode 100644 index 00000000..efa55526 --- /dev/null +++ b/Crashlytics/Crashlytics.plist @@ -0,0 +1,8 @@ + + + + + API Key + + + diff --git a/External/Pearl b/External/Pearl index 9b1a79dc..32660d8e 160000 --- a/External/Pearl +++ b/External/Pearl @@ -1 +1 @@ -Subproject commit 9b1a79dc981997c2c0c0276bca4aad2eeb9de9cd +Subproject commit 32660d8ebc2701bf8f702c64c1bdc1b9382b1612 diff --git a/Localytics/Localytics.plist b/Localytics/Localytics.plist new file mode 100644 index 00000000..24012ab5 --- /dev/null +++ b/Localytics/Localytics.plist @@ -0,0 +1,10 @@ + + + + + Key.development + e6238ceba8ec92832e77b1b-9ccd60bc-c39b-11e0-06e4-007f58cb3154 + Key.distribution + + + diff --git a/Localytics/LocalyticsDatabase.h b/Localytics/LocalyticsDatabase.h new file mode 100644 index 00000000..9a1e1d58 --- /dev/null +++ b/Localytics/LocalyticsDatabase.h @@ -0,0 +1,57 @@ +// +// LocalyticsDatabase.h +// LocalyticsDemo +// +// Created by jkaufman on 5/26/11. +// Copyright 2011 Localytics. All rights reserved. +// + +#import +#import + +#define MAX_DATABASE_SIZE 500000 // The maximum allowed disk size of the primary database file at open, in bytes +#define VACUUM_THRESHOLD 0.8 // The database is vacuumed after its size exceeds this proportion of the maximum. + +@interface LocalyticsDatabase : NSObject { + sqlite3 *_databaseConnection; +} + ++ (LocalyticsDatabase *)sharedLocalyticsDatabase; + +- (NSUInteger)databaseSize; +- (int)eventCount; +- (NSTimeInterval)createdTimestamp; + +- (BOOL)beginTransaction:(NSString *)name; +- (BOOL)releaseTransaction:(NSString *)name; +- (BOOL)rollbackTransaction:(NSString *)name; + +- (BOOL)incrementLastUploadNumber:(int *)uploadNumber; +- (BOOL)incrementLastSessionNumber:(int *)sessionNumber; + +- (BOOL)addEventWithBlobString:(NSString *)blob; +- (BOOL)addCloseEventWithBlobString:(NSString *)blob; +- (BOOL)addFlowEventWithBlobString:(NSString *)blob; +- (BOOL)removeLastCloseAndFlowEvents; + +- (BOOL)addHeaderWithSequenceNumber:(int)number blobString:(NSString *)blob rowId:(sqlite3_int64 *)insertedRowId; +- (int)unstagedEventCount; +- (BOOL)stageEventsForUpload:(sqlite3_int64)headerId; +- (BOOL)updateAppKey:(NSString *)appKey; +- (NSString *)uploadBlobString; +- (BOOL)deleteUploadedData; +- (BOOL)resetAnalyticsData; +- (BOOL)vacuumIfRequired; + +- (NSTimeInterval)lastSessionStartTimestamp; +- (BOOL)setLastsessionStartTimestamp:(NSTimeInterval)timestamp; + +- (BOOL)isOptedOut; +- (BOOL)setOptedOut:(BOOL)optOut; +- (NSString *)installId; +- (NSString *)appKey; // Most recent app key-- may not be that used to open the session. + +- (NSString *)customDimension:(int)dimension; +- (BOOL)setCustomDimension:(int)dimension value:(NSString *)value; + +@end diff --git a/Localytics/LocalyticsDatabase.m b/Localytics/LocalyticsDatabase.m new file mode 100644 index 00000000..3b3700fe --- /dev/null +++ b/Localytics/LocalyticsDatabase.m @@ -0,0 +1,743 @@ +// +// LocalyticsDatabase.m +// LocalyticsDemo +// +// Created by jkaufman on 5/26/11. +// Copyright 2011 Localytics. All rights reserved. +// + +#import "LocalyticsDatabase.h" + +#define LOCALYTICS_DIR @".localytics" // Name for the directory in which Localytics database is stored +#define LOCALYTICS_DB @"localytics" // File name for the database (without extension) +#define BUSY_TIMEOUT 30 // Maximum time SQlite will busy-wait for the database to unlock before returning SQLITE_BUSY + +@interface LocalyticsDatabase () + - (int)schemaVersion; + - (void)createSchema; + - (void)upgradeToSchemaV2; + - (void)upgradeToSchemaV3; + - (void)moveDbToCaches; + - (NSString *)randomUUID; +@end + +@implementation LocalyticsDatabase + +// The singleton database object. +static LocalyticsDatabase *_sharedLocalyticsDatabase = nil; + ++ (NSString *)localyticsDirectoryPath { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); + return [[paths objectAtIndex:0] stringByAppendingPathComponent:LOCALYTICS_DIR]; +} + ++ (NSString *)localyticsDatabasePath { + NSString *path = [[LocalyticsDatabase localyticsDirectoryPath] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.sqlite", LOCALYTICS_DB]]; + return path; +} + +#pragma mark Singleton Class ++ (LocalyticsDatabase *)sharedLocalyticsDatabase { + @synchronized(self) { + if (_sharedLocalyticsDatabase == nil) { + _sharedLocalyticsDatabase = [[self alloc] init]; + } + } + return _sharedLocalyticsDatabase; +} + +- (LocalyticsDatabase *)init { + if((self = [super init])) { + + // Mover any data that a previous library may have left in the documents directory + [self moveDbToCaches]; + + // Create directory structure for Localytics. + NSString *directoryPath = [LocalyticsDatabase localyticsDirectoryPath]; + if (![[NSFileManager defaultManager] fileExistsAtPath:directoryPath]) { + [[NSFileManager defaultManager] createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:nil error:nil]; + } + + // Attempt to open database. It will be created if it does not exist, already. + NSString *dbPath = [LocalyticsDatabase localyticsDatabasePath]; + int code = sqlite3_open([dbPath UTF8String], &_databaseConnection); + + // If we were unable to open the database, it is likely corrupted. Clobber it and move on. + if (code != SQLITE_OK) { + [[NSFileManager defaultManager] removeItemAtPath:dbPath error:nil]; + code = sqlite3_open([dbPath UTF8String], &_databaseConnection); + } + + // Check db connection, creating schema if necessary. + if (code == SQLITE_OK) { + sqlite3_busy_timeout(_databaseConnection, BUSY_TIMEOUT); // Defaults to 0, otherwise. + if ([self schemaVersion] == 0) { + [self createSchema]; + } + } + + // Perform any Migrations if necessary + if ([self schemaVersion] < 2) { + [self upgradeToSchemaV2]; + } + if ([self schemaVersion] < 3) { + [self upgradeToSchemaV3]; + } + } + + return self; +} + +#pragma mark - Database + +- (BOOL)beginTransaction:(NSString *)name { + const char *sql = [[NSString stringWithFormat:@"SAVEPOINT %@", name] cStringUsingEncoding:NSUTF8StringEncoding]; + int code = sqlite3_exec(_databaseConnection, sql, NULL, NULL, NULL); + return code == SQLITE_OK; +} + +- (BOOL)releaseTransaction:(NSString *)name { + const char *sql = [[NSString stringWithFormat:@"RELEASE SAVEPOINT %@", name] cStringUsingEncoding:NSUTF8StringEncoding]; + int code = sqlite3_exec(_databaseConnection, sql, NULL, NULL, NULL); + return code == SQLITE_OK; +} + +- (BOOL)rollbackTransaction:(NSString *)name { + const char *sql = [[NSString stringWithFormat:@"ROLLBACK SAVEPOINT %@", name] cStringUsingEncoding:NSUTF8StringEncoding]; + int code = sqlite3_exec(_databaseConnection, sql, NULL, NULL, NULL); + return code == SQLITE_OK; +} + +- (int)schemaVersion { + int version = 0; + const char *sql = "SELECT MAX(schema_version) FROM localytics_info"; + sqlite3_stmt *selectSchemaVersion; + if(sqlite3_prepare_v2(_databaseConnection, sql, -1, &selectSchemaVersion, NULL) == SQLITE_OK) { + if(sqlite3_step(selectSchemaVersion) == SQLITE_ROW) { + version = sqlite3_column_int(selectSchemaVersion, 0); + } + } + sqlite3_finalize(selectSchemaVersion); + return version; +} + +- (NSString *)installId { + NSString *installId = nil; + + sqlite3_stmt *selectInstallId; + sqlite3_prepare_v2(_databaseConnection, "SELECT install_id FROM localytics_info", -1, &selectInstallId, NULL); + int code = sqlite3_step(selectInstallId); + if (code == SQLITE_ROW && sqlite3_column_text(selectInstallId, 0)) { + installId = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectInstallId, 0)]; + } + sqlite3_finalize(selectInstallId); + + return installId; +} + +- (NSString *)appKey { + NSString *appKey = nil; + + sqlite3_stmt *selectAppKey; + sqlite3_prepare_v2(_databaseConnection, "SELECT app_key FROM localytics_info", -1, &selectAppKey, NULL); + int code = sqlite3_step(selectAppKey); + if (code == SQLITE_ROW && sqlite3_column_text(selectAppKey, 0)) { + appKey = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectAppKey, 0)]; + } + sqlite3_finalize(selectAppKey); + + return appKey; +} + +// Due to the new iOS storage guidelines it is necessary to move the database out of the documents directory +// and into the /library/caches directory +- (void)moveDbToCaches { + NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *localyticsDocumentsDirectory = [[documentPaths objectAtIndex:0] stringByAppendingPathComponent:LOCALYTICS_DIR]; + NSArray *cachesPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); + NSString *localyticsCachesDirectory = [[cachesPaths objectAtIndex:0] stringByAppendingPathComponent:LOCALYTICS_DIR]; + + // If the old directory doesn't exist, there is nothing else to do here + if([[NSFileManager defaultManager] fileExistsAtPath:localyticsDocumentsDirectory] == NO) + { + return; + } + + // Try to move the directory + if(NO == [[NSFileManager defaultManager] moveItemAtPath:localyticsDocumentsDirectory + toPath:localyticsCachesDirectory + error:nil]) + { + // If the move failed try and, delete the old directory + [ [NSFileManager defaultManager] removeItemAtPath:localyticsDocumentsDirectory error:nil]; + } +} + +- (void)createSchema { + int code = SQLITE_OK; + + // Execute schema creation within a single transaction. + code = sqlite3_exec(_databaseConnection, "BEGIN", NULL, NULL, NULL); + + if (code == SQLITE_OK) { + code = sqlite3_exec(_databaseConnection, + "CREATE TABLE upload_headers (" + "sequence_number INTEGER PRIMARY KEY, " + "blob_string TEXT)", + NULL, NULL, NULL); + } + + if (code == SQLITE_OK) { + code = sqlite3_exec(_databaseConnection, + "CREATE TABLE events (" + "event_id INTEGER PRIMARY KEY AUTOINCREMENT, " // In case foreign key constraints are reintroduced. + "upload_header INTEGER, " + "blob_string TEXT NOT NULL)", + NULL, NULL, NULL); + } + + if (code == SQLITE_OK) { + code = sqlite3_exec(_databaseConnection, + "CREATE TABLE localytics_info (" + "schema_version INTEGER PRIMARY KEY, " + "last_upload_number INTEGER, " + "last_session_number INTEGER, " + "opt_out BOOLEAN, " + "last_close_event INTEGER, " + "last_flow_event INTEGER, " + "last_session_start REAL, " + "app_key CHAR(64), " + "custom_d0 CHAR(64), " + "custom_d1 CHAR(64), " + "custom_d2 CHAR(64), " + "custom_d3 CHAR(64) " + ")", + NULL, NULL, NULL); + } + + if (code == SQLITE_OK) { + code = sqlite3_exec(_databaseConnection, + "INSERT INTO localytics_info (schema_version, last_upload_number, last_session_number, opt_out) " + "VALUES (3, 0, 0, 0)", NULL, NULL, NULL); + } + + // Commit transaction. + if (code == SQLITE_OK || code == SQLITE_DONE) { + sqlite3_exec(_databaseConnection, "COMMIT", NULL, NULL, NULL); + } else { + sqlite3_exec(_databaseConnection, "ROLLBACK", NULL, NULL, NULL); + } +} + +// V2 adds a unique identifier for each installation +// This identifier has been moved to user preferences so the database an live in the caches directory +// Also adds storage for custom dimensions +- (void)upgradeToSchemaV2 { + int code = SQLITE_OK; + + code = sqlite3_exec(_databaseConnection, "BEGIN", NULL, NULL, NULL); + + if (code == SQLITE_OK) { + code = sqlite3_exec(_databaseConnection, + "ALTER TABLE localytics_info ADD install_id CHAR(40)", + NULL, NULL, NULL); + } + + if (code == SQLITE_OK) { + code = sqlite3_exec(_databaseConnection, + "ALTER TABLE localytics_info ADD custom_d0 CHAR(64)", + NULL, NULL, NULL); + } + + if (code == SQLITE_OK) { + code = sqlite3_exec(_databaseConnection, + "ALTER TABLE localytics_info ADD custom_d1 CHAR(64)", + NULL, NULL, NULL); + } + + if (code == SQLITE_OK) { + code = sqlite3_exec(_databaseConnection, + "ALTER TABLE localytics_info ADD custom_d2 CHAR(64)", + NULL, NULL, NULL); + } + + if (code == SQLITE_OK) { + sqlite3_exec(_databaseConnection, + "ALTER TABLE localytics_info ADD custom_d3 CHAR(64)", + NULL, NULL, NULL); + } + + // Attempt to set schema version and install_id regardless of the result code following the ALTER statements above. + // This is necessary because a previous version of the library performed the migration without setting these values. + // The transaction will succeed even if the individual statements fail with errors (eg. "duplicate column name"). + sqlite3_stmt *updateLocalyticsInfo; + sqlite3_prepare_v2(_databaseConnection, "UPDATE localytics_info set install_id = ?, schema_version = 2 ", -1, &updateLocalyticsInfo, NULL); + sqlite3_bind_text (updateLocalyticsInfo, 1, [[self randomUUID] UTF8String], -1, SQLITE_TRANSIENT); + code = sqlite3_step(updateLocalyticsInfo); + sqlite3_finalize(updateLocalyticsInfo); + + // Commit transaction. + if (code == SQLITE_OK || code == SQLITE_DONE) { + sqlite3_exec(_databaseConnection, "COMMIT", NULL, NULL, NULL); + } else { + sqlite3_exec(_databaseConnection, "ROLLBACK", NULL, NULL, NULL); + } +} + +// V3 adds a field for the last app key and patches a V2 migration issue. +- (void)upgradeToSchemaV3 { + sqlite3_exec(_databaseConnection, + "ALTER TABLE localytics_info ADD app_key CHAR(64)", + NULL, NULL, NULL); +} + +- (NSUInteger)databaseSize { + NSUInteger size = 0; + NSDictionary *fileAttributes = [[NSFileManager defaultManager] + attributesOfItemAtPath:[LocalyticsDatabase localyticsDatabasePath] + error:nil]; + size = [fileAttributes fileSize]; + return size; +} + +- (int) eventCount { + int count = 0; + const char *sql = "SELECT count(*) FROM events"; + sqlite3_stmt *selectEventCount; + + if(sqlite3_prepare_v2(_databaseConnection, sql, -1, &selectEventCount, NULL) == SQLITE_OK) + { + if(sqlite3_step(selectEventCount) == SQLITE_ROW) { + count = sqlite3_column_int(selectEventCount, 0); + } + } + sqlite3_finalize(selectEventCount); + + return count; +} + +- (NSTimeInterval)createdTimestamp { + NSTimeInterval timestamp = 0; + NSDictionary *fileAttributes = [[NSFileManager defaultManager] + attributesOfItemAtPath:[LocalyticsDatabase localyticsDatabasePath] + error:nil]; + timestamp = [[fileAttributes fileCreationDate] timeIntervalSince1970]; + return timestamp; +} + +- (NSTimeInterval)lastSessionStartTimestamp { + + NSTimeInterval lastSessionStart = 0; + + sqlite3_stmt *selectLastSessionStart; + sqlite3_prepare_v2(_databaseConnection, "SELECT last_session_start FROM localytics_info", -1, &selectLastSessionStart, NULL); + int code = sqlite3_step(selectLastSessionStart); + if (code == SQLITE_ROW) { + lastSessionStart = sqlite3_column_double(selectLastSessionStart, 0) == 1; + } + sqlite3_finalize(selectLastSessionStart); + + return lastSessionStart; +} + +- (BOOL)setLastsessionStartTimestamp:(NSTimeInterval)timestamp { + sqlite3_stmt *updateLastSessionStart; + sqlite3_prepare_v2(_databaseConnection, "UPDATE localytics_info SET last_session_start = ?", -1, &updateLastSessionStart, NULL); + sqlite3_bind_double(updateLastSessionStart, 1, timestamp); + int code = sqlite3_step(updateLastSessionStart); + sqlite3_finalize(updateLastSessionStart); + + return code == SQLITE_DONE; +} + +- (BOOL)isOptedOut { + BOOL optedOut = NO; + + sqlite3_stmt *selectOptOut; + sqlite3_prepare_v2(_databaseConnection, "SELECT opt_out FROM localytics_info", -1, &selectOptOut, NULL); + int code = sqlite3_step(selectOptOut); + if (code == SQLITE_ROW) { + optedOut = sqlite3_column_int(selectOptOut, 0) == 1; + } + sqlite3_finalize(selectOptOut); + + return optedOut; +} + +- (BOOL)setOptedOut:(BOOL)optOut { + sqlite3_stmt *updateOptedOut; + sqlite3_prepare_v2(_databaseConnection, "UPDATE localytics_info SET opt_out = ?", -1, &updateOptedOut, NULL); + sqlite3_bind_int(updateOptedOut, 1, optOut); + int code = sqlite3_step(updateOptedOut); + sqlite3_finalize(updateOptedOut); + + return code == SQLITE_OK; +} + +- (NSString *)customDimension:(int)dimension { + if(dimension < 0 || dimension > 3) { + return nil; + } + + NSString *value = nil; + NSString *query = [NSString stringWithFormat:@"select custom_d%i from localytics_info", dimension]; + + sqlite3_stmt *selectCustomDim; + sqlite3_prepare_v2(_databaseConnection, [query UTF8String], -1, &selectCustomDim, NULL); + int code = sqlite3_step(selectCustomDim); + if (code == SQLITE_ROW && sqlite3_column_text(selectCustomDim, 0)) { + value = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectCustomDim, 0)]; + } + sqlite3_finalize(selectCustomDim); + + return value; +} + +- (BOOL)setCustomDimension:(int)dimension value:(NSString *)value { + if(dimension < 0 || dimension > 3) { + return false; + } + + NSString *query = [NSString stringWithFormat:@"update localytics_info SET custom_d%i = %@", + dimension, + (value == nil) ? @"null" : [NSString stringWithFormat:@"\"%@\"", value]]; + + int code = sqlite3_exec(_databaseConnection, [query UTF8String], NULL, NULL, NULL); + + return code == SQLITE_OK; +} + +- (BOOL)incrementLastUploadNumber:(int *)uploadNumber { + NSString *t = @"increment_upload_number"; + int code = SQLITE_OK; + + code = [self beginTransaction:t] ? SQLITE_OK : SQLITE_ERROR; + + if(code == SQLITE_OK) { + // Increment value + code = sqlite3_exec(_databaseConnection, + "UPDATE localytics_info " + "SET last_upload_number = (last_upload_number + 1)", + NULL, NULL, NULL); + } + + if(code == SQLITE_OK) { + // Retrieve new value + sqlite3_stmt *selectUploadNumber; + sqlite3_prepare_v2(_databaseConnection, + "SELECT last_upload_number FROM localytics_info", + -1, &selectUploadNumber, NULL); + code = sqlite3_step(selectUploadNumber); + if (code == SQLITE_ROW) { + *uploadNumber = sqlite3_column_int(selectUploadNumber, 0); + } + sqlite3_finalize(selectUploadNumber); + } + + if(code == SQLITE_ROW) { + [self releaseTransaction:t]; + } else { + [self rollbackTransaction:t]; + } + + return code == SQLITE_ROW; +} + +- (BOOL)incrementLastSessionNumber:(int *)sessionNumber { + NSString *t = @"increment_session_number"; + int code = [self beginTransaction:t] ? SQLITE_OK : SQLITE_ERROR; + + if(code == SQLITE_OK) { + // Increment value + code = sqlite3_exec(_databaseConnection, + "UPDATE localytics_info " + "SET last_session_number = (last_session_number + 1)", + NULL, NULL, NULL); + } + + if(code == SQLITE_OK) { + // Retrieve new value + sqlite3_stmt *selectSessionNumber; + sqlite3_prepare_v2(_databaseConnection, + "SELECT last_session_number FROM localytics_info", + -1, &selectSessionNumber, NULL); + code = sqlite3_step(selectSessionNumber); + if (code == SQLITE_ROW && sessionNumber != NULL) { + *sessionNumber = sqlite3_column_int(selectSessionNumber, 0); + } + sqlite3_finalize(selectSessionNumber); + } + + if(code == SQLITE_ROW) { + [self releaseTransaction:t]; + } else { + [self rollbackTransaction:t]; + } + + return code == SQLITE_ROW; +} + +- (BOOL)addEventWithBlobString:(NSString *)blob { + + int code = SQLITE_OK; + sqlite3_stmt *insertEvent; + sqlite3_prepare_v2(_databaseConnection, "INSERT INTO events (blob_string) VALUES (?)", -1, &insertEvent, NULL); + sqlite3_bind_text(insertEvent, 1, [blob UTF8String], -1, SQLITE_TRANSIENT); + code = sqlite3_step(insertEvent); + sqlite3_finalize(insertEvent); + + return code == SQLITE_DONE; +} + +- (BOOL)addCloseEventWithBlobString:(NSString *)blob { + NSString *t = @"add_close_event"; + BOOL success = [self beginTransaction:t]; + + // Add close event. + if (success) { + success = [self addEventWithBlobString:blob]; + } + + // Record row id to localytics_info so that it can be removed if the session resumes. + if (success) { + sqlite3_stmt *updateCloseEvent; + sqlite3_prepare_v2(_databaseConnection, "UPDATE localytics_info SET last_close_event = (SELECT event_id FROM events WHERE rowid = ?)", -1, &updateCloseEvent, NULL); + sqlite3_int64 lastRow = sqlite3_last_insert_rowid(_databaseConnection); + sqlite3_bind_int64(updateCloseEvent, 1, lastRow); + int code = sqlite3_step(updateCloseEvent); + sqlite3_finalize(updateCloseEvent); + success = code == SQLITE_DONE; + } + + if (success) { + [self releaseTransaction:t]; + } else { + [self rollbackTransaction:t]; + } + return success; +} + +- (BOOL)addFlowEventWithBlobString:(NSString *)blob { + NSString *t = @"add_flow_event"; + BOOL success = [self beginTransaction:t]; + + // Add flow event. + if (success) { + success = [self addEventWithBlobString:blob]; + } + + // Record row id to localytics_info so that it can be removed if the session resumes. + if (success) { + sqlite3_stmt *updateFlowEvent; + sqlite3_prepare_v2(_databaseConnection, "UPDATE localytics_info SET last_flow_event = (SELECT event_id FROM events WHERE rowid = ?)", -1, &updateFlowEvent, NULL); + sqlite3_int64 lastRow = sqlite3_last_insert_rowid(_databaseConnection); + sqlite3_bind_int64(updateFlowEvent, 1, lastRow); + int code = sqlite3_step(updateFlowEvent); + sqlite3_finalize(updateFlowEvent); + success = code == SQLITE_DONE; + } + + if (success) { + [self releaseTransaction:t]; + } else { + [self rollbackTransaction:t]; + } + return success; +} + +- (BOOL)removeLastCloseAndFlowEvents { + // Attempt to remove the last recorded close event. + // Fail quietly if none was saved or it was previously removed. + int code = sqlite3_exec(_databaseConnection, "DELETE FROM events WHERE event_id = (SELECT last_close_event FROM localytics_info) OR event_id = (SELECT last_flow_event FROM localytics_info)", NULL, NULL, NULL); + + return code == SQLITE_OK; +} + +- (BOOL)addHeaderWithSequenceNumber:(int)number blobString:(NSString *)blob rowId:(sqlite3_int64 *)insertedRowId { + sqlite3_stmt *insertHeader; + sqlite3_prepare_v2(_databaseConnection, "INSERT INTO upload_headers (sequence_number, blob_string) VALUES (?, ?)", -1, &insertHeader, NULL); + sqlite3_bind_int(insertHeader, 1, number); + sqlite3_bind_text(insertHeader, 2, [blob UTF8String], -1, SQLITE_TRANSIENT); + int code = sqlite3_step(insertHeader); + sqlite3_finalize(insertHeader); + + if (code == SQLITE_DONE && insertedRowId != NULL) { + *insertedRowId = sqlite3_last_insert_rowid(_databaseConnection); + } + + return code == SQLITE_DONE; +} + +- (int)unstagedEventCount { + int rowCount = 0; + sqlite3_stmt *selectEventCount; + sqlite3_prepare_v2(_databaseConnection, "SELECT COUNT(*) FROM events WHERE UPLOAD_HEADER IS NULL", -1, &selectEventCount, NULL); + int code = sqlite3_step(selectEventCount); + if (code == SQLITE_ROW) { + rowCount = sqlite3_column_int(selectEventCount, 0); + } + sqlite3_finalize(selectEventCount); + + return rowCount; +} + +- (BOOL)stageEventsForUpload:(sqlite3_int64)headerId { + + // Associate all outstanding events with the given upload header ID. + NSString *stageEvents = [NSString stringWithFormat:@"UPDATE events SET upload_header = ? WHERE upload_header IS NULL"]; + sqlite3_stmt *updateEvents; + sqlite3_prepare_v2(_databaseConnection, [stageEvents UTF8String], -1, &updateEvents, NULL); + sqlite3_bind_int(updateEvents, 1, headerId); + int code = sqlite3_step(updateEvents); + sqlite3_finalize(updateEvents); + BOOL success = (code == SQLITE_DONE); + + return success; +} + +- (BOOL)updateAppKey:(NSString *)appKey { + sqlite3_stmt *updateAppKey; + sqlite3_prepare_v2(_databaseConnection, "UPDATE localytics_info set app_key = ?", -1, &updateAppKey, NULL); + sqlite3_bind_text (updateAppKey, 1, [appKey UTF8String], -1, SQLITE_TRANSIENT); + int code = sqlite3_step(updateAppKey); + sqlite3_finalize(updateAppKey); + BOOL success = (code == SQLITE_DONE); + + return success; +} + +- (NSString *)uploadBlobString { + + // Retrieve the blob strings of each upload header and its child events, in order. + const char *sql = "SELECT * FROM ( " + " SELECT h.blob_string AS 'blob', h.sequence_number as 'seq', 0 FROM upload_headers h" + " UNION ALL " + " SELECT e.blob_string AS 'blob', e.upload_header as 'seq', 1 FROM events e" + ") " + "ORDER BY 2, 3"; + sqlite3_stmt *selectBlobs; + sqlite3_prepare_v2(_databaseConnection, sql, -1, &selectBlobs, NULL); + NSMutableString *uploadBlobString = [NSMutableString string]; + while (sqlite3_step(selectBlobs) == SQLITE_ROW) { + const char *blob = (const char *)sqlite3_column_text(selectBlobs, 0); + if (blob != NULL) { + NSString *blobString = [[NSString alloc] initWithCString:blob encoding:NSUTF8StringEncoding]; + [uploadBlobString appendString:blobString]; + [blobString release]; + } + } + sqlite3_finalize(selectBlobs); + + return [[uploadBlobString copy] autorelease]; +} + +- (BOOL)deleteUploadedData { + // Delete all headers and staged events. + NSString *t = @"delete_upload_data"; + int code = [self beginTransaction:t] ? SQLITE_OK : SQLITE_ERROR; + + if (code == SQLITE_OK) { + code = sqlite3_exec(_databaseConnection, "DELETE FROM events WHERE upload_header IS NOT NULL", NULL, NULL, NULL); + } + + if (code == SQLITE_OK) { + code = sqlite3_exec(_databaseConnection, "DELETE FROM upload_headers", NULL, NULL, NULL); + } + + if (code == SQLITE_OK) { + [self releaseTransaction:t]; + } else { + [self rollbackTransaction:t]; + } + + return code == SQLITE_OK; +} + +- (BOOL)resetAnalyticsData { + // Delete or zero all analytics data. + // Reset: headers, events, session number, upload number, last session start, last close event, and last flow event. + // Unaffected: schema version, opt out status, install ID (deprecated), and app key. + + NSString *t = @"reset_analytics_data"; + int code = [self beginTransaction:t] ? SQLITE_OK : SQLITE_ERROR; + + if (code == SQLITE_OK) { + code = sqlite3_exec(_databaseConnection, "DELETE FROM events", NULL, NULL, NULL); + } + + if (code == SQLITE_OK) { + code = sqlite3_exec(_databaseConnection, "DELETE FROM upload_headers", NULL, NULL, NULL); + } + + if (code == SQLITE_OK) { + code = sqlite3_exec(_databaseConnection,"UPDATE localytics_info SET last_session_number = 0, last_upload_number = 0," + "last_close_event = null, last_flow_event = null, last_session_start = null, " + "custom_d0 = null, custom_d1 = null, custom_d2 = null, custom_d3 = null", + NULL, NULL, NULL); + } + + if (code == SQLITE_OK) { + [self releaseTransaction:t]; + } else { + [self rollbackTransaction:t]; + } + + return code == SQLITE_OK; +} + +- (BOOL)vacuumIfRequired { + int code = SQLITE_OK; + if ([self databaseSize] > MAX_DATABASE_SIZE * VACUUM_THRESHOLD) { + code = sqlite3_exec(_databaseConnection, "VACUUM", NULL, NULL, NULL); + } + + return code == SQLITE_OK; +} + +- (NSString *)randomUUID { + CFUUIDRef theUUID = CFUUIDCreate(NULL); + CFStringRef stringUUID = CFUUIDCreateString(NULL, theUUID); + CFRelease(theUUID); + return [(NSString *)stringUUID autorelease]; +} + +#pragma mark - Lifecycle + ++ (id)allocWithZone:(NSZone *)zone { + @synchronized(self) { + if (_sharedLocalyticsDatabase == nil) { + _sharedLocalyticsDatabase = [super allocWithZone:zone]; + return _sharedLocalyticsDatabase; + } + } + // returns nil on subsequent allocations + return nil; +} + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + +- (id)retain { + return self; +} + +- (unsigned)retainCount { + // maximum value of an unsigned int - prevents additional retains for the class + return UINT_MAX; +} + +- (oneway void)release { + // ignore release commands +} + +- (id)autorelease { + return self; +} + +- (void)dealloc { + sqlite3_close(_databaseConnection); + [super dealloc]; +} + +@end diff --git a/Localytics/LocalyticsSession.h b/Localytics/LocalyticsSession.h new file mode 100644 index 00000000..e204469d --- /dev/null +++ b/Localytics/LocalyticsSession.h @@ -0,0 +1,216 @@ +// LocalyticsSession.h +// Copyright (C) 2009 Char Software Inc., DBA Localytics +// +// This code is provided under the Localytics Modified BSD License. +// A copy of this license has been distributed in a file called LICENSE +// with this source code. +// +// Please visit www.localytics.com for more information. + +#import + +// Set this to true to enable localytics traces (useful for debugging) +#define DO_LOCALYTICS_LOGGING false + +/*! + @class LocalyticsSession + @discussion The class which manages creating, collecting, & uploading a Localytics session. + Please see the following guides for information on how to best use this + library, sample code, and other useful information: +

+ + Best Practices +
    +
  • Instantiate the LocalyticsSession object in applicationDidFinishLaunching.
  • +
  • Open your session and begin your uploads in applicationDidFinishLaunching. This way the + upload has time to complete and it all happens before your users have a + chance to begin any data intensive actions of their own.
  • +
  • Close the session in applicationWillTerminate, and in applicationDidEnterBackground.
  • +
  • Resume the session in applicationWillEnterForeground.
  • +
  • Do not call any Localytics functions inside a loop. Instead, calls + such as tagEvent should follow user actions. This limits the + amount of data which is stored and uploaded.
  • +
  • Do not use multiple LocalticsSession objects to upload data with + multiple application keys. This can cause invalid state.
  • +
+ + @author Localytics + */ +@interface LocalyticsSession : NSObject { + + BOOL _hasInitialized; // Whether or not the session object has been initialized. + BOOL _isSessionOpen; // Whether or not this session has been opened. + float _backgroundSessionTimeout; // If an App stays in the background for more + // than this many seconds, start a new session + // when it returns to foreground. + @private + #pragma mark Member Variables + dispatch_queue_t _queue; // Queue of Localytics block objects. + dispatch_group_t _criticalGroup; // Group of blocks the must complete before backgrounding. + NSString *_sessionUUID; // Unique identifier for this session. + NSString *_applicationKey; // Unique identifier for the instrumented application + NSTimeInterval _lastSessionStartTimestamp; // The start time of the most recent session. + NSDate *_sessionResumeTime; // Time session was started or resumed. + NSDate *_sessionCloseTime; // Time session was closed. + NSMutableString *_unstagedFlowEvents; // Comma-delimited list of app screens and events tagged during this + // session that have NOT been staged for upload. + NSMutableString *_stagedFlowEvents; // App screens and events tagged during this session that HAVE been staged + // for upload. + NSMutableString *_screens; // Comma-delimited list of screens tagged during this session. + NSTimeInterval _sessionActiveDuration; // Duration that session open. + BOOL _sessionHasBeenOpen; // Whether or not this session has ever been open. +} + +@property dispatch_queue_t queue; +@property dispatch_group_t criticalGroup; +@property BOOL isSessionOpen; +@property BOOL hasInitialized; +@property float backgroundSessionTimeout; + +#pragma mark Public Methods +/*! + @method sharedLocalyticsSession + @abstract Accesses the Session object. This is a Singleton class which maintains + a single session throughout your application. It is possible to manage your own + session, but this is the easiest way to access the Localytics object throughout your code. + The class is accessed within the code using the following syntax: + [[LocalyticsSession sharedLocalyticsSession] functionHere] + So, to tag an event, all that is necessary, anywhere in the code is: + [[LocalyticsSession sharedLocalyticsSession] tagEvent:@"MY_EVENT"]; + */ ++ (LocalyticsSession *)sharedLocalyticsSession; + +/*! + @method LocalyticsSession + @abstract Initializes the Localytics Object. Not necessary if you choose to use startSession. + @param applicationKey The key unique for each application generated at www.localytics.com + */ +- (void)LocalyticsSession:(NSString *)appKey; + +/*! + @method startSession + @abstract An optional convenience initialize method that also calls the LocalyticsSession, open & + upload methods. Best Practice is to call open & upload immediately after Localytics Session when loading an app, + this method fascilitates that behavior. + It is recommended that this call be placed in applicationDidFinishLaunching. + @param applicationKey The key unique for each application generated + at www.localytics.com + */ +- (void)startSession:(NSString *)appKey; + +/*! + @method setOptIn + @abstract (OPTIONAL) Allows the application to control whether or not it will collect user data. + Even if this call is used, it is necessary to continue calling upload(). No new data will be + collected, so nothing new will be uploaded but it is necessary to upload an event telling the + server this user has opted out. + @param optedIn True if the user is opted in, false otherwise. + */ +- (void)setOptIn:(BOOL)optedIn; + +/*! + @method isOptedIn + @abstract (OPTIONAL) Whether or not this user has is opted in or out. The only way they can be + opted out is if setOptIn(false) has been called before this. This function should only be + used to pre-populate a checkbox in an options menu. It is not recommended that an application + branch based on Localytics instrumentation because this creates an additional test case. If + the app is opted out, all subsequent Localytics calls will return immediately. + @result true if the user is opted in, false otherwise. + */ +- (BOOL)isOptedIn; + +/*! + @method open + @abstract Opens the Localytics session. Not necessary if you choose to use startSession. + The session time as presented on the website is the time between open and the + final close so it is recommended to open the session as early as possible, and close + it at the last moment. The session must be opened before any tags can + be written. It is recommended that this call be placed in applicationDidFinishLaunching. +
+ If for any reason this is called more than once every subsequent open call + will be ignored. + */ +- (void)open; + +/*! + @method resume + @abstract Resumes the Localytics session. When the App enters the background, the session is + closed and the time of closing is recorded. When the app returns to the foreground, the session + is resumed. If the time since closing is greater than BACKGROUND_SESSION_TIMEOUT, (15 seconds + by default) a new session is created, and uploading is triggered. Otherwise, the previous session + is reopened. +*/ +- (void)resume; + +/*! + @method close + @abstract Closes the Localytics session. This should be called in + applicationWillTerminate. +
+ If close is not called, the session will still be uploaded but no + events will be processed and the session time will not appear. This is + because the session is not yet closed so it should not be used in + comparison with sessions which are closed. + */ +- (void)close; + +/*! + @method tagEvent + @abstract Allows a session to tag a particular event as having occurred. For + example, if a view has three buttons, it might make sense to tag + each button click with the name of the button which was clicked. + For another example, in a game with many levels it might be valuable + to create a new tag every time the user gets to a new level in order + to determine how far the average user is progressing in the game. +
+ Tagging Best Practices +
    +
  • DO NOT use tags to record personally identifiable information.
  • +
  • The best way to use tags is to create all the tag strings as predefined + constants and only use those. This is more efficient and removes the risk of + collecting personal information.
  • +
  • Do not set tags inside loops or any other place which gets called + frequently. This can cause a lot of data to be stored and uploaded.
  • +
+
+ See the tagging guide at: http://wiki.localytics.com/ + @param event The name of the event which occurred. + */ +- (void)tagEvent:(NSString *)event; + +- (void)tagEvent:(NSString *)event attributes:(NSDictionary *)attributes; + +- (void)tagEvent:(NSString *)event attributes:(NSDictionary *)attributes reportAttributes:(NSDictionary *)reportAttributes; + +/*! + @method tagScreen + @abstract Allows tagging the flow of screens encountered during the session. + @param screen The name of the screen + */ +- (void)tagScreen:(NSString *)screen; + +/*! + @method upload + @abstract Creates a low priority thread which uploads any Localytics data already stored + on the device. This should be done early in the process life in order to + guarantee as much time as possible for slow connections to complete. It is also reasonable + to upload again when the application is exiting because if the upload is cancelled the data + will just get uploaded the next time the app comes up. + */ +- (void)upload; + +/*! + @method setCustomDimension + @abstract (ENTERPRISE ONLY) Sets the value of a custom dimension. Custom dimensions are dimensions + which contain user defined data unlike the predefined dimensions such as carrier, model, and country. + Once a value for a custom dimension is set, the device it was set on will continue to upload that value + until the value is changed. To clear a value pass nil as the value. + The proper use of custom dimensions involves defining a dimension with less than ten distinct possible + values and assigning it to one of the four available custom dimensions. Once assigned this definition should + never be changed without changing the App Key otherwise old installs of the application will pollute new data. + */ +- (void)setCustomDimension:(int)dimension value:(NSString *)value; + +@end diff --git a/Localytics/LocalyticsSession.m b/Localytics/LocalyticsSession.m new file mode 100644 index 00000000..8f75c36d --- /dev/null +++ b/Localytics/LocalyticsSession.m @@ -0,0 +1,1148 @@ +// LocalyticsSession.m +// Copyright (C) 2009 Char Software Inc., DBA Localytics +// +// This code is provided under the Localytics Modified BSD License. +// A copy of this license has been distributed in a file called LICENSE +// with this source code. +// +// Please visit www.localytics.com for more information. + +#import "LocalyticsSession.h" +#import "WebserviceConstants.h" +#import "LocalyticsUploader.h" +#import "LocalyticsDatabase.h" + +#include +#include +#include +#include +#include +#include +#include + +#pragma mark Constants +#define PREFERENCES_KEY @"_localytics_install_id" // The randomly generated ID for each install of the app +#define CLIENT_VERSION @"iOS_2.6" // The version of this library +#define LOCALYTICS_DIR @".localytics" // The directory in which the Localytics database is stored +#define IFT_ETHER 0x6 // Ethernet CSMACD +#define PATH_TO_APT @"/private/var/lib/apt/" + +#define DEFAULT_BACKGROUND_SESSION_TIMEOUT 15 // Default value for how many seconds a session persists when App shifts to the background. + +// The singleton session object. +static LocalyticsSession *_sharedLocalyticsSession = nil; + +@interface LocalyticsSession() + +@property (nonatomic, retain) NSString *sessionUUID; +@property (nonatomic, retain) NSString *applicationKey; +@property (nonatomic, assign) NSTimeInterval lastSessionStartTimestamp; +@property (nonatomic, retain) NSDate *sessionResumeTime; +@property (nonatomic, retain) NSDate *sessionCloseTime; +@property (nonatomic, retain) NSMutableString *unstagedFlowEvents; +@property (nonatomic, retain) NSMutableString *stagedFlowEvents; +@property (nonatomic, retain) NSMutableString *screens; +@property (nonatomic, assign) NSTimeInterval sessionActiveDuration; +@property (nonatomic, assign) BOOL sessionHasBeenOpen; + +// Private methods. +- (void)ll_open; +- (void)reopenPreviousSession; +- (void)addFlowEventWithName:(NSString *)name type:(NSString *)eventType; +- (void)addScreenWithName:(NSString *)name; +- (NSString *)blobHeaderStringWithSequenceNumber:(int)nextSequenceNumber; +- (BOOL)ll_isOptedIn; +- (BOOL)createOptEvent:(BOOL)optState; +- (BOOL)saveApplicationFlowAndRemoveOnResume:(BOOL)removeOnResume; +- (NSString *)formatAttributeWithName:(NSString *)paramName value:(NSString *)paramValue; +- (NSString *)formatAttributeWithName:(NSString *)paramName value:(NSString *)paramValue first:(BOOL)firstAttribute; +- (void)logMessage:(NSString *)message; + +// Datapoint methods. +- (NSString *)customDimensions; +- (NSString *)macAddress; +- (NSString *)hashString:(NSString *)input; +- (NSString *)randomUUID; +- (NSString *)escapeString:(NSString *)input; +- (NSString *)installationId; +- (NSString *)uniqueDeviceIdentifier; +- (NSString *)appVersion; +- (NSTimeInterval)currentTimestamp; +- (BOOL)isDeviceJailbroken; +- (NSString *)deviceModel; +- (NSString *)modelSizeString; +- (double)availableMemory; + +@end + +@implementation LocalyticsSession + +@synthesize queue = _queue; +@synthesize criticalGroup = _criticalGroup; +@synthesize sessionUUID = _sessionUUID; +@synthesize applicationKey = _applicationKey; +@synthesize lastSessionStartTimestamp = _lastSessionStartTimestamp; +@synthesize sessionResumeTime = _sessionResumeTime; +@synthesize sessionCloseTime = _sessionCloseTime; +@synthesize isSessionOpen = _isSessionOpen; +@synthesize hasInitialized = _hasInitialized; +@synthesize backgroundSessionTimeout = _backgroundSessionTimeout; +@synthesize unstagedFlowEvents = _unstagedFlowEvents; +@synthesize stagedFlowEvents = _stagedFlowEvents; +@synthesize screens = _screens; +@synthesize sessionActiveDuration = _sessionActiveDuration; +@synthesize sessionHasBeenOpen = _sessionHasBeenOpen; + +#pragma mark Singleton + ++ (LocalyticsSession *)sharedLocalyticsSession { + @synchronized(self) { + if (_sharedLocalyticsSession == nil) { + _sharedLocalyticsSession = [[self alloc] init]; + } + } + return _sharedLocalyticsSession; +} + +- (LocalyticsSession *)init { + if((self = [super init])) { + _isSessionOpen = NO; + _hasInitialized = NO; + _backgroundSessionTimeout = DEFAULT_BACKGROUND_SESSION_TIMEOUT; + _sessionHasBeenOpen = NO; + _queue = dispatch_queue_create("com.Localytics.operations", DISPATCH_QUEUE_SERIAL); + _criticalGroup = dispatch_group_create(); + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; + + [LocalyticsDatabase sharedLocalyticsDatabase]; + } + + return self; +} + +#pragma mark Public Methods + +- (void)LocalyticsSession:(NSString *)appKey { + // If the session has already initialized, don't bother doing it again. + if(self.hasInitialized) + { + [self logMessage:@"Object has already been initialized."]; + return; + } + + @try { + + if(appKey == (id)[NSNull null] || appKey.length == 0) { + [self logMessage:@"App key is null or empty."]; + self.hasInitialized = NO; + return; + } + + // App key should only be alphanumeric chars and dashes. + NSString *trimmedAppKey = [appKey stringByReplacingOccurrencesOfString:@"-" withString:@""]; + if([[trimmedAppKey stringByTrimmingCharactersInSet:[NSCharacterSet alphanumericCharacterSet]] isEqualToString:@""] == false) { + [self logMessage:@"App key may only contain dashes and alphanumeric characters."]; + self.hasInitialized = NO; + return; + } + + if ([LocalyticsDatabase sharedLocalyticsDatabase]) { + // Check if the app key has changed. + NSString *lastAppKey = [[LocalyticsDatabase sharedLocalyticsDatabase] appKey]; + if (![lastAppKey isEqualToString:appKey]) { + if (lastAppKey) { + // Clear previous events and dimensions to guarantee that new data isn't associated with the old app key. + [[LocalyticsDatabase sharedLocalyticsDatabase] resetAnalyticsData]; + + // Vacuum to improve the odds of opening a new session following bulk delete. + [[LocalyticsDatabase sharedLocalyticsDatabase] vacuumIfRequired]; + } + // Record the key for future checks. + [[LocalyticsDatabase sharedLocalyticsDatabase] updateAppKey:appKey]; + } + + self.applicationKey = appKey; + self.hasInitialized = YES; + [self logMessage:[@"Object Initialized. Application's key is: " stringByAppendingString:self.applicationKey]]; + } + } + @catch (NSException * e) {} +} + +- (void)startSession:(NSString *)appKey { + [self LocalyticsSession:appKey]; + [self open]; + [self upload]; +} + +// Public interface to ll_open. +- (void)open { + dispatch_async(_queue, ^{ + [self ll_open]; + }); +} + +- (void)resume { + dispatch_async(_queue, ^{ + // Do nothing if session is already open + if(self.isSessionOpen == YES) + return; + + if([self ll_isOptedIn] == false) { + [self logMessage:@"Can't resume session because user is opted out."]; + return; + } + + // conditions for resuming previous session + if(self.sessionHasBeenOpen && + (!self.sessionCloseTime || + [self.sessionCloseTime timeIntervalSinceNow]*-1 <= self.backgroundSessionTimeout)) { + // Note that we allow the session to be resumed even if the database size exceeds the + // maximum. This is because we don't want to create incomplete sessions. If the DB was large + // enough that the previous session could not be opened, there will be nothing to resume. But + // if this session caused it to go over it is better to let it complete and stop the next one + // from being created. + [self logMessage:@"Resume called - Resuming previous session."]; + [self reopenPreviousSession]; + } else { + // otherwise open new session and upload + [self logMessage:@"Resume called - Opening a new session."]; + [self ll_open]; + } + self.sessionCloseTime = nil; + }); +} + +- (void)close { + dispatch_group_async(_criticalGroup, _queue, ^{ + // Do nothing if the session is not open + if (self.isSessionOpen == NO) { + [self logMessage:@"Unable to close session"]; + return; + } + + // Save time of close + self.sessionCloseTime = [NSDate date]; + + // Update active session duration. + self.sessionActiveDuration += [self.sessionCloseTime timeIntervalSinceDate:self.sessionResumeTime]; + + int sessionLength = (int)[[NSDate date] timeIntervalSince1970] - self.lastSessionStartTimestamp; + + @try { + // Create the JSON representing the close blob + NSMutableString *closeEventString = [NSMutableString string]; + [closeEventString appendString:@"{"]; + [closeEventString appendString:[self formatAttributeWithName:PARAM_DATA_TYPE value:@"c" first:YES]]; + [closeEventString appendString:[self formatAttributeWithName:PARAM_SESSION_UUID value:self.sessionUUID]]; + [closeEventString appendString:[self formatAttributeWithName:PARAM_UUID value:[self randomUUID] ]]; + [closeEventString appendFormat:@",\"%@\":%u", PARAM_SESSION_START, (long)self.lastSessionStartTimestamp]; + [closeEventString appendFormat:@",\"%@\":%u", PARAM_SESSION_ACTIVE, (long)self.sessionActiveDuration]; + [closeEventString appendFormat:@",\"%@\":%u", PARAM_CLIENT_TIME, (long)[self currentTimestamp]]; + + // Avoid recording session lengths of users with unreasonable client times (usually caused by developers testing clock change attacks) + if(sessionLength > 0 && sessionLength < 400000) { + [closeEventString appendFormat:@",\"%@\":%u", PARAM_SESSION_TOTAL, sessionLength]; + } + + // Open second level - screen flow + [closeEventString appendFormat:@",\"%@\":[", PARAM_SESSION_SCREENFLOW]; + [closeEventString appendString:self.screens]; + + // Close second level - screen flow + [closeEventString appendString:@"]"]; + + // Append the custom dimensions + [closeEventString appendString:[self customDimensions]]; + + // Close first level - close blob + [closeEventString appendString:@"}\n"]; + + BOOL success = [[LocalyticsDatabase sharedLocalyticsDatabase] addCloseEventWithBlobString:[[closeEventString copy] autorelease]]; + + self.isSessionOpen = NO; // Session is no longer open. + + if (success) { + // Record final session flow, opting to remove it from the database if the session happens to resume. + // This is safe now that the session has closed because no new events can be added. + success = [self saveApplicationFlowAndRemoveOnResume:YES]; + } + + if (success) { + [self logMessage:@"Session succesfully closed."]; + } else { + [self logMessage:@"Failed to record session close."]; + } + } + @catch (NSException * e) {} + }); +} + +- (void)setOptIn:(BOOL)optedIn { + dispatch_async(_queue, ^{ + @try { + LocalyticsDatabase *db = [LocalyticsDatabase sharedLocalyticsDatabase]; + NSString *t = @"set_opt"; + BOOL success = [db beginTransaction:t]; + + // Write out opt event. + if (success) { + success = [self createOptEvent:optedIn]; + } + + // Update database with the option (stored internally as an opt-out). + if (success) { + [db setOptedOut:optedIn == NO]; + } + + if (success && optedIn == NO) { + // Disable all further Localytics calls for this and future sessions + // This should not be flipped when the session is opted back in because that + // would create an incomplete session. + self.isSessionOpen = NO; + } + + if (success) { + [db releaseTransaction:t]; + [self logMessage:[NSString stringWithFormat:@"Application opted %@", optedIn ? @"in" : @"out"]]; + } else { + [db rollbackTransaction:t]; + [self logMessage:@"Failed to update opt state."]; + } + } + @catch (NSException * e) {} + }); +} + +// Public interface to ll_isOptedIn. +- (BOOL)isOptedIn { + __block BOOL optedIn = YES; + dispatch_sync(_queue, ^{ + optedIn = [self ll_isOptedIn]; + }); + return optedIn; +} + +// A convenience function for users who don't wish to add attributes. +- (void)tagEvent:(NSString *)event { + [self tagEvent:event attributes:nil reportAttributes:nil]; +} + +// Most users should use this tagEvent call. +- (void)tagEvent:(NSString *)event attributes:(NSDictionary *)attributes { + [self tagEvent:event attributes:attributes reportAttributes:nil]; +} + +- (void)tagEvent:(NSString *)event attributes:(NSDictionary *)attributes reportAttributes:(NSDictionary *)reportAttributes { + dispatch_async(_queue, ^{ + @try { + // Do nothing if the session is not open. + if (self.isSessionOpen == NO) + { + [self logMessage:@"Cannot tag an event because the session is not open."]; + return; + } + + if(event == (id)[NSNull null] || event.length == 0) + { + [self logMessage:@"Event tagged without a name. Skipping."]; + return; + } + + // Create the JSON for the event + NSMutableString *eventString = [[[NSMutableString alloc] init] autorelease]; + [eventString appendString:@"{"]; + [eventString appendString:[self formatAttributeWithName:PARAM_DATA_TYPE value:@"e" first:YES] ]; + [eventString appendString:[self formatAttributeWithName:PARAM_UUID value:[self randomUUID] ]]; + [eventString appendString:[self formatAttributeWithName:PARAM_APP_KEY value:self.applicationKey ]]; + [eventString appendString:[self formatAttributeWithName:PARAM_SESSION_UUID value:self.sessionUUID ]]; + [eventString appendString:[self formatAttributeWithName:PARAM_EVENT_NAME value:[self escapeString:event] ]]; + [eventString appendFormat:@",\"%@\":%u", PARAM_CLIENT_TIME, (long)[self currentTimestamp]]; + + // Append the custom dimensions + [eventString appendString:[self customDimensions]]; + + // If there are any attributes for this event, add them as a hash + int attrIndex = 0; + if(attributes != nil) + { + // Open second level - attributes + [eventString appendString:[NSString stringWithFormat:@",\"%@\":{", PARAM_ATTRIBUTES]]; + for (id key in [attributes allKeys]) + { + // Have to escape paramName and paramValue because they user-defined. + [eventString appendString: + [self formatAttributeWithName:[self escapeString:[key description]] + value:[self escapeString:[[attributes valueForKey:key] description]] + first:(attrIndex == 0)]]; + attrIndex++; + } + + // Close second level - attributes + [eventString appendString:@"}"]; + } + + // If there are any report attributes for this event, add them as above + attrIndex = 0; + if(reportAttributes != nil) + { + [eventString appendString:[NSString stringWithFormat:@",\"%@\":{", PARAM_REPORT_ATTRIBUTES]]; + for(id key in [reportAttributes allKeys]) { + [eventString appendString: + [self formatAttributeWithName:[self escapeString:[key description]] + value:[self escapeString:[[reportAttributes valueForKey:key] description]] + first:(attrIndex == 0)]]; + attrIndex++; + } + [eventString appendString:@"}"]; + } + + // Close first level - Event information + [eventString appendString:@"}\n"]; + + BOOL success = [[LocalyticsDatabase sharedLocalyticsDatabase] addEventWithBlobString:[[eventString copy] autorelease]]; + if (success) { + // User-originated events should be tracked as application flow. + [self addFlowEventWithName:event type:@"e"]; // "e" for Event. + + [self logMessage:[@"Tagged event: " stringByAppendingString:event]]; + } else { + [self logMessage:@"Failed to tag event."]; + } + } + @catch (NSException * e) {} + }); +} + +- (void)tagScreen:(NSString *)screen { + dispatch_async(_queue, ^{ + // Do nothing if the session is not open. + if (self.isSessionOpen == NO) + { + [self logMessage:@"Cannot tag a screen because the session is not open."]; + return; + } + + // Tag screen with description to enforce string type and avoid retaining objects passed by clients in lieu of a + // screen name. + NSString *screenName = [screen description]; + [self addFlowEventWithName:screenName type:@"s"]; // "s" for Screen. + + // Maintain a parallel list of only screen names. This is submitted in the session close event. + // This may be removed in a future version of the client library. + [self addScreenWithName:screenName]; + + [self logMessage:[@"Tagged screen: " stringByAppendingString:screenName]]; + }); +} + +- (void)setCustomDimension:(int)dimension value:(NSString *)value { + dispatch_async(_queue, ^{ + if(dimension < 0 || dimension > 3) { + [self logMessage:@"Only valid dimensions are 0 - 3"]; + return; + } + + if(false == [[LocalyticsDatabase sharedLocalyticsDatabase] setCustomDimension:dimension value:value]) { + [self logMessage:@"Unable to set custom dimensions."]; + } + }); +} + +- (void)upload { + dispatch_group_async(_criticalGroup, _queue, ^{ + @try { + if ([[LocalyticsUploader sharedLocalyticsUploader] isUploading]) { + [self logMessage:@"An upload is already in progress. Aborting."]; + return; + } + + NSString *t = @"stage_upload"; + LocalyticsDatabase *db = [LocalyticsDatabase sharedLocalyticsDatabase]; + BOOL success = [db beginTransaction:t]; + + // - The event list for the current session is not modified + // New flow events are only transitioned to the "old" list if the upload is staged successfully. The queue + // ensures that the list of events are not modified while a call to upload is in progress. + if (success) { + // Write flow blob to database. This is for a session in progress and should not be removed upon resume. + success = [self saveApplicationFlowAndRemoveOnResume:NO]; + } + + if (success && [db unstagedEventCount] > 0) { + // Increment upload sequence number. + int sequenceNumber = 0; + success = [db incrementLastUploadNumber:&sequenceNumber]; + + // Write out header to database. + sqlite3_int64 headerRowId = 0; + if (success) { + NSString *headerBlob = [self blobHeaderStringWithSequenceNumber:sequenceNumber]; + success = [db addHeaderWithSequenceNumber:sequenceNumber blobString:headerBlob rowId:&headerRowId]; + } + + // Associate unstaged events. + if (success) { + success = [db stageEventsForUpload:headerRowId]; + } + } + + if (success) { + // Complete transaction + [db releaseTransaction:t]; + + // Move new flow events to the old flow event array. + if (self.unstagedFlowEvents.length) { + if (self.stagedFlowEvents.length) { + [self.stagedFlowEvents appendFormat:@",%@", self.unstagedFlowEvents]; + } else { + self.stagedFlowEvents = [[self.unstagedFlowEvents mutableCopy] autorelease]; + } + self.unstagedFlowEvents = [NSMutableString string]; + } + + // Begin upload. + [[LocalyticsUploader sharedLocalyticsUploader] uploaderWithApplicationKey:self.applicationKey]; + } else { + [db rollbackTransaction:t]; + [self logMessage:@"Failed to start upload."]; + } + } + @catch (NSException * e) { } + }); +} + +#pragma mark Private Methods + +- (void)ll_open { + // There are a number of conditions in which nothing should be done: + if (self.hasInitialized == NO || // the session object has not yet initialized + self.isSessionOpen == YES) // session has already been opened + { + [self logMessage:@"Unable to open session."]; + return; + } + + if([self ll_isOptedIn] == false) { + [self logMessage:@"Can't open session because user is opted out."]; + return; + } + + @try { + // If there is too much data on the disk, don't bother collecting any more. + LocalyticsDatabase *db = [LocalyticsDatabase sharedLocalyticsDatabase]; + if([db databaseSize] > MAX_DATABASE_SIZE) { + [self logMessage:@"Database has exceeded the maximum size. Session not opened."]; + self.isSessionOpen = NO; + return; + } + + self.sessionActiveDuration = 0; + self.sessionResumeTime = [NSDate date]; + self.unstagedFlowEvents = [NSMutableString string]; + self.stagedFlowEvents = [NSMutableString string]; + self.screens = [NSMutableString string]; + + // Begin transaction for session open. + NSString *t = @"open_session"; + BOOL success = [db beginTransaction:t]; + + // Save session start time. + self.lastSessionStartTimestamp = [self.sessionResumeTime timeIntervalSince1970]; + if (success) { + success = [db setLastsessionStartTimestamp:self.lastSessionStartTimestamp]; + } + + // Retrieve next session number. + int sessionNumber = 0; + if (success) { + success = [db incrementLastSessionNumber:&sessionNumber]; + } + + if (success) { + // Prepare session open event. + self.sessionUUID = [self randomUUID]; + + // Store event. + NSMutableString *openEventString = [NSMutableString string]; + [openEventString appendString:@"{"]; + [openEventString appendString:[self formatAttributeWithName:PARAM_DATA_TYPE value:@"s" first:YES]]; + [openEventString appendString:[self formatAttributeWithName:PARAM_NEW_SESSION_UUID value:self.sessionUUID]]; + [openEventString appendFormat:@",\"%@\":%u", PARAM_CLIENT_TIME, (long)self.lastSessionStartTimestamp]; + [openEventString appendFormat:@",\"%@\":%d", PARAM_SESSION_NUMBER, sessionNumber]; + + [openEventString appendString:[self customDimensions]]; + + [openEventString appendString:@"}\n"]; + + [self customDimensions]; + + success = [db addEventWithBlobString:[[openEventString copy] autorelease]]; + } + + if (success) { + [db releaseTransaction:t]; + self.isSessionOpen = YES; + self.sessionHasBeenOpen = YES; + [self logMessage:[@"Succesfully opened session. UUID is: " stringByAppendingString:self.sessionUUID]]; + } else { + [db rollbackTransaction:t]; + self.isSessionOpen = NO; + [self logMessage:@"Failed to open session."]; + } + } + @catch (NSException * e) {} +} + +/*! + @method reopenPreviousSession + @abstract Reopens the previous session, using previous session variables. If there was no previous session, do nothing. +*/ +- (void)reopenPreviousSession { + if(self.sessionHasBeenOpen == NO){ + [self logMessage:@"Unable to reopen previous session, because a previous session was never opened."]; + return; + } + + // Record session resume time. + self.sessionResumeTime = [NSDate date]; + + //Remove close and flow events if they exist. + [[LocalyticsDatabase sharedLocalyticsDatabase] removeLastCloseAndFlowEvents]; + + self.isSessionOpen = YES; +} + +/*! + @method addFlowEventWithName:type: + @abstract Adds a simple key-value pair to the list of events tagged during this session. + @param name The name of the tagged event. + @param eventType A key representing the type of the tagged event. Either "s" for Screen or "e" for Event. + */ +- (void)addFlowEventWithName:(NSString *)name type:(NSString *)eventType { + if (!name || !eventType) + return; + + // Format new event as simple key-value dictionary. + NSString *eventString = [self formatAttributeWithName:eventType value:[self escapeString:name] first:YES]; + + // Flow events are uploaded as a sequence of key-value pairs. Wrap the above in braces and append to the list. + BOOL previousFlowEvents = self.unstagedFlowEvents.length > 0; + if (previousFlowEvents) { + [self.unstagedFlowEvents appendString:@","]; + } + [self.unstagedFlowEvents appendFormat:@"{%@}", eventString]; +} + +/*! + @method addScreenWithName: + @abstract Adds a name to list of screens encountered during this session. + @discussion The complete list of names is sent with the session close event. Screen names are stored in parallel to the + screen flow events list and may be removed in future versions of this library. + @param name The name of the tagged screen. + */ +- (void)addScreenWithName:(NSString *)name { + if (self.screens.length > 0) { + [self.screens appendString:@","]; + } + [self.screens appendFormat:@"\"%@\"", [self escapeString:name]]; +} + +/*! + @method blobHeaderStringWithSequenceNumber: + @abstract Creates the JSON string for the upload blob header, substituting in the given upload sequence number. + @param nextSequenceNumber The sequence number for the current upload attempt. + @return The upload header JSON blob. + */ +- (NSString *)blobHeaderStringWithSequenceNumber:(int)nextSequenceNumber { + + NSMutableString *headerString = [[[NSMutableString alloc] init] autorelease]; + + // Common header information. + UIDevice *thisDevice = [UIDevice currentDevice]; + NSLocale *locale = [NSLocale currentLocale]; + NSLocale *english = [[[NSLocale alloc] initWithLocaleIdentifier: @"en_US"] autorelease]; + NSLocale *device_locale = [[NSLocale preferredLanguages] objectAtIndex:0]; + NSString *device_language = [english displayNameForKey:NSLocaleIdentifier value:device_locale]; + NSString *locale_country = [english displayNameForKey:NSLocaleCountryCode value:[locale objectForKey:NSLocaleCountryCode]]; + NSString *uuid = [self randomUUID]; + NSString *device_uuid = [self uniqueDeviceIdentifier]; + + // Open first level - blob information + [headerString appendString:@"{"]; + [headerString appendFormat:@"\"%@\":%d", PARAM_SEQUENCE_NUMBER, nextSequenceNumber]; + [headerString appendFormat:@",\"%@\":%u", PARAM_PERSISTED_AT, (long)[[LocalyticsDatabase sharedLocalyticsDatabase] createdTimestamp]]; + [headerString appendString:[self formatAttributeWithName:PARAM_DATA_TYPE value:@"h" ]]; + [headerString appendString:[self formatAttributeWithName:PARAM_UUID value:uuid ]]; + + // Open second level - blob header attributes + [headerString appendString:[NSString stringWithFormat:@",\"%@\":{", PARAM_ATTRIBUTES]]; + [headerString appendString:[self formatAttributeWithName:PARAM_DATA_TYPE value:@"a" first:YES]]; + + // >> Application and session information + [headerString appendString:[self formatAttributeWithName:PARAM_INSTALL_ID value:[self installationId] ]]; + [headerString appendString:[self formatAttributeWithName:PARAM_APP_KEY value:self.applicationKey ]]; + [headerString appendString:[self formatAttributeWithName:PARAM_APP_VERSION value:[self appVersion] ]]; + [headerString appendString:[self formatAttributeWithName:PARAM_LIBRARY_VERSION value:CLIENT_VERSION ]]; + + // >> Device Information +// [headerString appendString:[self formatAttributeWithName:PARAM_DEVICE_UUID value:device_uuid ]]; + [headerString appendString:[self formatAttributeWithName:PARAM_DEVICE_UUID_HASHED value:[self hashString:device_uuid] ]]; + [headerString appendString:[self formatAttributeWithName:PARAM_DEVICE_PLATFORM value:[thisDevice model] ]]; + [headerString appendString:[self formatAttributeWithName:PARAM_DEVICE_OS_VERSION value:[thisDevice systemVersion] ]]; + [headerString appendString:[self formatAttributeWithName:PARAM_DEVICE_MODEL value:[self deviceModel] ]]; + +// MAC Address collection. Uncomment the following line to add Mac address to the mix of collected identifiers +// [headerString appendString:[self formatAttributeWithName:PARAM_DEVICE_MAC value:[self hashString:[self macAddress]] ]]; + [headerString appendString:[NSString stringWithFormat:@",\"%@\":%d", PARAM_DEVICE_MEMORY, (long)[self availableMemory] ]]; + [headerString appendString:[self formatAttributeWithName:PARAM_LOCALE_LANGUAGE value:device_language]]; + [headerString appendString:[self formatAttributeWithName:PARAM_LOCALE_COUNTRY value:locale_country]]; + [headerString appendString:[self formatAttributeWithName:PARAM_DEVICE_COUNTRY value:[locale objectForKey:NSLocaleCountryCode]]]; + [headerString appendString:[NSString stringWithFormat:@",\"%@\":%@", PARAM_JAILBROKEN, [self isDeviceJailbroken] ? @"true" : @"false"]]; + + // Close second level - attributes + [headerString appendString:@"}"]; + + // Close first level - blob information + [headerString appendString:@"}\n"]; + + return [[headerString copy] autorelease]; +} + +- (BOOL)ll_isOptedIn { + return [[LocalyticsDatabase sharedLocalyticsDatabase] isOptedOut] == NO; +} + +/*! + @method createOptEvent: + @abstract Generates the JSON for an opt event (user opting in or out) and writes it to the database. + @return YES if the event was written to the database, NO otherwise + */ +- (BOOL)createOptEvent:(BOOL)optState { + NSMutableString *optEventString = [NSMutableString string]; + [optEventString appendString:@"{"]; + [optEventString appendString:[self formatAttributeWithName:PARAM_DATA_TYPE value:@"o" first:YES]]; + [optEventString appendString:[self formatAttributeWithName:PARAM_APP_KEY value:self.applicationKey first:NO]]; + [optEventString appendString:[NSString stringWithFormat:@",\"%@\":%@", PARAM_OPT_VALUE, (optState ? @"true" : @"false") ]]; + [optEventString appendFormat:@",\"%@\":%u", PARAM_CLIENT_TIME, (long)[self currentTimestamp]]; + [optEventString appendString:@"}\n"]; + + BOOL success = [[LocalyticsDatabase sharedLocalyticsDatabase] addEventWithBlobString:[[optEventString copy] autorelease]]; + return success; +} + +/* + @method saveApplicationFlowAndRemoveOnResume: + @abstract Constructs an application flow blob string and writes it to the database, optionally flagging it for deletion + if the session is resumed. + @param removeOnResume YES if the application flow blob should be deleted if the session is resumed. + @return YES if the application flow event was written to the database successfully. + */ +- (BOOL)saveApplicationFlowAndRemoveOnResume:(BOOL)removeOnResume { + BOOL success = YES; + + // If there are no new events, then there is nothing additional to save. + if (self.unstagedFlowEvents.length) { + // Flows are uploaded as a distinct blob type containing arrays of new and previously-uploaded event and + // screen names. Write a flow event to the database. + NSMutableString *flowEventString = [[[NSMutableString alloc] init] autorelease]; + + // Open first level - flow blob event + [flowEventString appendString:@"{"]; + [flowEventString appendString:[self formatAttributeWithName:PARAM_DATA_TYPE value:@"f" first:YES]]; + [flowEventString appendString:[self formatAttributeWithName:PARAM_UUID value:[self randomUUID] ]]; + [flowEventString appendFormat:@",\"%@\":%u", PARAM_SESSION_START, (long)self.lastSessionStartTimestamp]; + + // Open second level - new flow events + [flowEventString appendFormat:@",\"%@\":[", PARAM_NEW_FLOW_EVENTS]; + [flowEventString appendString:self.unstagedFlowEvents]; // Flow events are escaped in |-addFlowEventWithName:| + // Close second level - new flow events + [flowEventString appendString:@"]"]; + + // Open second level - old flow events + [flowEventString appendFormat:@",\"%@\":[", PARAM_OLD_FLOW_EVENTS]; + [flowEventString appendString:self.stagedFlowEvents]; + // Close second level - old flow events + [flowEventString appendString:@"]"]; + + // Close first level - flow blob event + [flowEventString appendString:@"}\n"]; + + success = [[LocalyticsDatabase sharedLocalyticsDatabase] addFlowEventWithBlobString:[[flowEventString copy] autorelease]]; + } + return success; +} + +// Convenience method for formatAttributeWithName which sets firstAttribute to NO since +// this is the most common way to call it. +- (NSString *)formatAttributeWithName:(NSString *)paramName value:(NSString *)paramValue { + return [self formatAttributeWithName:paramName value:paramValue first:NO]; +} + +/*! + @method formatAttributeWithName:value:firstAttribute: + @abstract Returns the given string key/value pair as a JSON string. + @param paramName The name of the parameter + @param paramValue The value of the parameter + @param firstAttribute YES if this attribute is first in an attribute list + @return a JSON string which can be dumped to the JSON file + */ +- (NSString *)formatAttributeWithName:(NSString *)paramName value:(NSString *)paramValue first:(BOOL)firstAttribute { + // The expected result is one of: + // "paramname":"paramvalue" + // "paramname":null + NSMutableString *formattedString = [NSMutableString string]; + if (!firstAttribute) { + [formattedString appendString:@","]; + } + + NSString *quotedString = @"\"%@\""; + paramName = [NSString stringWithFormat:quotedString, paramName]; + paramValue = paramValue ? [NSString stringWithFormat:quotedString, paramValue] : @"null"; + [formattedString appendFormat:@"%@:%@", paramName, paramValue]; + return [[formattedString copy] autorelease]; +} + +/*! + @method escapeString + @abstract Formats the input string so it fits nicely in a JSON document. This includes + escaping double quote and slash characters. + @return The escaped version of the input string + */ +- (NSString *)escapeString:(NSString *)input +{ + NSString *output = [input stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; + output = [output stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; + output = [output stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]; + return output; +} + +- (void)applicationDidEnterBackground:(NSNotification *)notification +{ + [self logMessage:@"Application entered the background."]; + + // Continue executing until critical blocks finish executing or background time runs out, whichever comes first. + UIApplication *application = (UIApplication *)[notification object]; + __block UIBackgroundTaskIdentifier taskID = [application beginBackgroundTaskWithExpirationHandler:^{ + // Synchronize with the main queue in case the the tasks finish at the same time as the expiration handler. + dispatch_async(dispatch_get_main_queue(), ^{ + if (taskID != UIBackgroundTaskInvalid) { + [self logMessage:@"Failed to finish executing critical tasks. Cleaning up."]; + [application endBackgroundTask:taskID]; + taskID = UIBackgroundTaskInvalid; + } + }); + }]; + + // Critical tasks have finished. Expire the background task. + dispatch_group_notify(_criticalGroup, dispatch_get_main_queue(), ^{ + [self logMessage:@"Finished executing critical tasks."]; + if (taskID != UIBackgroundTaskInvalid) { + [application endBackgroundTask:taskID]; + taskID = UIBackgroundTaskInvalid; + } + }); +} + +/*! + @method logMessage + @abstract Logs a message with (localytics) prepended to it. + @param message The message to log + */ +- (void)logMessage:(NSString *)message +{ + if(DO_LOCALYTICS_LOGGING) { + NSLog(@"(localytics) %s\n", [message UTF8String]); + } +} + +#pragma mark Datapoint Functions +/*! + @method customDimensions + @abstract Returns the json blob containing the custom dimensions. Assumes this will be appended + to an existing blob and as a result prepends the results with a comma. + */ +- (NSString *)customDimensions +{ + NSMutableString *dimensions = [[[NSMutableString alloc] init] autorelease]; + + for(int i=0; i <4; i++) { + NSString *dimension = [[LocalyticsDatabase sharedLocalyticsDatabase] customDimension:i]; + if(dimension) { + [dimensions appendFormat:@",\"c%i\":\"%@\"", i, dimension]; + } + } + + return [[dimensions copy] autorelease]; +} + +/*! + @method macAddress + @abstract Returns the macAddress of this device. + */ +- (NSString *)macAddress +{ + NSMutableString* result = [NSMutableString string]; + + BOOL success; + struct ifaddrs* addrs; + const struct ifaddrs* cursor; + const struct sockaddr_dl* dlAddr; + const uint8_t * base; + int i; + + success = (getifaddrs(&addrs) == 0); + if(success) + { + cursor = addrs; + while(cursor != NULL) + { + if((cursor->ifa_addr->sa_family == AF_LINK) && (((const struct sockaddr_dl *) cursor->ifa_addr)->sdl_type == IFT_ETHER)) + { + dlAddr = (const struct sockaddr_dl *) cursor->ifa_addr; + base = (const uint8_t *) &dlAddr->sdl_data[dlAddr->sdl_nlen]; + + for(i=0; isdl_alen; i++) + { + if(i != 0) { + [result appendString:@":"]; + } + [result appendFormat:@"%02x", base[i]]; + } + break; + } + cursor = cursor->ifa_next; + } + freeifaddrs(addrs); + } + + return result; +} + +/*! + @method hashString + @abstract SHA1 Hashes a string + */ +- (NSString *)hashString:(NSString *)input +{ + NSData *stringBytes = [input dataUsingEncoding: NSUTF8StringEncoding]; + unsigned char digest[CC_SHA1_DIGEST_LENGTH]; + + if (CC_SHA1([stringBytes bytes], [stringBytes length], digest)) { + NSMutableString* hashedUUID = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2]; + for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) { + [hashedUUID appendFormat:@"%02x", digest[i]]; + } + return hashedUUID; + } + + return nil; +} + +/*! + @method randomUUID + @abstract Generates a random UUID + @return NSString containing the new UUID + */ +- (NSString *)randomUUID { + CFUUIDRef theUUID = CFUUIDCreate(NULL); + CFStringRef stringUUID = CFUUIDCreateString(NULL, theUUID); + CFRelease(theUUID); + return [(NSString *)stringUUID autorelease]; +} + +/*! + @method installationId + @abstract Looks in user preferences for an ID unique to this installation. If one is not + found it checks if one happens to be in the database (carroyover from older version of the db) + if not, it generates one. + @return A string uniquely identifying this installation of this app + */ +- (NSString *) installationId { + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + NSString *installId = [prefs stringForKey:PREFERENCES_KEY]; + + if(installId == nil) + { + [self logMessage:@"Install ID not found in preferences, checking DB"]; + installId = [[LocalyticsDatabase sharedLocalyticsDatabase] installId]; + } + + // If it hasn't been found yet, generate a new one. + if(installId == nil) + { + [self logMessage:@"Install ID not find one in database, generating a new one."]; + installId = [self randomUUID]; + } + + // Store the newly generated installId + [prefs setObject:installId forKey:PREFERENCES_KEY]; + [[NSUserDefaults standardUserDefaults] synchronize]; + + return installId; +} + +/*! + @method uniqueDeviceIdentifier + @abstract A unique device identifier is a hash value composed from various hardware identifiers such + as the device’s serial number. It is guaranteed to be unique for every device but cannot + be tied to a user account. [UIDevice Class Reference] + @return An 1-way hashed identifier unique to this device. + */ +- (NSString *)uniqueDeviceIdentifier { + +// Supress the warning for uniqueIdentifier being deprecated. +// We collect it as long as it is available along with a randomly generated ID. +// This way, when this becomes unavailable we can map existing users so the +// new vs returning counts do not break. This will be removed before it causes grief. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSString *systemId = [[UIDevice currentDevice] uniqueIdentifier]; +#pragma clang diagnostic pop + + return systemId; +} + +/*! + @method appVersion + @abstract Gets the pretty string for this application's version. + @return The application's version as a pretty string + */ +- (NSString *)appVersion { + return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]; +} + +/*! + @method currentTimestamp + @abstract Gets the current time as seconds since Unix epoch. + @return an NSTimeInterval time. + */ +- (NSTimeInterval)currentTimestamp { + return [[NSDate date] timeIntervalSince1970]; +} + +/*! + @method isDeviceJailbroken + @abstract checks for the existance of apt to determine whether the user is running any + of the jailbroken app sources. + @return whether or not the device is jailbroken. + */ +- (BOOL) isDeviceJailbroken { + NSFileManager *sessionFileManager = [NSFileManager defaultManager]; + return [sessionFileManager fileExistsAtPath:PATH_TO_APT]; +} + +/*! + @method deviceModel + @abstract Gets the device model string. + @return a platform string identifying the device + */ +- (NSString *)deviceModel { + char *buffer[256] = { 0 }; + size_t size = sizeof(buffer); + sysctlbyname("hw.machine", buffer, &size, NULL, 0); + NSString *platform = [NSString stringWithCString:(const char*)buffer + encoding:NSUTF8StringEncoding]; + return platform; +} + +/*! + @method modelSizeString + @abstract Checks how much disk space is reported and uses that to determine the model + @return A string identifying the model, e.g. 8GB, 16GB, etc + */ +- (NSString *) modelSizeString { + +#if TARGET_IPHONE_SIMULATOR + return @"simulator"; +#endif + + // User partition + NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSDictionary *stats = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[path lastObject] error:nil]; + uint64_t user = [[stats objectForKey:NSFileSystemSize] longLongValue]; + + // System partition + path = NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSSystemDomainMask, YES); + stats = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[path lastObject] error:nil]; + uint64_t system = [[stats objectForKey:NSFileSystemSize] longLongValue]; + + // Add up and convert to gigabytes + // TODO: seem to be missing a system partiton or two... + NSInteger size = (user + system) >> 30; + + // Find nearest power of 2 (eg, 1,2,4,8,16,32,etc). Over 64 and we return 0 + for (NSInteger gig = 1; gig < 257; gig = gig << 1) { + if (size < gig) + return [NSString stringWithFormat:@"%dGB", gig]; + } + return nil; +} + +/*! + @method availableMemory + @abstract Reports how much memory is available + @return A double containing the available free memory + */ +- (double)availableMemory { + double result = NSNotFound; + vm_statistics_data_t stats; + mach_msg_type_number_t count = HOST_VM_INFO_COUNT; + if (!host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&stats, &count)) + result = vm_page_size * stats.free_count; + + return result; +} + + +#pragma mark System Functions ++ (id)allocWithZone:(NSZone *)zone { + @synchronized(self) { + if (_sharedLocalyticsSession == nil) { + _sharedLocalyticsSession = [super allocWithZone:zone]; + return _sharedLocalyticsSession; + } + } + // returns nil on subsequent allocations + return nil; +} + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + +- (id)retain { + return self; +} + +- (unsigned)retainCount { + // maximum value of an unsigned int - prevents additional retains for the class + return UINT_MAX; +} + +- (oneway void)release { + // ignore release commands +} + +- (id)autorelease { + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; + + dispatch_release(_criticalGroup); + dispatch_release(_queue); + [_sessionUUID release]; + [_applicationKey release]; + [_sessionCloseTime release]; + [_unstagedFlowEvents release]; + [_stagedFlowEvents release]; + [_screens release]; + [_sharedLocalyticsSession release]; + + [super dealloc]; +} + +@end diff --git a/Localytics/LocalyticsUploader.h b/Localytics/LocalyticsUploader.h new file mode 100644 index 00000000..2d6b867e --- /dev/null +++ b/Localytics/LocalyticsUploader.h @@ -0,0 +1,42 @@ +// LocalyticsUploader.h +// Copyright (C) 2009 Char Software Inc., DBA Localytics +// +// This code is provided under the Localytics Modified BSD License. +// A copy of this license has been distributed in a file called LICENSE +// with this source code. +// +// Please visit www.localytics.com for more information. + +#import + +/*! + @class LocalyticsUploader + @discussion Singleton class to handle data uploads + */ + +@interface LocalyticsUploader : NSObject { +} + +@property (readonly) BOOL isUploading; + +/*! + @method sharedLocalyticsUploader + @abstract Establishes this as a Singleton Class allowing for data persistence. + The class is accessed within the code using the following syntax: + [[LocalyticsUploader sharedLocalyticsUploader] functionHere] + */ ++ (LocalyticsUploader *)sharedLocalyticsUploader; + +/*! + @method LocalyticsUploader + @abstract Creates a thread which uploads all queued header and event data. + All files starting with sessionFilePrefix are renamed, + uploaded and deleted on upload. This way the sessions can continue + writing data regardless of whether or not the upload succeeds. Files + which have been renamed still count towards the total number of Localytics + files which can be stored on the disk. + @param localyticsApplicationKey the Localytics application ID + */ +- (void)uploaderWithApplicationKey:(NSString *)localyticsApplicationKey; + +@end \ No newline at end of file diff --git a/Localytics/LocalyticsUploader.m b/Localytics/LocalyticsUploader.m new file mode 100644 index 00000000..251c8f97 --- /dev/null +++ b/Localytics/LocalyticsUploader.m @@ -0,0 +1,236 @@ +// LocalyticsUploader.m +// Copyright (C) 2009 Char Software Inc., DBA Localytics +// +// This code is provided under the Localytics Modified BSD License. +// A copy of this license has been distributed in a file called LICENSE +// with this source code. +// +// Please visit www.localytics.com for more information. + +#import "LocalyticsUploader.h" +#import "LocalyticsSession.h" +#import "LocalyticsDatabase.h" +#import + +#define LOCALYTICS_URL @"http://analytics.localytics.com/api/v2/applications/%@/uploads" + +static LocalyticsUploader *_sharedUploader = nil; + +@interface LocalyticsUploader () +- (void)finishUpload; +- (NSData *)gzipDeflatedDataWithData:(NSData *)data; +- (void)logMessage:(NSString *)message; + +@property (readwrite) BOOL isUploading; + +@end + +@implementation LocalyticsUploader +@synthesize isUploading = _isUploading; + +#pragma mark - Singleton Class ++ (LocalyticsUploader *)sharedLocalyticsUploader { + @synchronized(self) { + if (_sharedUploader == nil) { + _sharedUploader = [[self alloc] init]; + } + } + return _sharedUploader; +} + +#pragma mark - Class Methods + +- (void)uploaderWithApplicationKey:(NSString *)localyticsApplicationKey { + + // Do nothing if already uploading. + if (self.isUploading == true) + { + [self logMessage:@"Upload already in progress. Aborting."]; + return; + } + + [self logMessage:@"Beginning upload process"]; + self.isUploading = true; + + // Prepare the data for upload. The upload could take a long time, so some effort has to be made to be sure that events + // which get written while the upload is taking place don't get lost or duplicated. To achieve this, the logic is: + // 1) Append every header row blob string and and those of its associated events to the upload string. + // 2) Deflate and upload the data. + // 3) On success, delete all blob headers and staged events. Events added while an upload is in process are not + // deleted because they are not associated a header (and cannot be until the upload completes). + + // Step 1 + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + LocalyticsDatabase *db = [LocalyticsDatabase sharedLocalyticsDatabase]; + NSString *blobString = [db uploadBlobString]; + + if ([blobString length] == 0) { + // There is nothing outstanding to upload. + [self logMessage:@"Abandoning upload. There are no new events."]; + [pool drain]; + [self finishUpload]; + + return; + } + + NSData *requestData = [blobString dataUsingEncoding:NSUTF8StringEncoding]; + NSString *myString = [[[NSString alloc] initWithData:requestData encoding:NSUTF8StringEncoding] autorelease]; + [self logMessage:[NSString stringWithFormat:@"Uploading data (length: %u)", [myString length]]]; + + // Step 2 + NSData *deflatedRequestData = [[self gzipDeflatedDataWithData:requestData] retain]; + + [pool drain]; + + NSString *apiUrlString = [NSString stringWithFormat:LOCALYTICS_URL, [localyticsApplicationKey stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + NSMutableURLRequest *submitRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:apiUrlString] + cachePolicy:NSURLRequestReloadIgnoringCacheData + timeoutInterval:60.0]; + [submitRequest setHTTPMethod:@"POST"]; + [submitRequest setValue:@"application/x-gzip" forHTTPHeaderField:@"Content-Type"]; + [submitRequest setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"]; + [submitRequest setValue:[NSString stringWithFormat:@"%d", [deflatedRequestData length]] forHTTPHeaderField:@"Content-Length"]; + [submitRequest setHTTPBody:deflatedRequestData]; + [deflatedRequestData release]; + + // Perform synchronous upload in an async dispatch. This is necessary because the calling block will not persist to + // receive the response data. + dispatch_group_async([[LocalyticsSession sharedLocalyticsSession] criticalGroup], [[LocalyticsSession sharedLocalyticsSession] queue], ^{ + @try { + NSURLResponse *response = nil; + NSError *responseError = nil; + [NSURLConnection sendSynchronousRequest:submitRequest returningResponse:&response error:&responseError]; + NSInteger responseStatusCode = [(NSHTTPURLResponse *)response statusCode]; + + if (responseError) { + // On error, simply print the error and close the uploader. We have to assume the data was not transmited + // so it is not deleted. In the event that we accidently store data which was succesfully uploaded, the + // duplicate data will be ignored by the server when it is next uploaded. + [self logMessage:[NSString stringWithFormat: + @"Error Uploading. Code: %d, Description: %@", + [responseError code], + [responseError localizedDescription]]]; + } else { + // Step 3 + // While response status codes in the 5xx range leave upload rows intact, the default case is to delete. + if (responseStatusCode >= 500 && responseStatusCode < 600) { + [self logMessage:[NSString stringWithFormat:@"Upload failed with response status code %d", responseStatusCode]]; + } else { + // Because only one instance of the uploader can be running at a time it should not be possible for + // new upload rows to appear so there is no fear of deleting data which has not yet been uploaded. + [self logMessage:[NSString stringWithFormat:@"Upload completed successfully. Response code %d", responseStatusCode]]; + [[LocalyticsDatabase sharedLocalyticsDatabase] deleteUploadedData]; + } + } + } + @catch (NSException * e) {} + + [self finishUpload]; + }); +} + +- (void)finishUpload +{ + self.isUploading = false; + + // Upload data has been deleted. Recover the disk space if necessary. + [[LocalyticsDatabase sharedLocalyticsDatabase] vacuumIfRequired]; +} + +/*! + @method gzipDeflatedDataWithData + @abstract Deflates the provided data using gzip at the default compression level (6). Complete NSData gzip category available on CocoaDev. http://www.cocoadev.com/index.pl?NSDataCategory. + @return the deflated data + */ +- (NSData *)gzipDeflatedDataWithData:(NSData *)data +{ + if ([data length] == 0) return data; + + z_stream strm; + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.total_out = 0; + strm.next_in=(Bytef *)[data bytes]; + strm.avail_in = [data length]; + + // Compresssion Levels: + // Z_NO_COMPRESSION + // Z_BEST_SPEED + // Z_BEST_COMPRESSION + // Z_DEFAULT_COMPRESSION + + if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY) != Z_OK) return nil; + + NSMutableData *compressed = [NSMutableData dataWithLength:16384]; // 16K chunks for expansion + + do { + + if (strm.total_out >= [compressed length]) + [compressed increaseLengthBy: 16384]; + + strm.next_out = [compressed mutableBytes] + strm.total_out; + strm.avail_out = [compressed length] - strm.total_out; + + deflate(&strm, Z_FINISH); + + } while (strm.avail_out == 0); + + deflateEnd(&strm); + + [compressed setLength: strm.total_out]; + return [NSData dataWithData:compressed]; +} + +/*! + @method logMessage + @abstract Logs a message with (localytics uploader) prepended to it + @param message The message to log + */ +- (void) logMessage:(NSString *)message { + if(DO_LOCALYTICS_LOGGING) { + NSLog(@"(localytics uploader) %s\n", [message UTF8String]); + } +} + +#pragma mark - System Functions ++ (id)allocWithZone:(NSZone *)zone { + @synchronized(self) { + if (_sharedUploader == nil) { + _sharedUploader = [super allocWithZone:zone]; + return _sharedUploader; + } + } + // returns nil on subsequent allocations + return nil; +} + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + +- (id)retain { + return self; +} + +- (unsigned)retainCount { + // maximum value of an unsigned int - prevents additional retains for the class + return UINT_MAX; +} + +- (oneway void)release { + // ignore release commands +} + +- (id)autorelease { + return self; +} + +- (void)dealloc { + [_sharedUploader release]; + [super dealloc]; +} + +@end diff --git a/Localytics/UploaderThread.h b/Localytics/UploaderThread.h new file mode 100644 index 00000000..0b59c5a4 --- /dev/null +++ b/Localytics/UploaderThread.h @@ -0,0 +1,48 @@ +// UploaderThread.h +// Copyright (C) 2009 Char Software Inc., DBA Localytics +// +// This code is provided under the Localytics Modified BSD License. +// A copy of this license has been distributed in a file called LICENSE +// with this source code. +// +// Please visit www.localytics.com for more information. + +#import + +/*! + @class UploaderThread + @discussion Singleton class to handle data uploads + */ + +@interface UploaderThread : NSObject { + NSURLConnection *_uploadConnection; // The connection which uploads the bits + NSInteger _responseStatusCode; // The HTTP response status code for the current connection + + BOOL _isUploading; // A flag to gaurantee only one uploader instance can happen at once +} + +@property (nonatomic, retain) NSURLConnection *uploadConnection; + +@property BOOL isUploading; + +/*! + @method sharedUploaderThread + @abstract Establishes this as a Singleton Class allowing for data persistence. + The class is accessed within the code using the following syntax: + [[UploaderThread sharedUploaderThread] functionHere] + */ ++ (UploaderThread *)sharedUploaderThread; + +/*! + @method UploaderThread + @abstract Creates a thread which uploads all queued header and event data. + All files starting with sessionFilePrefix are renamed, + uploaded and deleted on upload. This way the sessions can continue + writing data regardless of whether or not the upload succeeds. Files + which have been renamed still count towards the total number of Localytics + files which can be stored on the disk. + @param localyticsApplicationKey the Localytics application ID + */ +- (void)uploaderThreadwithApplicationKey:(NSString *)localyticsApplicationKey; + +@end \ No newline at end of file diff --git a/Localytics/UploaderThread.m b/Localytics/UploaderThread.m new file mode 100644 index 00000000..3c04c127 --- /dev/null +++ b/Localytics/UploaderThread.m @@ -0,0 +1,260 @@ +// UploaderThread.m +// Copyright (C) 2009 Char Software Inc., DBA Localytics +// +// This code is provided under the Localytics Modified BSD License. +// A copy of this license has been distributed in a file called LICENSE +// with this source code. +// +// Please visit www.localytics.com for more information. + +#import "UploaderThread.h" +#import "LocalyticsSession.h" +#import "LocalyticsDatabase.h" +#import + +#define LOCALYTICS_URL @"http://analytics.localytics.com/api/v2/applications/%@/uploads" // url to send the + +static UploaderThread *_sharedUploaderThread = nil; + +@interface UploaderThread () +- (void)complete; +- (NSData *)gzipDeflatedDataWithData:(NSData *)data; +- (void)logMessage:(NSString *)message; +@end + +@implementation UploaderThread + +@synthesize uploadConnection = _uploadConnection; +@synthesize isUploading = _isUploading; + +#pragma mark Singleton Class ++ (UploaderThread *)sharedUploaderThread { + @synchronized(self) { + if (_sharedUploaderThread == nil) + { + _sharedUploaderThread = [[self alloc] init]; + } + } + return _sharedUploaderThread; +} + +#pragma mark Class Methods +- (void)uploaderThreadwithApplicationKey:(NSString *)localyticsApplicationKey { + + // Do nothing if already uploading. + if (self.uploadConnection != nil || self.isUploading == true) + { + [self logMessage:@"Upload already in progress. Aborting."]; + return; + } + + [self logMessage:@"Beginning upload process"]; + self.isUploading = true; + + // Prepare the data for upload. The upload could take a long time, so some effort has to be made to be sure that events + // which get written while the upload is taking place don't get lost or duplicated. To achieve this, the logic is: + // 1) Append every header row blob string and and those of its associated events to the upload string. + // 2) Deflate and upload the data. + // 3) On success, delete all blob headers and staged events. Events added while an upload is in process are not + // deleted because they are not associated a header (and cannot be until the upload completes). + + // Step 1 + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + LocalyticsDatabase *db = [LocalyticsDatabase sharedLocalyticsDatabase]; + NSString *blobString = [db uploadBlobString]; + + if ([blobString length] == 0) { + // There is nothing outstanding to upload. + [self logMessage:@"Abandoning upload. There are no new events."]; + + [pool drain]; + [self complete]; + return; + } + + NSData *requestData = [blobString dataUsingEncoding:NSUTF8StringEncoding]; + NSString *myString = [[[NSString alloc] initWithData:requestData encoding:NSUTF8StringEncoding] autorelease]; + [self logMessage:@"Upload data:"]; + [self logMessage:myString]; + + // Step 2 + NSData *deflatedRequestData = [[self gzipDeflatedDataWithData:requestData] retain]; + + [pool drain]; + + NSString *apiUrlString = [NSString stringWithFormat:LOCALYTICS_URL, [localyticsApplicationKey stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + NSMutableURLRequest *submitRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:apiUrlString] + cachePolicy:NSURLRequestReloadIgnoringCacheData + timeoutInterval:60.0]; + [submitRequest setHTTPMethod:@"POST"]; + [submitRequest setValue:@"application/x-gzip" forHTTPHeaderField:@"Content-Type"]; + [submitRequest setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"]; + [submitRequest setValue:[NSString stringWithFormat:@"%d", [deflatedRequestData length]] forHTTPHeaderField:@"Content-Length"]; + [submitRequest setHTTPBody:deflatedRequestData]; + [deflatedRequestData release]; + + // The NSURLConnection Object automatically spawns its own thread as a default behavior. + @try + { + [self logMessage:@"Spawning new thread for upload"]; + self.uploadConnection = [NSURLConnection connectionWithRequest:submitRequest delegate:self]; + + // Step 3 is handled by connectionDidFinishLoading. + } + @catch (NSException * e) + { + [self complete]; + } +} + +#pragma mark **** NSURLConnection FUNCTIONS **** + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { + // Used to gather response data from server - Not utilized in this version +} + +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { + // Could receive multiple response callbacks, likely due to redirection. + // Record status and act only when connection completes load. + _responseStatusCode = [(NSHTTPURLResponse *)response statusCode]; +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection { + // If the connection finished loading, the files should be deleted. While response status codes in the 5xx range + // leave upload rows intact, the default case is to delete. + if (_responseStatusCode >= 500 && _responseStatusCode < 600) + { + [self logMessage:[NSString stringWithFormat:@"Upload failed with response status code %d", _responseStatusCode]]; + } else + { + // The connection finished loading and uploaded data should be deleted. Because only one instance of the + // uploader can be running at a time it should not be possible for new upload rows to appear so there is no + // fear of deleting data which has not yet been uploaded. + [self logMessage:[NSString stringWithFormat:@"Upload completed successfully. Response code %d", _responseStatusCode]]; + [[LocalyticsDatabase sharedLocalyticsDatabase] deleteUploadData]; + } + + // Close upload session + [self complete]; +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { + // On error, simply print the error and close the uploader. We have to assume the data was not transmited + // so it is not deleted. In the event that we accidently store data which was succesfully uploaded, the + // duplicate data will be ignored by the server when it is next uploaded. + [self logMessage:[NSString stringWithFormat: + @"Error Uploading. Code: %d, Description: %s", + [error code], + [error localizedDescription]]]; + + [self complete]; +} + +/*! + @method complete + @abstract closes the upload connection and reports back to the session that the upload is complete + */ +- (void)complete { + _responseStatusCode = 0; + self.uploadConnection = nil; + self.isUploading = false; +} + +/*! + @method gzipDeflatedDataWithData + @abstract Deflates the provided data using gzip at the default compression level (6). Complete NSData gzip category available on CocoaDev. http://www.cocoadev.com/index.pl?NSDataCategory. + @return the deflated data + */ +- (NSData *)gzipDeflatedDataWithData:(NSData *)data +{ + if ([data length] == 0) return data; + + z_stream strm; + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.total_out = 0; + strm.next_in=(Bytef *)[data bytes]; + strm.avail_in = [data length]; + + // Compresssion Levels: + // Z_NO_COMPRESSION + // Z_BEST_SPEED + // Z_BEST_COMPRESSION + // Z_DEFAULT_COMPRESSION + + if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY) != Z_OK) return nil; + + NSMutableData *compressed = [NSMutableData dataWithLength:16384]; // 16K chunks for expansion + + do { + + if (strm.total_out >= [compressed length]) + [compressed increaseLengthBy: 16384]; + + strm.next_out = [compressed mutableBytes] + strm.total_out; + strm.avail_out = [compressed length] - strm.total_out; + + deflate(&strm, Z_FINISH); + + } while (strm.avail_out == 0); + + deflateEnd(&strm); + + [compressed setLength: strm.total_out]; + return [NSData dataWithData:compressed]; +} + +/*! + @method logMessage + @abstract Logs a message with (localytics uploader) prepended to it + @param message The message to log +*/ +- (void) logMessage:(NSString *)message { + if(DO_LOCALYTICS_LOGGING) { + NSLog(@"(localytics uploader) %s\n", [message UTF8String]); + } +} + +#pragma mark System Functions ++ (id)allocWithZone:(NSZone *)zone { + @synchronized(self) { + if (_sharedUploaderThread == nil) { + _sharedUploaderThread = [super allocWithZone:zone]; + return _sharedUploaderThread; + } + } + // returns nil on subsequent allocations + return nil; +} + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + +- (id)retain { + return self; +} + +- (unsigned)retainCount { + // maximum value of an unsigned int - prevents additional retains for the class + return UINT_MAX; +} + +- (oneway void)release { + // ignore release commands +} + +- (id)autorelease { + return self; +} + +- (void)dealloc { + [_uploadConnection release]; + [_sharedUploaderThread release]; + [super dealloc]; +} + +@end diff --git a/Localytics/WebserviceConstants.h b/Localytics/WebserviceConstants.h new file mode 100644 index 00000000..fafdf88f --- /dev/null +++ b/Localytics/WebserviceConstants.h @@ -0,0 +1,111 @@ +// WebserviceConstants.h +// Copyright (C) 2009 Char Software Inc., DBA Localytics +// +// This code is provided under the Localytics Modified BSD License. +// A copy of this license has been distributed in a file called LICENSE +// with this source code. +// +// Please visit www.localytics.com for more information. + +// The constants which are used to make up the JSON blob +// To save disk space and network bandwidth all the keywords have been +// abbreviated and are exploded by the server. + +/********************* + * Shared Attributes * + *********************/ +#define PARAM_UUID @"u" // UUID for JSON document +#define PARAM_DATA_TYPE @"dt" // Data Type +#define PARAM_CLIENT_TIME @"ct" // Client Time, seconds from Unix epoch (int) +#define PARAM_LATITUDE @"lat" // Latitude - if available +#define PARAM_LONGITUDE @"lon" // Longitude - if available +#define PARAM_SESSION_UUID @"su" // UUID for an existing session +#define PARAM_NEW_SESSION_UUID @"u" // UUID for a new session +#define PARAM_ATTRIBUTES @"attrs" // Attributes (dictionary) + +/*************** + * Blob Header * + ***************/ + +// PARAM_UUID +// PARAM_DATA_TYPE => "h" for Header +// PARAM_ATTRIBUTES => dictionary containing Header Common Attributes +#define PARAM_PERSISTED_AT @"pa" // Persistent Storage Created At. A timestamp created when the app was + // first launched and the persistent storage was created. Stores as + // seconds from Unix epoch. (int) +#define PARAM_SEQUENCE_NUMBER @"seq" // Sequence number - an increasing count for each blob, stored in the + // persistent store Consistent across app starts. (int) + +/**************************** + * Header Common Attributes * + ****************************/ + +// PARAM_DATA_TYPE +#define PARAM_APP_KEY @"au" // Localytics Application ID +#define PARAM_DEVICE_UUID @"du" // Device UUID +#define PARAM_DEVICE_UUID_HASHED @"udid" // Hashed version of the UUID +#define PARAM_DEVICE_MAC @"wmac" // Hashed version of the device Mac +#define PARAM_INSTALL_ID @"iu" // Install ID +#define PARAM_JAILBROKEN @"j" // Jailbroken (boolean) +#define PARAM_LIBRARY_VERSION @"lv" // Client Version +#define PARAM_APP_VERSION @"av" // Application Version +#define PARAM_DEVICE_PLATFORM @"dp" // Device Platform +#define PARAM_LOCALE_LANGUAGE @"dll" // Locale Language +#define PARAM_LOCALE_COUNTRY @"dlc" // Locale Country +#define PARAM_NETWORK_COUNTRY @"nc" // Network Country (iso code) // ???: Never used on iPhone. +#define PARAM_DEVICE_COUNTRY @"dc" // Device Country (iso code) +#define PARAM_DEVICE_MANUFACTURER @"dma" // Device Manufacturer // ???: Never used on iPhone. Used to be "Device Make". +#define PARAM_DEVICE_MODEL @"dmo" // Device Model +#define PARAM_DEVICE_OS_VERSION @"dov" // Device OS Version +#define PARAM_NETWORK_CARRIER @"nca" // Network Carrier +#define PARAM_DATA_CONNECTION @"dac" // Data Connection Type // ???: Never used on iPhone. +#define PARAM_OPT_VALUE @"optin" // Opt In (boolean) +#define PARAM_DEVICE_MEMORY @"dmem" // Device Memory + +/***************** + * Session Start * + *****************/ + +// PARAM_UUID +// PARAM_DATA_TYPE => "s" for Start +// PARAM_CLIENT_TIME +#define PARAM_SESSION_NUMBER @"nth" // This is the nth session on the device, 1-indexed (int) + +/**************** + * Session Stop * + ****************/ + +// PARAM_UUID +// PARAM_DATA_TYPE => "c" for Close +// PARAM_CLIENT_TIME +// PARAM_LATITUDE +// PARAM_LONGITUDE +// PARAM_SESSION_UUID => UUID of session being closed +#define PARAM_SESSION_ACTIVE @"cta" // Active time in seconds (time app was active) +#define PARAM_SESSION_TOTAL @"ctl" // Total session length +#define PARAM_SESSION_SCREENFLOW @"fl" // Screens encountered during this session, in order + +/********************* + * Application Event * + *********************/ + +// PARAM_UUID +// PARAM_DATA_TYPE => "e" for Event +// PARAM_CLIENT_TIME +// PARAM_LATITUDE +// PARAM_LONGITUDE +// PARAM_SESSION_UUID => UUID of session event occured in +// PARAM_ATTRIBUTES => dictionary containing attributes for this event as key-value string pairs +#define PARAM_EVENT_NAME @"n" // Event Name, (eg. 'Button Click') +#define PARAM_REPORT_ATTRIBUTES @"rattrs" // Attributes used in custom reports + +/******************** + * Application flow * + ********************/ + +// PARAM_UUID +// PARAM_DATA_TYPE => "f" for Flow +// PARAM_CLIENT_TIME +#define PARAM_SESSION_START @"ss" // Start time for the current session. +#define PARAM_NEW_FLOW_EVENTS @"nw" // Events and screens encountered during this session that have NOT been staged for upload. +#define PARAM_OLD_FLOW_EVENTS @"od" // Events and screens encountered during this session that HAVE been staged for upload. \ No newline at end of file diff --git a/MasterPassword-iOS.xcodeproj/project.pbxproj b/MasterPassword-iOS.xcodeproj/project.pbxproj index 6b130164..bdf791cc 100644 --- a/MasterPassword-iOS.xcodeproj/project.pbxproj +++ b/MasterPassword-iOS.xcodeproj/project.pbxproj @@ -56,7 +56,6 @@ DA95D5F614DF0B9F008D1B94 /* IASKPSTextFieldSpecifierViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA95D5CC14DF0691008D1B94 /* IASKPSTextFieldSpecifierViewCell.xib */; }; DA95D5F714DF0B9F008D1B94 /* IASKPSToggleSwitchSpecifierViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA95D5CD14DF0691008D1B94 /* IASKPSToggleSwitchSpecifierViewCell.xib */; }; DA95D5F814DF0B9F008D1B94 /* IASKSpecifierValuesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA95D5CE14DF0691008D1B94 /* IASKSpecifierValuesView.xib */; }; - DA95D60614DF3E67008D1B94 /* libTestFlight.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA95D60114DF3E67008D1B94 /* libTestFlight.a */; }; DAB8D45D15036BCF00CED3BC /* MasterPassword.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DAB8D43C15036BCF00CED3BC /* MasterPassword.xcdatamodeld */; }; DAB8D45E15036BCF00CED3BC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = DAB8D43F15036BCF00CED3BC /* InfoPlist.strings */; }; DAB8D45F15036BCF00CED3BC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DAB8D44115036BCF00CED3BC /* main.m */; }; @@ -712,9 +711,6 @@ DAB8D97A15036BF700CED3BC /* tip_location_wood.png in Resources */ = {isa = PBXBuildFile; fileRef = DAB8D6F815036BF600CED3BC /* tip_location_wood.png */; }; DAB8D97B15036BF700CED3BC /* tip_location_wood@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DAB8D6F915036BF600CED3BC /* tip_location_wood@2x.png */; }; DAB8D97C1503718B00CED3BC /* jquery-1.6.1.min.js in Resources */ = {isa = PBXBuildFile; fileRef = DAB8D6AB15036BF600CED3BC /* jquery-1.6.1.min.js */; }; - DABB9809150FF40100B05417 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; }; - DABB980F150FF40100B05417 /* SendToMac.m in Sources */ = {isa = PBXBuildFile; fileRef = DABB980E150FF40100B05417 /* SendToMac.m */; }; - DABB9814150FF5C100B05417 /* libSendToMac.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DABB9808150FF40100B05417 /* libSendToMac.a */; }; DABB981615100B4000B05417 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DABB981515100B4000B05417 /* SystemConfiguration.framework */; }; DAC6325E1486805C0075AEA5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; }; DAC6326D148680650075AEA5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; }; @@ -722,10 +718,29 @@ DAC63278148680740075AEA5 /* libjrswizzle.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC6326C148680650075AEA5 /* libjrswizzle.a */; }; DAC6327B1486809A0075AEA5 /* JRSwizzle.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC632791486809A0075AEA5 /* JRSwizzle.h */; }; DAC6327C1486809A0075AEA5 /* JRSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = DAC6327A1486809A0075AEA5 /* JRSwizzle.m */; }; - DAC6327F148680B10075AEA5 /* UIColor-Expanded.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC6327D148680B10075AEA5 /* UIColor-Expanded.h */; }; - DAC63280148680B10075AEA5 /* UIColor-Expanded.m in Sources */ = {isa = PBXBuildFile; fileRef = DAC6327E148680B10075AEA5 /* UIColor-Expanded.m */; }; DAC632891486D9690075AEA5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC632871486D95D0075AEA5 /* Security.framework */; }; DAC77CAE148291A600BCF976 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; }; + DAD3126715528C9C00A3F9ED /* Crashlytics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAD3125F15528C9C00A3F9ED /* Crashlytics.framework */; }; + DAD3126815528C9C00A3F9ED /* Crashlytics.plist in Resources */ = {isa = PBXBuildFile; fileRef = DAD3126015528C9C00A3F9ED /* Crashlytics.plist */; }; + DAD3126915528C9C00A3F9ED /* libTestFlight.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAD3126215528C9C00A3F9ED /* libTestFlight.a */; }; + DAD3126C15528C9C00A3F9ED /* TestFlight.plist in Resources */ = {isa = PBXBuildFile; fileRef = DAD3126615528C9C00A3F9ED /* TestFlight.plist */; }; + DAD3127215528CD200A3F9ED /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; }; + DAD3128715528D0F00A3F9ED /* LocalyticsDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = DAD3127E15528D0F00A3F9ED /* LocalyticsDatabase.h */; }; + DAD3128815528D0F00A3F9ED /* LocalyticsDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD3127F15528D0F00A3F9ED /* LocalyticsDatabase.m */; }; + DAD3128915528D0F00A3F9ED /* LocalyticsSession.h in Headers */ = {isa = PBXBuildFile; fileRef = DAD3128015528D0F00A3F9ED /* LocalyticsSession.h */; }; + DAD3128A15528D0F00A3F9ED /* LocalyticsSession.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD3128115528D0F00A3F9ED /* LocalyticsSession.m */; }; + DAD3128B15528D0F00A3F9ED /* LocalyticsUploader.h in Headers */ = {isa = PBXBuildFile; fileRef = DAD3128215528D0F00A3F9ED /* LocalyticsUploader.h */; }; + DAD3128C15528D0F00A3F9ED /* LocalyticsUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD3128315528D0F00A3F9ED /* LocalyticsUploader.m */; }; + DAD3128D15528D0F00A3F9ED /* UploaderThread.h in Headers */ = {isa = PBXBuildFile; fileRef = DAD3128415528D0F00A3F9ED /* UploaderThread.h */; }; + DAD3128E15528D0F00A3F9ED /* UploaderThread.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD3128515528D0F00A3F9ED /* UploaderThread.m */; }; + DAD3128F15528D0F00A3F9ED /* WebserviceConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = DAD3128615528D0F00A3F9ED /* WebserviceConstants.h */; }; + DAD3129015528D1600A3F9ED /* Localytics.plist in Resources */ = {isa = PBXBuildFile; fileRef = DAD3127D15528D0F00A3F9ED /* Localytics.plist */; }; + DAD312BB1552977200A3F9ED /* UIColor+Expanded.h in Headers */ = {isa = PBXBuildFile; fileRef = DAD312B71552977200A3F9ED /* UIColor+Expanded.h */; }; + DAD312BC1552977200A3F9ED /* UIColor+Expanded.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD312B81552977200A3F9ED /* UIColor+Expanded.m */; }; + DAD312BD1552977200A3F9ED /* UIColor+HSV.h in Headers */ = {isa = PBXBuildFile; fileRef = DAD312B91552977200A3F9ED /* UIColor+HSV.h */; }; + DAD312BE1552977200A3F9ED /* UIColor+HSV.m in Sources */ = {isa = PBXBuildFile; fileRef = DAD312BA1552977200A3F9ED /* UIColor+HSV.m */; }; + DAD312BF1552A1BD00A3F9ED /* libLocalytics.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAD3127115528CD200A3F9ED /* libLocalytics.a */; }; + DAD312C21552A22700A3F9ED /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = DAD312C01552A20800A3F9ED /* libsqlite3.dylib */; }; DAEBC45314F6364500987BF6 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAEBC45214F6364500987BF6 /* QuartzCore.framework */; }; DAFE4A1315039824003ABA7C /* NSObject_PearlExport.h in Headers */ = {isa = PBXBuildFile; fileRef = DAFE45D815039823003ABA7C /* NSObject_PearlExport.h */; }; DAFE4A1415039824003ABA7C /* NSObject_PearlExport.m in Sources */ = {isa = PBXBuildFile; fileRef = DAFE45D915039823003ABA7C /* NSObject_PearlExport.m */; }; @@ -890,8 +905,6 @@ DA95D5CD14DF0691008D1B94 /* IASKPSToggleSwitchSpecifierViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = IASKPSToggleSwitchSpecifierViewCell.xib; sourceTree = ""; }; DA95D5CE14DF0691008D1B94 /* IASKSpecifierValuesView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = IASKSpecifierValuesView.xib; sourceTree = ""; }; DA95D5F014DF0B1E008D1B94 /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; }; - DA95D60114DF3E67008D1B94 /* libTestFlight.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libTestFlight.a; sourceTree = ""; }; - DA95D60414DF3E67008D1B94 /* TestFlight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestFlight.h; sourceTree = ""; }; DAB8D43D15036BCF00CED3BC /* MasterPassword.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MasterPassword.xcdatamodel; sourceTree = ""; }; DAB8D44015036BCF00CED3BC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; DAB8D44115036BCF00CED3BC /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; @@ -1560,7 +1573,6 @@ DAB8D6F715036BF600CED3BC /* tip_location_teal@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "tip_location_teal@2x.png"; sourceTree = ""; }; DAB8D6F815036BF600CED3BC /* tip_location_wood.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tip_location_wood.png; sourceTree = ""; }; DAB8D6F915036BF600CED3BC /* tip_location_wood@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "tip_location_wood@2x.png"; sourceTree = ""; }; - DABB9808150FF40100B05417 /* libSendToMac.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSendToMac.a; sourceTree = BUILT_PRODUCTS_DIR; }; DABB980C150FF40100B05417 /* SendToMac-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SendToMac-Prefix.pch"; sourceTree = ""; }; DABB980D150FF40100B05417 /* SendToMac.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SendToMac.h; sourceTree = ""; }; DABB980E150FF40100B05417 /* SendToMac.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SendToMac.m; sourceTree = ""; }; @@ -1569,11 +1581,30 @@ DAC6326C148680650075AEA5 /* libjrswizzle.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjrswizzle.a; sourceTree = BUILT_PRODUCTS_DIR; }; DAC632791486809A0075AEA5 /* JRSwizzle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JRSwizzle.h; path = External/Pearl/External/jrswizzle/JRSwizzle.h; sourceTree = SOURCE_ROOT; }; DAC6327A1486809A0075AEA5 /* JRSwizzle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JRSwizzle.m; path = External/Pearl/External/jrswizzle/JRSwizzle.m; sourceTree = SOURCE_ROOT; }; - DAC6327D148680B10075AEA5 /* UIColor-Expanded.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIColor-Expanded.h"; path = "External/Pearl/External/uicolor-utilities/UIColor-Expanded.h"; sourceTree = SOURCE_ROOT; }; - DAC6327E148680B10075AEA5 /* UIColor-Expanded.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIColor-Expanded.m"; path = "External/Pearl/External/uicolor-utilities/UIColor-Expanded.m"; sourceTree = SOURCE_ROOT; }; DAC632871486D95D0075AEA5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; DAC77CAD148291A600BCF976 /* libPearl.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPearl.a; sourceTree = BUILT_PRODUCTS_DIR; }; DAC77CB1148291A600BCF976 /* Pearl-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Pearl-Prefix.pch"; sourceTree = ""; }; + DAD3125F15528C9C00A3F9ED /* Crashlytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Crashlytics.framework; sourceTree = ""; }; + DAD3126015528C9C00A3F9ED /* Crashlytics.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Crashlytics.plist; sourceTree = ""; }; + DAD3126215528C9C00A3F9ED /* libTestFlight.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libTestFlight.a; sourceTree = ""; }; + DAD3126515528C9C00A3F9ED /* TestFlight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestFlight.h; sourceTree = ""; }; + DAD3126615528C9C00A3F9ED /* TestFlight.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = TestFlight.plist; sourceTree = ""; }; + DAD3127115528CD200A3F9ED /* libLocalytics.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libLocalytics.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DAD3127D15528D0F00A3F9ED /* Localytics.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Localytics.plist; sourceTree = ""; }; + DAD3127E15528D0F00A3F9ED /* LocalyticsDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalyticsDatabase.h; sourceTree = ""; }; + DAD3127F15528D0F00A3F9ED /* LocalyticsDatabase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LocalyticsDatabase.m; sourceTree = ""; }; + DAD3128015528D0F00A3F9ED /* LocalyticsSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalyticsSession.h; sourceTree = ""; }; + DAD3128115528D0F00A3F9ED /* LocalyticsSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LocalyticsSession.m; sourceTree = ""; }; + DAD3128215528D0F00A3F9ED /* LocalyticsUploader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LocalyticsUploader.h; sourceTree = ""; }; + DAD3128315528D0F00A3F9ED /* LocalyticsUploader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LocalyticsUploader.m; sourceTree = ""; }; + DAD3128415528D0F00A3F9ED /* UploaderThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UploaderThread.h; sourceTree = ""; }; + DAD3128515528D0F00A3F9ED /* UploaderThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UploaderThread.m; sourceTree = ""; }; + DAD3128615528D0F00A3F9ED /* WebserviceConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebserviceConstants.h; sourceTree = ""; }; + DAD312B71552977200A3F9ED /* UIColor+Expanded.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIColor+Expanded.h"; path = "External/Pearl/External/uicolor-utilities/UIColor+Expanded.h"; sourceTree = SOURCE_ROOT; }; + DAD312B81552977200A3F9ED /* UIColor+Expanded.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIColor+Expanded.m"; path = "External/Pearl/External/uicolor-utilities/UIColor+Expanded.m"; sourceTree = SOURCE_ROOT; }; + DAD312B91552977200A3F9ED /* UIColor+HSV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIColor+HSV.h"; path = "External/Pearl/External/uicolor-utilities/UIColor+HSV.h"; sourceTree = SOURCE_ROOT; }; + DAD312BA1552977200A3F9ED /* UIColor+HSV.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIColor+HSV.m"; path = "External/Pearl/External/uicolor-utilities/UIColor+HSV.m"; sourceTree = SOURCE_ROOT; }; + DAD312C01552A20800A3F9ED /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; }; DAEBC45214F6364500987BF6 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; DAFE45D815039823003ABA7C /* NSObject_PearlExport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSObject_PearlExport.h; sourceTree = ""; }; DAFE45D915039823003ABA7C /* NSObject_PearlExport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSObject_PearlExport.m; sourceTree = ""; }; @@ -1657,8 +1688,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + DAD312C21552A22700A3F9ED /* libsqlite3.dylib in Frameworks */, + DAD312BF1552A1BD00A3F9ED /* libLocalytics.a in Frameworks */, DABB981615100B4000B05417 /* SystemConfiguration.framework in Frameworks */, - DABB9814150FF5C100B05417 /* libSendToMac.a in Frameworks */, DA672D3014F9413D004A189C /* libPearl.a in Frameworks */, DA672D2F14F92C6B004A189C /* libz.dylib in Frameworks */, DAEBC45314F6364500987BF6 /* QuartzCore.framework in Frameworks */, @@ -1670,7 +1702,8 @@ DA5BFA4B147E415C00F98B1E /* Foundation.framework in Frameworks */, DA5BFA4D147E415C00F98B1E /* CoreGraphics.framework in Frameworks */, DA5BFA4F147E415C00F98B1E /* CoreData.framework in Frameworks */, - DA95D60614DF3E67008D1B94 /* libTestFlight.a in Frameworks */, + DAD3126715528C9C00A3F9ED /* Crashlytics.framework in Frameworks */, + DAD3126915528C9C00A3F9ED /* libTestFlight.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1682,14 +1715,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - DABB9805150FF40100B05417 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - DABB9809150FF40100B05417 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; DAC6325A1486805C0075AEA5 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1717,6 +1742,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + DAD3126E15528CD200A3F9ED /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DAD3127215528CD200A3F9ED /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -1741,7 +1774,9 @@ DAC6325F1486805C0075AEA5 /* uicolor-utilities */, DAC6326E148680650075AEA5 /* jrswizzle */, DA95D59E14DF063C008D1B94 /* InAppSettingsKit */, - DA95D5FF14DF3E67008D1B94 /* TestFlightSDK */, + DAD3125E15528C9C00A3F9ED /* Crashlytics */, + DAD3126115528C9C00A3F9ED /* TestFlight */, + DAD3127315528CD200A3F9ED /* Localytics */, DA5BFA47147E415C00F98B1E /* Frameworks */, DA5BFA45147E415C00F98B1E /* Products */, ); @@ -1755,7 +1790,7 @@ DAC6325D1486805C0075AEA5 /* libuicolor-utilities.a */, DAC6326C148680650075AEA5 /* libjrswizzle.a */, DA95D59C14DF063C008D1B94 /* libInAppSettingsKit.a */, - DABB9808150FF40100B05417 /* libSendToMac.a */, + DAD3127115528CD200A3F9ED /* libLocalytics.a */, ); name = Products; sourceTree = ""; @@ -1763,6 +1798,7 @@ DA5BFA47147E415C00F98B1E /* Frameworks */ = { isa = PBXGroup; children = ( + DAD312C01552A20800A3F9ED /* libsqlite3.dylib */, DA95D5F014DF0B1E008D1B94 /* MessageUI.framework */, DABB981515100B4000B05417 /* SystemConfiguration.framework */, DA672D2E14F92C6B004A189C /* libz.dylib */, @@ -1787,10 +1823,10 @@ DA600C2615056427008E9AB6 /* MPConfig.h */, DA600C2715056427008E9AB6 /* MPConfig.m */, DAB8D45515036BCF00CED3BC /* MPElementStoredEntity.m */, + DAB8D45915036BCF00CED3BC /* MPTypes.h */, DAB8D45615036BCF00CED3BC /* MPTypes.m */, DAB8D45715036BCF00CED3BC /* MPElementEntity.h */, DAB8D45815036BCF00CED3BC /* MPElementEntity.m */, - DAB8D45915036BCF00CED3BC /* MPTypes.h */, DAB8D45A15036BCF00CED3BC /* MPElementGeneratedEntity.h */, DAB8D45B15036BCF00CED3BC /* MPElementGeneratedEntity.m */, DAB8D45C15036BCF00CED3BC /* MPElementStoredEntity.h */, @@ -1877,16 +1913,6 @@ path = External/InAppSettingsKit/InAppSettingsKit/Xibs; sourceTree = SOURCE_ROOT; }; - DA95D5FF14DF3E67008D1B94 /* TestFlightSDK */ = { - isa = PBXGroup; - children = ( - DA95D60114DF3E67008D1B94 /* libTestFlight.a */, - DA95D60414DF3E67008D1B94 /* TestFlight.h */, - ); - name = TestFlightSDK; - path = External/TestFlightSDK; - sourceTree = ""; - }; DAB8D43E15036BCF00CED3BC /* iOS */ = { isa = PBXGroup; children = ( @@ -2653,8 +2679,10 @@ DAC6325F1486805C0075AEA5 /* uicolor-utilities */ = { isa = PBXGroup; children = ( - DAC6327D148680B10075AEA5 /* UIColor-Expanded.h */, - DAC6327E148680B10075AEA5 /* UIColor-Expanded.m */, + DAD312B71552977200A3F9ED /* UIColor+Expanded.h */, + DAD312B81552977200A3F9ED /* UIColor+Expanded.m */, + DAD312B91552977200A3F9ED /* UIColor+HSV.h */, + DAD312BA1552977200A3F9ED /* UIColor+HSV.m */, ); path = "uicolor-utilities"; sourceTree = ""; @@ -2687,6 +2715,42 @@ name = "Supporting Files"; sourceTree = ""; }; + DAD3125E15528C9C00A3F9ED /* Crashlytics */ = { + isa = PBXGroup; + children = ( + DAD3125F15528C9C00A3F9ED /* Crashlytics.framework */, + DAD3126015528C9C00A3F9ED /* Crashlytics.plist */, + ); + path = Crashlytics; + sourceTree = ""; + }; + DAD3126115528C9C00A3F9ED /* TestFlight */ = { + isa = PBXGroup; + children = ( + DAD3126215528C9C00A3F9ED /* libTestFlight.a */, + DAD3126515528C9C00A3F9ED /* TestFlight.h */, + DAD3126615528C9C00A3F9ED /* TestFlight.plist */, + ); + path = TestFlight; + sourceTree = ""; + }; + DAD3127315528CD200A3F9ED /* Localytics */ = { + isa = PBXGroup; + children = ( + DAD3127D15528D0F00A3F9ED /* Localytics.plist */, + DAD3127E15528D0F00A3F9ED /* LocalyticsDatabase.h */, + DAD3127F15528D0F00A3F9ED /* LocalyticsDatabase.m */, + DAD3128015528D0F00A3F9ED /* LocalyticsSession.h */, + DAD3128115528D0F00A3F9ED /* LocalyticsSession.m */, + DAD3128215528D0F00A3F9ED /* LocalyticsUploader.h */, + DAD3128315528D0F00A3F9ED /* LocalyticsUploader.m */, + DAD3128415528D0F00A3F9ED /* UploaderThread.h */, + DAD3128515528D0F00A3F9ED /* UploaderThread.m */, + DAD3128615528D0F00A3F9ED /* WebserviceConstants.h */, + ); + path = Localytics; + sourceTree = ""; + }; DAFE45D715039823003ABA7C /* Pearl */ = { isa = PBXGroup; children = ( @@ -2827,18 +2891,12 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - DABB9806150FF40100B05417 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; DAC6325B1486805C0075AEA5 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - DAC6327F148680B10075AEA5 /* UIColor-Expanded.h in Headers */, + DAD312BB1552977200A3F9ED /* UIColor+Expanded.h in Headers */, + DAD312BD1552977200A3F9ED /* UIColor+HSV.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2895,6 +2953,18 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + DAD3126F15528CD200A3F9ED /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DAD3128715528D0F00A3F9ED /* LocalyticsDatabase.h in Headers */, + DAD3128915528D0F00A3F9ED /* LocalyticsSession.h in Headers */, + DAD3128B15528D0F00A3F9ED /* LocalyticsUploader.h in Headers */, + DAD3128D15528D0F00A3F9ED /* UploaderThread.h in Headers */, + DAD3128F15528D0F00A3F9ED /* WebserviceConstants.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ @@ -2905,7 +2975,8 @@ DA5BFA40147E415C00F98B1E /* Sources */, DA5BFA41147E415C00F98B1E /* Frameworks */, DA5BFA42147E415C00F98B1E /* Resources */, - DA6556E314D55F3000841C99 /* ShellScript */, + DA6556E314D55F3000841C99 /* Run Script: GIT version -> Info.plist */, + DAD3125D155288AA00A3F9ED /* ShellScript */, ); buildRules = ( ); @@ -2933,23 +3004,6 @@ productReference = DA95D59C14DF063C008D1B94 /* libInAppSettingsKit.a */; productType = "com.apple.product-type.library.static"; }; - DABB9807150FF40100B05417 /* SendToMac */ = { - isa = PBXNativeTarget; - buildConfigurationList = DABB9810150FF40100B05417 /* Build configuration list for PBXNativeTarget "SendToMac" */; - buildPhases = ( - DABB9804150FF40100B05417 /* Sources */, - DABB9805150FF40100B05417 /* Frameworks */, - DABB9806150FF40100B05417 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = SendToMac; - productName = SendToMac; - productReference = DABB9808150FF40100B05417 /* libSendToMac.a */; - productType = "com.apple.product-type.library.static"; - }; DAC6325C1486805C0075AEA5 /* uicolor-utilities */ = { isa = PBXNativeTarget; buildConfigurationList = DAC632651486805C0075AEA5 /* Build configuration list for PBXNativeTarget "uicolor-utilities" */; @@ -3003,6 +3057,23 @@ productReference = DAC77CAD148291A600BCF976 /* libPearl.a */; productType = "com.apple.product-type.library.static"; }; + DAD3127015528CD200A3F9ED /* Localytics */ = { + isa = PBXNativeTarget; + buildConfigurationList = DAD3127915528CD200A3F9ED /* Build configuration list for PBXNativeTarget "Localytics" */; + buildPhases = ( + DAD3126D15528CD200A3F9ED /* Sources */, + DAD3126E15528CD200A3F9ED /* Frameworks */, + DAD3126F15528CD200A3F9ED /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Localytics; + productName = Localytics; + productReference = DAD3127115528CD200A3F9ED /* libLocalytics.a */; + productType = "com.apple.product-type.library.static"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -3037,7 +3108,7 @@ DAC6325C1486805C0075AEA5 /* uicolor-utilities */, DAC6326B148680650075AEA5 /* jrswizzle */, DA95D59B14DF063C008D1B94 /* InAppSettingsKit */, - DABB9807150FF40100B05417 /* SendToMac */, + DAD3127015528CD200A3F9ED /* Localytics */, ); }; /* End PBXProject section */ @@ -3720,13 +3791,31 @@ DAB8D97A15036BF700CED3BC /* tip_location_wood.png in Resources */, DAB8D97B15036BF700CED3BC /* tip_location_wood@2x.png in Resources */, DAFE4A5A1503982E003ABA7C /* Pearl.strings in Resources */, + DAD3126815528C9C00A3F9ED /* Crashlytics.plist in Resources */, + DAD3126C15528C9C00A3F9ED /* TestFlight.plist in Resources */, + DAD3129015528D1600A3F9ED /* Localytics.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - DA6556E314D55F3000841C99 /* ShellScript */ = { + DA6556E314D55F3000841C99 /* Run Script: GIT version -> Info.plist */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script: GIT version -> Info.plist"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = "/bin/bash -e"; + shellScript = "PATH+=:/usr/libexec\n\nsetPlistWithKey() {\n local key=$1 value=$2 plist=${3:-\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"}\n \n PlistBuddy -c \"Set :'$key' $value\" \"$plist\"\n}\ngetPlistWithKey() {\n local key=$1 plist=${2:-\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"}\n \n PlistBuddy -c \"Print :'$key'\" \"$plist\"\n}\nsetSettingWithTitle() {\n local i title=$1 value=$2 plist=${3:-\"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Settings.bundle/Root.plist\"}\n \n for (( i=0; 1; ++i )); do\n PlistBuddy -c \"Print :PreferenceSpecifiers:$i\" \"$plist\" &>/dev/null || break\n echo \"Checking preference specifier $i\"\n \n [[ $(PlistBuddy -c \"Print :PreferenceSpecifiers:$i:Title\" \"$plist\" 2>/dev/null) = $title ]] || continue\n \n echo \"Correct title, setting value.\"\n PlistBuddy -c \"Set :PreferenceSpecifiers:$i:DefaultValue $value\" \"$plist\"\n break\n done\n}\n\nbuild=$(git describe --tags --always --dirty --long)\ntag=$(git describe --tags | sed 's/-\\([^-]*\\)-[^-]*$/.\\1/')\n\nsetPlistWithKey CFBundleVersion \"$build\"\nsetPlistWithKey CFBundleShortVersionString \"$tag\"\n\nsetSettingWithTitle \"Build\" \"$build\"\nsetSettingWithTitle \"Version\" \"$tag\"\nsetSettingWithTitle \"Copyright\" \"$(getPlistWithKey NSHumanReadableCopyright)\"\n"; + showEnvVarsInLog = 0; + }; + DAD3125D155288AA00A3F9ED /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -3737,7 +3826,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = "/bin/bash -e"; - shellScript = "PATH+=:/usr/libexec\n\nsetPlistWithKey() {\n local key=$1 value=$2 plist=${3:-\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"}\n\n PlistBuddy -c \"Set :$key $value\" \"$plist\"\n}\ngetPlistWithKey() {\n local key=$1 plist=${2:-\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"}\n \n PlistBuddy -c \"Print :$key\" \"$plist\"\n}\nsetSettingWithTitle() {\n local i title=$1 value=$2 plist=${3:-\"$BUILT_PRODUCTS_DIR/$CONTENTS_FOLDER_PATH/Settings.bundle/Root.plist\"}\n \n for (( i=0; 1; ++i )); do\n PlistBuddy -c \"Print :PreferenceSpecifiers:$i\" \"$plist\" &>/dev/null || break\n echo \"Checking preference specifier $i\"\n \n [[ $(PlistBuddy -c \"Print :PreferenceSpecifiers:$i:Title\" \"$plist\" 2>/dev/null) = $title ]] || continue\n\n echo \"Correct title, setting value.\"\n PlistBuddy -c \"Set :PreferenceSpecifiers:$i:DefaultValue $value\" \"$plist\"\n break\n done\n}\n\nbuild=$(git describe --tags --always --dirty --long)\ntag=$(git describe --tags | sed 's/-\\([^-]*\\)-[^-]*$/.\\1/')\n\nsetPlistWithKey CFBundleVersion \"$build\"\nsetPlistWithKey CFBundleShortVersionString \"$tag\"\n\nsetSettingWithTitle \"Build\" \"$build\"\nsetSettingWithTitle \"Version\" \"$tag\"\nsetSettingWithTitle \"Copyright\" \"$(getPlistWithKey NSHumanReadableCopyright)\"\n"; + shellScript = "Crashlytics/Crashlytics.framework/run \"$(/usr/libexec/PlistBuddy -c \"Print :'API Key'\" Crashlytics/Crashlytics.plist)\""; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -3787,19 +3876,12 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - DABB9804150FF40100B05417 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - DABB980F150FF40100B05417 /* SendToMac.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; DAC632591486805C0075AEA5 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - DAC63280148680B10075AEA5 /* UIColor-Expanded.m in Sources */, + DAD312BC1552977200A3F9ED /* UIColor+Expanded.m in Sources */, + DAD312BE1552977200A3F9ED /* UIColor+HSV.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3851,6 +3933,17 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + DAD3126D15528CD200A3F9ED /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DAD3128815528D0F00A3F9ED /* LocalyticsDatabase.m in Sources */, + DAD3128A15528D0F00A3F9ED /* LocalyticsSession.m in Sources */, + DAD3128C15528D0F00A3F9ED /* LocalyticsUploader.m in Sources */, + DAD3128E15528D0F00A3F9ED /* UploaderThread.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -3891,131 +3984,226 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_WARN_CXX0X_EXTENSIONS = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREPROCESSOR_DEFINITIONS = ( - "TESTFLIGHT=1", "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; + GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = NO; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_VALUE = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 5.0; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "${TARGET_NAME}"; SDKROOT = iphoneos; - STRIP_INSTALLED_PRODUCT = NO; + SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; - DA5BFA6C147E415C00F98B1E /* Release */ = { + DA5BFA6C147E415C00F98B1E /* AdHoc */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_WARN_CXX0X_EXTENSIONS = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREPROCESSOR_DEFINITIONS = ( - "TESTFLIGHT=1", + "ADHOC=1", "$(inherited)", + "NDEBUG=1", + "NS_BLOCK_ASSERTIONS=1", ); + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; + GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_VALUE = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 5.0; - OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "${TARGET_NAME}"; "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; SDKROOT = iphoneos; - STRIP_INSTALLED_PRODUCT = NO; + SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; - name = Release; + name = AdHoc; }; DA5BFA6E147E415C00F98B1E /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = MasterPassword/iOS/MasterPassword.entitlements; - GCC_PRECOMPILE_PREFIX_HEADER = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/Crashlytics\"", + ); GCC_PREFIX_HEADER = "MasterPassword/iOS/MasterPassword-Prefix.pch"; INFOPLIST_FILE = "MasterPassword/iOS/MasterPassword-Info.plist"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "\"$(SRCROOT)/External/TestFlightSDK\"", + "\"$(SRCROOT)/TestFlight\"", ); OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = app; }; name = Debug; }; - DA5BFA6F147E415C00F98B1E /* Release */ = { + DA5BFA6F147E415C00F98B1E /* AdHoc */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = MasterPassword/iOS/MasterPassword.entitlements; - GCC_PRECOMPILE_PREFIX_HEADER = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/Crashlytics\"", + ); GCC_PREFIX_HEADER = "MasterPassword/iOS/MasterPassword-Prefix.pch"; INFOPLIST_FILE = "MasterPassword/iOS/MasterPassword-Info.plist"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "\"$(SRCROOT)/External/TestFlightSDK\"", + "\"$(SRCROOT)/TestFlight\"", ); OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = app; }; - name = Release; + name = AdHoc; }; DA95D5A514DF063C008D1B94 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { DSTROOT = /tmp/InAppSettingsKit.dst; + GCC_WARN_INHIBIT_ALL_WARNINGS = YES; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = InAppSettingsKit; SKIP_INSTALL = YES; }; name = Debug; }; - DA95D5A614DF063C008D1B94 /* Release */ = { + DA95D5A614DF063C008D1B94 /* AdHoc */ = { isa = XCBuildConfiguration; buildSettings = { DSTROOT = /tmp/InAppSettingsKit.dst; + GCC_WARN_INHIBIT_ALL_WARNINGS = YES; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = InAppSettingsKit; SKIP_INSTALL = YES; }; - name = Release; + name = AdHoc; }; DA95D60914DF3F3B008D1B94 /* AppStore */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_WARN_CXX0X_EXTENSIONS = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; + CLANG_WARN__EXIT_TIME_DESTRUCTORS = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "APPSTORE=1", "$(inherited)", + "NDEBUG=1", + "NS_BLOCK_ASSERTIONS=1", ); + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; + GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_VALUE = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 5.0; - OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "${TARGET_NAME}"; "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; SDKROOT = iphoneos; - STRIP_INSTALLED_PRODUCT = NO; + SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -4026,16 +4214,17 @@ buildSettings = { CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = MasterPassword/iOS/MasterPassword.entitlements; - GCC_PRECOMPILE_PREFIX_HEADER = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/Crashlytics\"", + ); GCC_PREFIX_HEADER = "MasterPassword/iOS/MasterPassword-Prefix.pch"; INFOPLIST_FILE = "MasterPassword/iOS/MasterPassword-Info.plist"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "\"$(SRCROOT)/External/TestFlightSDK\"", + "\"$(SRCROOT)/TestFlight\"", ); OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = app; }; name = AppStore; }; @@ -4081,60 +4270,13 @@ isa = XCBuildConfiguration; buildSettings = { DSTROOT = /tmp/InAppSettingsKit.dst; + GCC_WARN_INHIBIT_ALL_WARNINGS = YES; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = InAppSettingsKit; SKIP_INSTALL = YES; }; name = AppStore; }; - DABB9811150FF40100B05417 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_OBJC_ARC = YES; - DSTROOT = /tmp/SendToMac.dst; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "SendToMac/SendToMac-Prefix.pch"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_UNINITIALIZED_AUTOS = YES; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - DABB9812150FF40100B05417 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_OBJC_ARC = YES; - COPY_PHASE_STRIP = YES; - DSTROOT = /tmp/SendToMac.dst; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "SendToMac/SendToMac-Prefix.pch"; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = Release; - }; - DABB9813150FF40100B05417 /* AppStore */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_OBJC_ARC = YES; - COPY_PHASE_STRIP = YES; - DSTROOT = /tmp/SendToMac.dst; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "SendToMac/SendToMac-Prefix.pch"; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = AppStore; - }; DAC632661486805C0075AEA5 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -4147,7 +4289,7 @@ }; name = Debug; }; - DAC632671486805C0075AEA5 /* Release */ = { + DAC632671486805C0075AEA5 /* AdHoc */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_OBJC_ARC = NO; @@ -4157,7 +4299,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; - name = Release; + name = AdHoc; }; DAC63275148680650075AEA5 /* Debug */ = { isa = XCBuildConfiguration; @@ -4171,7 +4313,7 @@ }; name = Debug; }; - DAC63276148680650075AEA5 /* Release */ = { + DAC63276148680650075AEA5 /* AdHoc */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_OBJC_ARC = NO; @@ -4181,7 +4323,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; - name = Release; + name = AdHoc; }; DAC77CB5148291A600BCF976 /* Debug */ = { isa = XCBuildConfiguration; @@ -4197,7 +4339,7 @@ }; name = Debug; }; - DAC77CB6148291A600BCF976 /* Release */ = { + DAC77CB6148291A600BCF976 /* AdHoc */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_OBJC_ARC = NO; @@ -4209,7 +4351,28 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; - name = Release; + name = AdHoc; + }; + DAD3127A15528CD200A3F9ED /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_INHIBIT_ALL_WARNINGS = YES; + }; + name = Debug; + }; + DAD3127B15528CD200A3F9ED /* AdHoc */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_INHIBIT_ALL_WARNINGS = YES; + }; + name = AdHoc; + }; + DAD3127C15528CD200A3F9ED /* AppStore */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_INHIBIT_ALL_WARNINGS = YES; + }; + name = AppStore; }; /* End XCBuildConfiguration section */ @@ -4218,70 +4381,71 @@ isa = XCConfigurationList; buildConfigurations = ( DA5BFA6B147E415C00F98B1E /* Debug */, - DA5BFA6C147E415C00F98B1E /* Release */, + DA5BFA6C147E415C00F98B1E /* AdHoc */, DA95D60914DF3F3B008D1B94 /* AppStore */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; + defaultConfigurationName = AdHoc; }; DA5BFA6D147E415C00F98B1E /* Build configuration list for PBXNativeTarget "MasterPassword" */ = { isa = XCConfigurationList; buildConfigurations = ( DA5BFA6E147E415C00F98B1E /* Debug */, - DA5BFA6F147E415C00F98B1E /* Release */, + DA5BFA6F147E415C00F98B1E /* AdHoc */, DA95D60A14DF3F3B008D1B94 /* AppStore */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; + defaultConfigurationName = AdHoc; }; DA95D5A414DF063C008D1B94 /* Build configuration list for PBXNativeTarget "InAppSettingsKit" */ = { isa = XCConfigurationList; buildConfigurations = ( DA95D5A514DF063C008D1B94 /* Debug */, - DA95D5A614DF063C008D1B94 /* Release */, + DA95D5A614DF063C008D1B94 /* AdHoc */, DA95D60E14DF3F3B008D1B94 /* AppStore */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - DABB9810150FF40100B05417 /* Build configuration list for PBXNativeTarget "SendToMac" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - DABB9811150FF40100B05417 /* Debug */, - DABB9812150FF40100B05417 /* Release */, - DABB9813150FF40100B05417 /* AppStore */, - ); - defaultConfigurationIsVisible = 0; + defaultConfigurationName = AdHoc; }; DAC632651486805C0075AEA5 /* Build configuration list for PBXNativeTarget "uicolor-utilities" */ = { isa = XCConfigurationList; buildConfigurations = ( DAC632661486805C0075AEA5 /* Debug */, - DAC632671486805C0075AEA5 /* Release */, + DAC632671486805C0075AEA5 /* AdHoc */, DA95D60C14DF3F3B008D1B94 /* AppStore */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; + defaultConfigurationName = AdHoc; }; DAC63274148680650075AEA5 /* Build configuration list for PBXNativeTarget "jrswizzle" */ = { isa = XCConfigurationList; buildConfigurations = ( DAC63275148680650075AEA5 /* Debug */, - DAC63276148680650075AEA5 /* Release */, + DAC63276148680650075AEA5 /* AdHoc */, DA95D60D14DF3F3B008D1B94 /* AppStore */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; + defaultConfigurationName = AdHoc; }; DAC77CB7148291A600BCF976 /* Build configuration list for PBXNativeTarget "Pearl" */ = { isa = XCConfigurationList; buildConfigurations = ( DAC77CB5148291A600BCF976 /* Debug */, - DAC77CB6148291A600BCF976 /* Release */, + DAC77CB6148291A600BCF976 /* AdHoc */, DA95D60B14DF3F3B008D1B94 /* AppStore */, ); defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; + defaultConfigurationName = AdHoc; + }; + DAD3127915528CD200A3F9ED /* Build configuration list for PBXNativeTarget "Localytics" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DAD3127A15528CD200A3F9ED /* Debug */, + DAD3127B15528CD200A3F9ED /* AdHoc */, + DAD3127C15528CD200A3F9ED /* AppStore */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = AdHoc; }; /* End XCConfigurationList section */ diff --git a/MasterPassword-iOS.xcodeproj/xcshareddata/xcschemes/MasterPassword (Development).xcscheme b/MasterPassword-iOS.xcodeproj/xcshareddata/xcschemes/MasterPassword (Development).xcscheme index eda35017..d0732f12 100644 --- a/MasterPassword-iOS.xcodeproj/xcshareddata/xcschemes/MasterPassword (Development).xcscheme +++ b/MasterPassword-iOS.xcodeproj/xcshareddata/xcschemes/MasterPassword (Development).xcscheme @@ -68,14 +68,14 @@ shouldUseLaunchSchemeArgsEnv = "YES" savedToolIdentifier = "" useCustomWorkingDirectory = "NO" - buildConfiguration = "Release" + buildConfiguration = "AdHoc" debugDocumentVersioning = "YES"> diff --git a/MasterPassword/MPAppDelegate_Key.m b/MasterPassword/MPAppDelegate_Key.m index 8656e180..e791a408 100644 --- a/MasterPassword/MPAppDelegate_Key.m +++ b/MasterPassword/MPAppDelegate_Key.m @@ -42,9 +42,7 @@ static NSDictionary *keyHashQuery() { [PearlKeyChain deleteItemForQuery:keyHashQuery()]; [[NSNotificationCenter defaultCenter] postNotificationName:MPNotificationKeyForgotten object:self]; -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointMPForgotten]; -#endif } - (void)signOut { @@ -63,9 +61,7 @@ static NSDictionary *keyHashQuery() { // Key should not be stored in keychain. Delete it. dbg(@"Deleting key from key chain."); [PearlKeyChain deleteItemForQuery:keyQuery()]; -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointMPUnstored]; -#endif } } @@ -96,15 +92,11 @@ static NSDictionary *keyHashQuery() { if (![keyHash isEqual:tryKeyHash]) { dbg(@"Key phrase hash mismatch. Expected: %@, answer: %@.", keyHash, tryKeyHash); -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointMPMismatch]; -#endif return NO; } -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointMPAsked]; -#endif [self updateKey:tryKey]; return YES; @@ -142,9 +134,7 @@ static NSDictionary *keyHashQuery() { nil]]; } -#ifdef TESTFLIGHT [TestFlight passCheckpoint:[NSString stringWithFormat:MPTestFlightCheckpointSetKeyphraseLength, key.length]]; -#endif } } diff --git a/MasterPassword/MPElementGeneratedEntity.h b/MasterPassword/MPElementGeneratedEntity.h index 8103a226..832ca61b 100644 --- a/MasterPassword/MPElementGeneratedEntity.h +++ b/MasterPassword/MPElementGeneratedEntity.h @@ -13,6 +13,6 @@ @interface MPElementGeneratedEntity : MPElementEntity -@property (nonatomic, assign) uint16_t counter; +@property (nonatomic, assign) int16_t counter; @end diff --git a/MasterPassword/MPElementGeneratedEntity.m b/MasterPassword/MPElementGeneratedEntity.m index b2827d42..04e549c9 100644 --- a/MasterPassword/MPElementGeneratedEntity.m +++ b/MasterPassword/MPElementGeneratedEntity.m @@ -22,7 +22,7 @@ return nil; if (self.type & MPElementTypeClassCalculated) - return MPCalculateContent(self.type, self.name, [MPAppDelegate get].key, self.counter); + return MPCalculateContent((unsigned)self.type, self.name, [MPAppDelegate get].key, self.counter); @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"Unsupported type: %d", self.type] userInfo:nil]; diff --git a/MasterPassword/MPTypes.h b/MasterPassword/MPTypes.h index c73b94ef..d13a12f8 100644 --- a/MasterPassword/MPTypes.h +++ b/MasterPassword/MPTypes.h @@ -32,10 +32,10 @@ typedef enum { MPElementTypeStoredDevicePrivate = MPElementTypeClassStored | 0x02, } MPElementType; -#ifdef TESTFLIGHT #define MPTestFlightCheckpointAction @"MPTestFlightCheckpointAction" #define MPTestFlightCheckpointHelpChapter @"MPTestFlightCheckpointHelpChapter_%@" #define MPTestFlightCheckpointCopyToPasteboard @"MPTestFlightCheckpointCopyToPasteboard" +#define MPTestFlightCheckpointResetPasswordCounter @"MPTestFlightCheckpointResetPasswordCounter" #define MPTestFlightCheckpointIncrementPasswordCounter @"MPTestFlightCheckpointIncrementPasswordCounter" #define MPTestFlightCheckpointEditPassword @"MPTestFlightCheckpointEditPassword" #define MPTestFlightCheckpointCloseAlert @"MPTestFlightCheckpointCloseAlert" @@ -56,7 +56,6 @@ typedef enum { #define MPTestFlightCheckpointMPAsked @"MPTestFlightCheckpointMPAsked" #define MPTestFlightCheckpointStoreIncompatible @"MPTestFlightCheckpointStoreIncompatible" #define MPTestFlightCheckpointSetKeyphraseLength @"MPTestFlightCheckpointSetKeyphraseLength_%d" -#endif #define MPNotificationStoreUpdated @"MPNotificationStoreUpdated" #define MPNotificationKeySet @"MPNotificationKeySet" @@ -69,4 +68,4 @@ NSData *keyHashForKey(NSData *key); NSString *NSStringFromMPElementType(MPElementType type); NSString *ClassNameFromMPElementType(MPElementType type); Class ClassFromMPElementType(MPElementType type); -NSString *MPCalculateContent(MPElementType type, NSString *name, NSData *key, uint16_t counter); +NSString *MPCalculateContent(MPElementType type, NSString *name, NSData *key, int16_t counter); diff --git a/MasterPassword/MPTypes.m b/MasterPassword/MPTypes.m index 9934ead5..4589a7cf 100644 --- a/MasterPassword/MPTypes.m +++ b/MasterPassword/MPTypes.m @@ -102,7 +102,7 @@ NSString *ClassNameFromMPElementType(MPElementType type) { } static NSDictionary *MPTypes_ciphers = nil; -NSString *MPCalculateContent(MPElementType type, NSString *name, NSData *key, uint16_t counter) { +NSString *MPCalculateContent(MPElementType type, NSString *name, NSData *key, int16_t counter) { assert(type & MPElementTypeClassCalculated); diff --git a/MasterPassword/iOS/MPAppDelegate.m b/MasterPassword/iOS/MPAppDelegate.m index 7b626301..505f615b 100644 --- a/MasterPassword/iOS/MPAppDelegate.m +++ b/MasterPassword/iOS/MPAppDelegate.m @@ -11,6 +11,23 @@ #import "MPMainViewController.h" #import "IASKSettingsReader.h" +#import "LocalyticsSession.h" +#import "TestFlight.h" +#import + +@interface MPAppDelegate () + +- (NSString *)testFlightInfo; +- (NSString *)testFlightToken; + +- (NSString *)crashlyticsInfo; +- (NSString *)crashlyticsAPIKey; + +- (NSString *)localyticsInfo; +- (NSString *)localyticsKey; + +@end + @implementation MPAppDelegate @@ -28,30 +45,70 @@ #ifdef DEBUG [PearlLogger get].autoprintLevel = PearlLogLevelDebug; - [NSClassFromString(@"WebView") performSelector:@selector(_enableRemoteInspector)]; +// [NSClassFromString(@"WebView") performSelector:NSSelectorFromString(@"_enableRemoteInspector")]; #endif } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { -#ifdef TESTFLIGHT - @try { - [TestFlight takeOff:@"bd44885deee7adce0645ce8e5498d80a_NDQ5NDQyMDExLTEyLTAyIDExOjM1OjQ4LjQ2NjM4NA"]; - [TestFlight setOptions:[NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithBool:NO], @"logToConsole", - [NSNumber numberWithBool:NO], @"logToSTDERR", - nil]]; - [TestFlight passCheckpoint:MPTestFlightCheckpointLaunched]; - [[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) { - if (message.level >= PearlLogLevelInfo) - TFLog(@"%@", message); - - return YES; - }]; - } - @catch (NSException *exception) { - err(@"TestFlight: %@", exception); - } +#ifndef DEBUG + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ + @try { + NSString *testFlightToken = [self testFlightToken]; + if ([testFlightToken length]) { + dbg(@"Initializing TestFlight"); + [TestFlight addCustomEnvironmentInformation:@"Anonymous" forKey:@"username"]; + [TestFlight setOptions:[NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:NO], @"logToConsole", + [NSNumber numberWithBool:NO], @"logToSTDERR", + nil]]; + [TestFlight takeOff:testFlightToken]; + [[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) { + if (message.level >= PearlLogLevelInfo) + TFLog(@"%@", message); + + return YES; + }]; + [TestFlight passCheckpoint:MPTestFlightCheckpointLaunched]; + } + } + @catch (NSException *exception) { + err(@"TestFlight: %@", exception); + } + @try { + NSString *crashlyticsAPIKey = [self crashlyticsAPIKey]; + if ([crashlyticsAPIKey length]) { + dbg(@"Initializing Crashlytics"); + //[Crashlytics sharedInstance].debugMode = YES; + [Crashlytics startWithAPIKey:crashlyticsAPIKey afterDelay:0]; + } + } + @catch (NSException *exception) { + err(@"Crashlytics: %@", exception); + } + @try { + NSString *localyticsKey = [self localyticsKey]; + if ([localyticsKey length]) { + dbg(@"Initializing Localytics"); + [[LocalyticsSession sharedLocalyticsSession] startSession:localyticsKey]; + [[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) { + if (message.level >= PearlLogLevelError) + [[LocalyticsSession sharedLocalyticsSession] tagEvent:@"Problem" attributes: + [NSDictionary dictionaryWithObjectsAndKeys: + [message levelDescription], + @"level", + message.message, + @"message", + nil]]; + + return YES; + }]; + } + } + @catch (NSException *exception) { + err(@"Localytics exception: %@", exception); + } + }); #endif UIImage *navBarImage = [[UIImage imageNamed:@"ui_navbar_container"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)]; @@ -59,10 +116,10 @@ [[UINavigationBar appearance] setBackgroundImage:navBarImage forBarMetrics:UIBarMetricsLandscapePhone]; [[UINavigationBar appearance] setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys: - [UIColor colorWithRed:255.0/255.0 green:255.0/255.0 blue:255.0/255.0 alpha:1.0], UITextAttributeTextColor, - [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.8], UITextAttributeTextShadowColor, - [NSValue valueWithUIOffset:UIOffsetMake(0, -1)], UITextAttributeTextShadowOffset, - [UIFont fontWithName:@"Helvetica-Neue" size:0.0], UITextAttributeFont, + [UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f], UITextAttributeTextColor, + [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.8f], UITextAttributeTextShadowColor, + [NSValue valueWithUIOffset:UIOffsetMake(0, -1)], UITextAttributeTextShadowOffset, + [UIFont fontWithName:@"Helvetica-Neue" size:0.0f], UITextAttributeFont, nil]]; UIImage *navBarButton = [[UIImage imageNamed:@"ui_navbar_button"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 5, 0, 5)]; @@ -73,10 +130,10 @@ [[UIBarButtonItem appearance] setBackButtonBackgroundImage:nil forState:UIControlStateNormal barMetrics:UIBarMetricsLandscapePhone]; [[UIBarButtonItem appearance] setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys: - [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0], UITextAttributeTextColor, - [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.5], UITextAttributeTextShadowColor, - [NSValue valueWithUIOffset:UIOffsetMake(0, 1)], UITextAttributeTextShadowOffset, - [UIFont fontWithName:@"Helvetica-Neue" size:0.0], UITextAttributeFont, + [UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f], UITextAttributeTextColor, + [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f], UITextAttributeTextShadowColor, + [NSValue valueWithUIOffset:UIOffsetMake(0, 1)], UITextAttributeTextShadowOffset, + [UIFont fontWithName:@"Helvetica-Neue" size:0.0f], UITextAttributeFont, nil] forState:UIControlStateNormal]; @@ -118,7 +175,7 @@ [self loadKey:YES]; }]; -#ifdef TESTFLIGHT +#ifdef ADHOC [PearlAlert showAlertWithTitle:@"Welcome, tester!" message: @"Thank you for taking the time to test Master Password.\n\n" @"Please provide any feedback, however minor it may seem, via the Feedback action item accessible from the top right.\n\n" @@ -143,18 +200,14 @@ else [self loadKey:NO]; -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointActivated]; -#endif } - (void)showGuide { [self.navigationController performSegueWithIdentifier:@"MP_Guide" sender:self]; -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointShowGuide]; -#endif } - (void)loadKey:(BOOL)animated { @@ -172,6 +225,34 @@ }); } +- (void)applicationDidEnterBackground:(UIApplication *)application { + + [[LocalyticsSession sharedLocalyticsSession] close]; + [[LocalyticsSession sharedLocalyticsSession] upload]; + + [super applicationDidEnterBackground:application]; +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + + [[LocalyticsSession sharedLocalyticsSession] resume]; + [[LocalyticsSession sharedLocalyticsSession] upload]; + + [super applicationWillEnterForeground:application]; +} + +- (void)applicationWillTerminate:(UIApplication *)application { + + [self saveContext]; + + [TestFlight passCheckpoint:MPTestFlightCheckpointTerminated]; + + [[LocalyticsSession sharedLocalyticsSession] close]; + [[LocalyticsSession sharedLocalyticsSession] upload]; + + [super applicationWillTerminate:application]; +} + - (void)applicationWillResignActive:(UIApplication *)application { [self saveContext]; @@ -179,18 +260,7 @@ if (![[MPiOSConfig get].rememberKey boolValue]) [self updateKey:nil]; -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointDeactivated]; -#endif -} - -- (void)applicationWillTerminate:(UIApplication *)application { - - [self saveContext]; - -#ifdef TESTFLIGHT - [TestFlight passCheckpoint:MPTestFlightCheckpointTerminated]; -#endif } + (NSManagedObjectContext *)managedObjectContext { @@ -279,9 +349,7 @@ [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]; #endif -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointStoreIncompatible]; -#endif @throw [NSException exceptionWithName:error.domain reason:error.localizedDescription userInfo:[NSDictionary dictionaryWithObject:error forKey:@"cause"]]; @@ -306,4 +374,70 @@ return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; } + +#pragma mark - TestFlight + + +static NSDictionary *testFlightInfo = nil; + +- (NSDictionary *)testFlightInfo { + + if (testFlightInfo == nil) + testFlightInfo = [[NSDictionary alloc] initWithContentsOfURL: + [[NSBundle mainBundle] URLForResource:@"TestFlight" withExtension:@"plist"]]; + + return testFlightInfo; +} + +- (NSString *)testFlightToken { + + return NSNullToNil([[self testFlightInfo] valueForKeyPath:@"Team Token"]); +} + + +#pragma mark - Crashlytics + + +static NSDictionary *crashlyticsInfo = nil; + +- (NSDictionary *)crashlyticsInfo { + + if (crashlyticsInfo == nil) + crashlyticsInfo = [[NSDictionary alloc] initWithContentsOfURL: + [[NSBundle mainBundle] URLForResource:@"Crashlytics" withExtension:@"plist"]]; + + return crashlyticsInfo; +} + +- (NSString *)crashlyticsAPIKey { + + return NSNullToNil([[self crashlyticsInfo] valueForKeyPath:@"API Key"]); +} + + +#pragma mark - Localytics + + +static NSDictionary *localyticsInfo = nil; + +- (NSDictionary *)localyticsInfo { + + if (localyticsInfo == nil) + localyticsInfo = [[NSDictionary alloc] initWithContentsOfURL: + [[NSBundle mainBundle] URLForResource:@"Localytics" withExtension:@"plist"]]; + + return localyticsInfo; +} + +- (NSString *)localyticsKey { + +#ifdef DEBUG + return NSNullToNil([[self localyticsInfo] valueForKeyPath:@"Key.development"]); +#elif defined(LITE) + return NSNullToNil([[self localyticsInfo] valueForKeyPath:@"Key.distribution.lite"]); +#else + return NSNullToNil([[self localyticsInfo] valueForKeyPath:@"Key.distribution"]); +#endif +} + @end diff --git a/MasterPassword/iOS/MPMainViewController.h b/MasterPassword/iOS/MPMainViewController.h index 145dbe4a..038a2d26 100644 --- a/MasterPassword/iOS/MPMainViewController.h +++ b/MasterPassword/iOS/MPMainViewController.h @@ -34,6 +34,7 @@ - (IBAction)copyContent; - (IBAction)incrementPasswordCounter; +- (IBAction)resetPasswordCounter:(UILongPressGestureRecognizer *)sender; - (IBAction)editPassword; - (IBAction)closeAlert; - (IBAction)action:(UIBarButtonItem *)sender; diff --git a/MasterPassword/iOS/MPMainViewController.m b/MasterPassword/iOS/MPMainViewController.m index 93576aa5..5e341383 100644 --- a/MasterPassword/iOS/MPMainViewController.m +++ b/MasterPassword/iOS/MPMainViewController.m @@ -21,7 +21,8 @@ - (void)updateWasAnimated:(BOOL)animated; - (void)showContentTip:(NSString *)message withIcon:(UIImageView *)icon; - (void)showAlertWithTitle:(NSString *)title message:(NSString *)message; -- (void)updateElement:(void (^)(void))updateElement; +- (void)changeElementWithWarning:(NSString *)warning do:(void (^)(void))task; +- (void)changeElementWithoutWarningDo:(void (^)(void))task; @end @@ -163,9 +164,9 @@ self.passwordIncrementer.alpha = self.activeElement.type & MPElementTypeClassCalculated? 0.5f: 0; self.passwordEdit.alpha = self.activeElement.type & MPElementTypeClassStored? 0.5f: 0; - [self.typeButton setTitle:NSStringFromMPElementType(self.activeElement.type) + [self.typeButton setTitle:NSStringFromMPElementType((unsigned)self.activeElement.type) forState:UIControlStateNormal]; - self.typeButton.alpha = NSStringFromMPElementType(self.activeElement.type).length? 1: 0; + self.typeButton.alpha = NSStringFromMPElementType((unsigned)self.activeElement.type).length? 1: 0; self.contentField.enabled = NO; @@ -212,9 +213,7 @@ - (void)setHelpChapter:(NSString *)chapter { -#ifdef TESTFLIGHT [TestFlight passCheckpoint:[NSString stringWithFormat:MPTestFlightCheckpointHelpChapter, chapter]]; -#endif dispatch_async(dispatch_get_main_queue(), ^{ [self.helpView loadRequest: @@ -227,7 +226,7 @@ - (void)webViewDidFinishLoad:(UIWebView *)webView { NSString *error = [self.helpView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setClass('%@');", - ClassNameFromMPElementType(self.activeElement.type)]]; + ClassNameFromMPElementType((unsigned)self.activeElement.type)]]; if (error.length) err(@"helpView.setClass: %@", error); } @@ -285,42 +284,76 @@ [self showContentTip:@"Copied!" withIcon:nil]; -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointCopyToPasteboard]; -#endif } - (IBAction)incrementPasswordCounter { if (![self.activeElement isKindOfClass:[MPElementGeneratedEntity class]]) - // Not of a type that supports a password counter; + // Not of a type that supports a password counter. return; - [self updateElement:^{ - ++((MPElementGeneratedEntity *) self.activeElement).counter; - }]; + [self changeElementWithWarning: + @"You are incrementing the site's password counter.\n\n" + @"If you continue, a new password will be generated for this site. " + @"You will then need to update your account's old password to this newly generated password.\n" + @"You can reset the counter by holding down on this button." + do:^{ + ++((MPElementGeneratedEntity *) self.activeElement).counter; + }]; -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointIncrementPasswordCounter]; -#endif } -- (void)updateElement:(void (^)(void))updateElement { +- (IBAction)resetPasswordCounter:(UILongPressGestureRecognizer *)sender { - // Update password counter. + if (![self.activeElement isKindOfClass:[MPElementGeneratedEntity class]]) + // Not of a type that supports a password counter. + return; + if (((MPElementGeneratedEntity *)self.activeElement).counter == 1) + // Counter has initial value, no point resetting. + return; + + [self changeElementWithWarning: + @"You are resetting the site's password counter.\n\n" + @"If you continue, the site's password will change back to its original value. " + @"You will then need to update your account's password back to this original value." + do:^{ + ((MPElementGeneratedEntity *) self.activeElement).counter = 1; + }]; + + [TestFlight passCheckpoint:MPTestFlightCheckpointResetPasswordCounter]; +} + +- (void)changeElementWithWarning:(NSString *)warning do:(void (^)(void))task; { + + [PearlAlert showAlertWithTitle:@"Password Change" message:warning viewStyle:UIAlertViewStyleDefault + tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) { + if (buttonIndex == [alert cancelButtonIndex]) + return; + + [self changeElementWithoutWarningDo:task]; + } cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonContinue, nil]; +} + +- (void)changeElementWithoutWarningDo:(void (^)(void))task; { + + // Update element, keeping track of the old password. NSString *oldPassword = self.activeElement.description; - updateElement(); + task(); NSString *newPassword = self.activeElement.description; [self updateAnimated:YES]; // Show new and old password. if ([oldPassword length] && ![oldPassword isEqualToString:newPassword]) [self showAlertWithTitle:@"Password Changed!" message:l(@"The password for %@ has changed.\n\n" + @"IMPORTANT:\n" @"Don't forget to update the site with your new password! " @"Your old password was:\n" @"%@", self.activeElement.name, oldPassword)]; } + - (IBAction)editPassword { if (self.activeElement.type & MPElementTypeClassStored) { @@ -328,9 +361,7 @@ [self.contentField becomeFirstResponder]; } -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointEditPassword]; -#endif } - (IBAction)closeAlert { @@ -342,9 +373,7 @@ self.alertBody.text = nil; }]; -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointCloseAlert]; -#endif } - (IBAction)action:(id)sender { @@ -371,7 +400,7 @@ [self.navigationController pushViewController:settingsVC animated:YES]; break; } -#ifdef TESTFLIGHT +#ifdef ADHOC case 4: [TestFlight openFeedbackView]; break; @@ -386,13 +415,11 @@ } } -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointAction]; -#endif } cancelTitle:[PearlStrings get].commonButtonCancel destructiveTitle:nil otherTitles: [self isHelpVisible]? @"Hide Help": @"Show Help", @"FAQ", @"Tutorial", @"Settings", -#ifdef TESTFLIGHT +#ifdef ADHOC @"Feedback", #endif @"Sign Out", @@ -401,36 +428,38 @@ - (MPElementType)selectedType { - return self.activeElement.type; + return (unsigned)self.activeElement.type; } - (void)didSelectType:(MPElementType)type { - [self updateElement:^{ - // Update password type. - if (ClassFromMPElementType(type) != ClassFromMPElementType(self.activeElement.type)) - // Type requires a different class of element. Recreate the element. - [[MPAppDelegate managedObjectContext] performBlockAndWait:^{ - MPElementEntity *newElement = [NSEntityDescription insertNewObjectForEntityForName:ClassNameFromMPElementType(type) - inManagedObjectContext:[MPAppDelegate managedObjectContext]]; - newElement.name = self.activeElement.name; - newElement.mpHashHex = self.activeElement.mpHashHex; - newElement.uses = self.activeElement.uses; - newElement.lastUsed = self.activeElement.lastUsed; - - [[MPAppDelegate managedObjectContext] deleteObject:self.activeElement]; - self.activeElement = newElement; - }]; - - self.activeElement.type = type; - -#ifdef TESTFLIGHT - [TestFlight passCheckpoint:[NSString stringWithFormat:MPTestFlightCheckpointSelectType, NSStringFromMPElementType(type)]]; -#endif - - if (type & MPElementTypeClassStored && ![self.activeElement.description length]) - [self showContentTip:@"Tap to set a password." withIcon:self.contentTipEditIcon]; - }]; + [self changeElementWithWarning: + @"You are about to change the type of this password.\n\n" + @"If you continue, the password for this site will change. " + @"You will need to update your account's old password to the new one." + do:^{ + // Update password type. + if (ClassFromMPElementType(type) != ClassFromMPElementType((unsigned)self.activeElement.type)) + // Type requires a different class of element. Recreate the element. + [[MPAppDelegate managedObjectContext] performBlockAndWait:^{ + MPElementEntity *newElement = [NSEntityDescription insertNewObjectForEntityForName:ClassNameFromMPElementType(type) + inManagedObjectContext:[MPAppDelegate managedObjectContext]]; + newElement.name = self.activeElement.name; + newElement.mpHashHex = self.activeElement.mpHashHex; + newElement.uses = self.activeElement.uses; + newElement.lastUsed = self.activeElement.lastUsed; + + [[MPAppDelegate managedObjectContext] deleteObject:self.activeElement]; + self.activeElement = newElement; + }]; + + self.activeElement.type = type; + + [TestFlight passCheckpoint:[NSString stringWithFormat:MPTestFlightCheckpointSelectType, NSStringFromMPElementType(type)]]; + + if (type & MPElementTypeClassStored && ![self.activeElement.description length]) + [self showContentTip:@"Tap to set a password." withIcon:self.contentTipEditIcon]; + }]; } - (void)didSelectElement:(MPElementEntity *)element { @@ -443,17 +472,14 @@ [self showAlertWithTitle:@"New Site" message: l(@"You've just created a password for %@.\n\n" @"IMPORTANT:\n" - @"Don't forget to set or change the password for your account at %@ to the password above. " - @"It's best to do this right away. If you forget it, may get confusing later on " - @"to remember what password you need to use for logging into the site.", + @"Go to %@ and set or change the password for your account to the password above.\n" + @"Do this right away: if you forget, you may have trouble remembering which password to use to log into the site later on.", self.activeElement.name, self.activeElement.name)]; [self.searchDisplayController setActive:NO animated:YES]; self.searchDisplayController.searchBar.text = self.activeElement.name; -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointSelectElement]; -#endif } [self updateAnimated:YES]; @@ -479,7 +505,7 @@ // Content hasn't changed. return; - [self updateElement:^{ + [self changeElementWithoutWarningDo:^{ ((MPElementStoredEntity *) self.activeElement).content = self.contentField.text; }]; } @@ -489,9 +515,7 @@ navigationType:(UIWebViewNavigationType)navigationType { if (navigationType == UIWebViewNavigationTypeLinkClicked) { -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointExternalLink]; -#endif [[UIApplication sharedApplication] openURL:[request URL]]; return NO; diff --git a/MasterPassword/iOS/MPSearchDelegate.m b/MasterPassword/iOS/MPSearchDelegate.m index 2083530e..92c2f29a 100644 --- a/MasterPassword/iOS/MPSearchDelegate.m +++ b/MasterPassword/iOS/MPSearchDelegate.m @@ -41,8 +41,8 @@ - (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar { UITableView *tableView = self.searchDisplayController.searchResultsTableView; - for (NSUInteger section = 0; section < [self numberOfSectionsInTableView:tableView]; ++section) { - NSUInteger rowCount = [self tableView:tableView numberOfRowsInSection:section]; + for (NSInteger section = 0; section < [self numberOfSectionsInTableView:tableView]; ++section) { + NSInteger rowCount = [self tableView:tableView numberOfRowsInSection:section]; if (!rowCount) continue; @@ -54,9 +54,7 @@ - (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointCancelSearch]; -#endif [self.delegate didSelectElement:nil]; } @@ -189,13 +187,13 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return [[self.fetchedResultsController sections] count] + ([self.query length]? 1: 0); + return (signed)[[self.fetchedResultsController sections] count] + ([self.query length]? 1: 0); } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - if (section < [[self.fetchedResultsController sections] count]) - return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects]; + if (section < (signed)[[self.fetchedResultsController sections] count]) + return (signed)[[[self.fetchedResultsController sections] objectAtIndex:(unsigned)section] numberOfObjects]; return 1; } @@ -230,7 +228,7 @@ - (void)configureCell:(UITableViewCell *)cell inTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath { - if (indexPath.section < [[self.fetchedResultsController sections] count]) { + if (indexPath.section < (signed)[[self.fetchedResultsController sections] count]) { MPElementEntity *element = [self.fetchedResultsController objectAtIndexPath:indexPath]; cell.textLabel.text = element.name; @@ -245,7 +243,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - if (indexPath.section < [[self.fetchedResultsController sections] count]) + if (indexPath.section < (signed)[[self.fetchedResultsController sections] count]) [self.delegate didSelectElement:[self.fetchedResultsController objectAtIndexPath:indexPath]]; else { @@ -263,7 +261,7 @@ [self.fetchedResultsController.managedObjectContext performBlock:^{ MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([MPElementGeneratedEntity class]) inManagedObjectContext:self.fetchedResultsController.managedObjectContext]; - assert([element isKindOfClass:ClassFromMPElementType(element.type)]); + assert([element isKindOfClass:ClassFromMPElementType((unsigned)element.type)]); assert([MPAppDelegate get].keyHashHex); element.name = siteName; @@ -279,8 +277,8 @@ - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - if (section < [[self.fetchedResultsController sections] count]) - return [[[self.fetchedResultsController sections] objectAtIndex:section] name]; + if (section < (signed)[[self.fetchedResultsController sections] count]) + return [[[self.fetchedResultsController sections] objectAtIndex:(unsigned)section] name]; return @""; } @@ -297,15 +295,13 @@ - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { - if (indexPath.section < [[self.fetchedResultsController sections] count]) { + if (indexPath.section < (signed)[[self.fetchedResultsController sections] count]) { if (editingStyle == UITableViewCellEditingStyleDelete) [self.fetchedResultsController.managedObjectContext performBlock:^{ MPElementEntity *element = [self.fetchedResultsController objectAtIndexPath:indexPath]; [self.fetchedResultsController.managedObjectContext deleteObject:element]; -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointDeleteElement]; -#endif }]; } } diff --git a/MasterPassword/iOS/MPUnlockViewController.m b/MasterPassword/iOS/MPUnlockViewController.m index 4f1c705e..37acc4b3 100644 --- a/MasterPassword/iOS/MPUnlockViewController.m +++ b/MasterPassword/iOS/MPUnlockViewController.m @@ -173,7 +173,7 @@ typedef enum { dispatch_async(dispatch_get_main_queue(), ^{ [self showMessage:@"Success!" state:MPLockscreenSuccess]; - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 1.5f), dispatch_get_main_queue(), ^{ + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (long)(NSEC_PER_SEC * 1.5f)), dispatch_get_main_queue(), ^{ [self dismissModalViewControllerAnimated:YES]; }); }); @@ -214,9 +214,7 @@ typedef enum { [[MPAppDelegate get] loadKey:YES]; -#ifdef TESTFLIGHT [TestFlight passCheckpoint:MPTestFlightCheckpointMPChanged]; -#endif } cancelTitle:[PearlStrings get].commonButtonAbort otherTitles:[PearlStrings get].commonButtonContinue, nil]; diff --git a/MasterPassword/iOS/MainStoryboard_iPhone.storyboard b/MasterPassword/iOS/MainStoryboard_iPhone.storyboard index bfa12a90..e2c4c185 100644 --- a/MasterPassword/iOS/MainStoryboard_iPhone.storyboard +++ b/MasterPassword/iOS/MainStoryboard_iPhone.storyboard @@ -1,8 +1,9 @@ - + + - + @@ -399,6 +400,7 @@ The passwords aren't saved anywhere. This is a major advantage: if you lose you