iCloud sync fixes.
[REMOVED] OS X: Disabled ability to add new sites from OS X until I have time to implement it properly without causing duplicates etc. [MOVED] iCloud and Core Data support was centralised to iOS and OS X to make sure both platforms always use the same container configuration. [FIXED] iCloud sync problems. [REMOVED] iCloud KV is not used/needed.
This commit is contained in:
parent
26f8e086bb
commit
376953ae56
2
External/InAppSettingsKit
vendored
2
External/InAppSettingsKit
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 5fd23fd728d2e6e3216c6c2bd5a807d5316966d1
|
Subproject commit 3ae828f48a63e505bcef7a9a9a78df567706eebc
|
2
External/Pearl
vendored
2
External/Pearl
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 5736ed0cb528aeabbad5cec1ae133c9002be2983
|
Subproject commit e23abc67cd80ec03543eed48ffd97b30439b5c84
|
@ -2142,6 +2142,7 @@
|
|||||||
DAB8DA101503972100CED3BC /* PearlSCrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlSCrypt.h; sourceTree = "<group>"; };
|
DAB8DA101503972100CED3BC /* PearlSCrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PearlSCrypt.h; sourceTree = "<group>"; };
|
||||||
DAB8DA111503972100CED3BC /* PearlSCrypt.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlSCrypt.m; sourceTree = "<group>"; };
|
DAB8DA111503972100CED3BC /* PearlSCrypt.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PearlSCrypt.m; sourceTree = "<group>"; };
|
||||||
DAB8DA121503972100CED3BC /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
|
DAB8DA121503972100CED3BC /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
|
||||||
|
DAD312C71553051900A3F9ED /* MasterPassword.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = MasterPassword.entitlements; sourceTree = "<group>"; };
|
||||||
DADEA5A41503C9DD00FD084E /* e_os.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = e_os.h; sourceTree = "<group>"; };
|
DADEA5A41503C9DD00FD084E /* e_os.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = e_os.h; sourceTree = "<group>"; };
|
||||||
DADEA5A51503C9DD00FD084E /* e_os2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = e_os2.h; sourceTree = "<group>"; };
|
DADEA5A51503C9DD00FD084E /* e_os2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = e_os2.h; sourceTree = "<group>"; };
|
||||||
DADEA5A91503CE3000FD084E /* _MWERKS_GUSI_prefix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _MWERKS_GUSI_prefix.h; sourceTree = "<group>"; };
|
DADEA5A91503CE3000FD084E /* _MWERKS_GUSI_prefix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _MWERKS_GUSI_prefix.h; sourceTree = "<group>"; };
|
||||||
@ -4025,6 +4026,7 @@
|
|||||||
DAB8D992150374AD00CED3BC /* MasterPassword */ = {
|
DAB8D992150374AD00CED3BC /* MasterPassword */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
DAD312C71553051900A3F9ED /* MasterPassword.entitlements */,
|
||||||
DAB8D9B2150375C800CED3BC /* MasterPassword.xcdatamodeld */,
|
DAB8D9B2150375C800CED3BC /* MasterPassword.xcdatamodeld */,
|
||||||
DAB8D9B4150375C800CED3BC /* Mac */,
|
DAB8D9B4150375C800CED3BC /* Mac */,
|
||||||
DA600C2C150565FC008E9AB6 /* MPAppDelegate_Key.h */,
|
DA600C2C150565FC008E9AB6 /* MPAppDelegate_Key.h */,
|
||||||
@ -6064,6 +6066,7 @@
|
|||||||
DAB8D985150374AD00CED3BC /* Frameworks */,
|
DAB8D985150374AD00CED3BC /* Frameworks */,
|
||||||
DAB8D986150374AD00CED3BC /* Resources */,
|
DAB8D986150374AD00CED3BC /* Resources */,
|
||||||
DA60116B15060F11008E9AB6 /* CopyFiles */,
|
DA60116B15060F11008E9AB6 /* CopyFiles */,
|
||||||
|
DAD312C9155305B200A3F9ED /* ShellScript */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@ -6809,6 +6812,23 @@
|
|||||||
};
|
};
|
||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
|
DAD312C9155305B200A3F9ED /* ShellScript */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
DAB8D984150374AD00CED3BC /* Sources */ = {
|
DAB8D984150374AD00CED3BC /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
@ -7529,6 +7549,8 @@
|
|||||||
DAB8D9AA150374AD00CED3BC /* Debug */ = {
|
DAB8D9AA150374AD00CED3BC /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
CODE_SIGN_ENTITLEMENTS = MasterPassword/MasterPassword.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||||
GCC_PREFIX_HEADER = "MasterPassword/Mac/MasterPassword-Prefix.pch";
|
GCC_PREFIX_HEADER = "MasterPassword/Mac/MasterPassword-Prefix.pch";
|
||||||
INFOPLIST_FILE = "MasterPassword/Mac/MasterPassword-Info.plist";
|
INFOPLIST_FILE = "MasterPassword/Mac/MasterPassword-Info.plist";
|
||||||
@ -7538,6 +7560,8 @@
|
|||||||
DAB8D9AB150374AD00CED3BC /* Release */ = {
|
DAB8D9AB150374AD00CED3BC /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
CODE_SIGN_ENTITLEMENTS = MasterPassword/MasterPassword.entitlements;
|
||||||
|
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||||
GCC_PREFIX_HEADER = "MasterPassword/Mac/MasterPassword-Prefix.pch";
|
GCC_PREFIX_HEADER = "MasterPassword/Mac/MasterPassword-Prefix.pch";
|
||||||
INFOPLIST_FILE = "MasterPassword/Mac/MasterPassword-Info.plist";
|
INFOPLIST_FILE = "MasterPassword/Mac/MasterPassword-Info.plist";
|
||||||
|
@ -56,6 +56,12 @@
|
|||||||
ReferencedContainer = "container:MasterPassword-Mac.xcodeproj">
|
ReferencedContainer = "container:MasterPassword-Mac.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildableProductRunnable>
|
</BuildableProductRunnable>
|
||||||
|
<CommandLineArguments>
|
||||||
|
<CommandLineArgument
|
||||||
|
argument = "-com.apple.coredata.ubiquity.logLevel 3"
|
||||||
|
isEnabled = "YES">
|
||||||
|
</CommandLineArgument>
|
||||||
|
</CommandLineArguments>
|
||||||
<AdditionalOptions>
|
<AdditionalOptions>
|
||||||
</AdditionalOptions>
|
</AdditionalOptions>
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
|
@ -4107,7 +4107,6 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"\"$(SRCROOT)/TestFlight\"",
|
"\"$(SRCROOT)/TestFlight\"",
|
||||||
);
|
);
|
||||||
OTHER_LDFLAGS = "-ObjC";
|
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
@ -4126,7 +4125,6 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"\"$(SRCROOT)/TestFlight\"",
|
"\"$(SRCROOT)/TestFlight\"",
|
||||||
);
|
);
|
||||||
OTHER_LDFLAGS = "-ObjC";
|
|
||||||
};
|
};
|
||||||
name = AdHoc;
|
name = AdHoc;
|
||||||
};
|
};
|
||||||
@ -4224,7 +4222,6 @@
|
|||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"\"$(SRCROOT)/TestFlight\"",
|
"\"$(SRCROOT)/TestFlight\"",
|
||||||
);
|
);
|
||||||
OTHER_LDFLAGS = "-ObjC";
|
|
||||||
};
|
};
|
||||||
name = AppStore;
|
name = AppStore;
|
||||||
};
|
};
|
||||||
|
@ -39,8 +39,8 @@
|
|||||||
</MacroExpansion>
|
</MacroExpansion>
|
||||||
</TestAction>
|
</TestAction>
|
||||||
<LaunchAction
|
<LaunchAction
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
@ -56,6 +56,12 @@
|
|||||||
ReferencedContainer = "container:MasterPassword-iOS.xcodeproj">
|
ReferencedContainer = "container:MasterPassword-iOS.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildableProductRunnable>
|
</BuildableProductRunnable>
|
||||||
|
<CommandLineArguments>
|
||||||
|
<CommandLineArgument
|
||||||
|
argument = "-com.apple.coredata.ubiquity.logLevel 3"
|
||||||
|
isEnabled = "YES">
|
||||||
|
</CommandLineArgument>
|
||||||
|
</CommandLineArguments>
|
||||||
<AdditionalOptions>
|
<AdditionalOptions>
|
||||||
<AdditionalOption
|
<AdditionalOption
|
||||||
key = "NSZombieEnabled"
|
key = "NSZombieEnabled"
|
||||||
|
@ -8,7 +8,16 @@
|
|||||||
|
|
||||||
#import "MPAppDelegate.h"
|
#import "MPAppDelegate.h"
|
||||||
|
|
||||||
@interface MPAppDelegate ()
|
@interface MPAppDelegate () {
|
||||||
|
|
||||||
|
NSPersistentStoreCoordinator *_persistentStoreCoordinator;
|
||||||
|
NSManagedObjectModel *_managedObjectModel;
|
||||||
|
NSManagedObjectContext *_managedObjectContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
|
||||||
|
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
|
||||||
|
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
|
||||||
|
|
||||||
@property (strong, nonatomic) NSData *key;
|
@property (strong, nonatomic) NSData *key;
|
||||||
@property (strong, nonatomic) NSData *keyHash;
|
@property (strong, nonatomic) NSData *keyHash;
|
||||||
@ -20,6 +29,13 @@
|
|||||||
|
|
||||||
+ (MPAppDelegate *)get;
|
+ (MPAppDelegate *)get;
|
||||||
|
|
||||||
|
- (NSURL *)applicationFilesDirectory;
|
||||||
|
|
||||||
|
+ (NSManagedObjectModel *)managedObjectModel;
|
||||||
|
+ (NSManagedObjectContext *)managedObjectContext;
|
||||||
|
- (void)saveContext;
|
||||||
|
- (void)printStore;
|
||||||
|
|
||||||
- (void)loadStoredKey;
|
- (void)loadStoredKey;
|
||||||
- (void)signOut;
|
- (void)signOut;
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#import "MPConfig.h"
|
#import "MPConfig.h"
|
||||||
#import "MPAppDelegate_Key.h"
|
#import "MPAppDelegate_Key.h"
|
||||||
|
#import "MPElementEntity.h"
|
||||||
|
|
||||||
@implementation MPAppDelegate (Key)
|
@implementation MPAppDelegate (Key)
|
||||||
|
|
||||||
@ -35,6 +36,180 @@ static NSDictionary *keyHashQuery() {
|
|||||||
return MPKeyHashQuery;
|
return MPKeyHashQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSURL *)applicationFilesDirectory {
|
||||||
|
|
||||||
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||||
|
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
|
||||||
|
#else
|
||||||
|
NSURL *appSupportURL = [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask] lastObject];
|
||||||
|
NSURL *applicationFilesDirectory = [appSupportURL URLByAppendingPathComponent:@"com.lyndir.lhunath.MasterPassword"];
|
||||||
|
|
||||||
|
NSError *error = nil;
|
||||||
|
[[NSFileManager defaultManager] createDirectoryAtURL:applicationFilesDirectory withIntermediateDirectories:YES attributes:nil error:&error];
|
||||||
|
if (error)
|
||||||
|
err(@"Couldn't create application directory: %@, error occurred: %@", applicationFilesDirectory, error);
|
||||||
|
|
||||||
|
return applicationFilesDirectory;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Core Data stack
|
||||||
|
|
||||||
|
+ (NSManagedObjectContext *)managedObjectContext {
|
||||||
|
|
||||||
|
return [[self get] managedObjectContext];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSManagedObjectModel *)managedObjectModel {
|
||||||
|
|
||||||
|
return [[self get] managedObjectModel];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSManagedObjectModel *)managedObjectModel {
|
||||||
|
|
||||||
|
if (_managedObjectModel)
|
||||||
|
return _managedObjectModel;
|
||||||
|
|
||||||
|
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MasterPassword" withExtension:@"momd"];
|
||||||
|
return _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSManagedObjectContext *)managedObjectContext {
|
||||||
|
|
||||||
|
if (_managedObjectContext)
|
||||||
|
return _managedObjectContext;
|
||||||
|
|
||||||
|
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
|
||||||
|
if (coordinator) {
|
||||||
|
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
||||||
|
_managedObjectContext.persistentStoreCoordinator = coordinator;
|
||||||
|
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserverForName:NSPersistentStoreDidImportUbiquitousContentChangesNotification
|
||||||
|
object:coordinator
|
||||||
|
queue:nil
|
||||||
|
usingBlock:^(NSNotification *note) {
|
||||||
|
dbg(@"Ubiquitous content change: %@", note);
|
||||||
|
|
||||||
|
[_managedObjectContext performBlock:^{
|
||||||
|
[_managedObjectContext mergeChangesFromContextDidSaveNotification:note];
|
||||||
|
[self printStore];
|
||||||
|
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotification:
|
||||||
|
[NSNotification notificationWithName:MPNotificationStoreUpdated
|
||||||
|
object:self userInfo:[note userInfo]]];
|
||||||
|
}];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
return _managedObjectContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
|
||||||
|
|
||||||
|
if (_persistentStoreCoordinator)
|
||||||
|
return _persistentStoreCoordinator;
|
||||||
|
|
||||||
|
NSString *contentName = @"store";
|
||||||
|
NSURL *storeURL = [[self applicationFilesDirectory] URLByAppendingPathComponent:@"MasterPassword.sqlite"];
|
||||||
|
NSURL *contentURL = [[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]
|
||||||
|
URLByAppendingPathComponent:@"logs" isDirectory:YES];
|
||||||
|
|
||||||
|
//#if DEBUG
|
||||||
|
// dbg(@"Deleting store and content.");
|
||||||
|
// NSError *storeRemovalError = nil, *contentRemovalError = nil;
|
||||||
|
// [[NSFileManager defaultManager] removeItemAtURL:storeURL error:&storeRemovalError];
|
||||||
|
// if (storeRemovalError)
|
||||||
|
// err(@"Store removal error: %@", storeRemovalError);
|
||||||
|
// else
|
||||||
|
// [[NSFileManager defaultManager] removeItemAtURL:contentURL error:&contentRemovalError];
|
||||||
|
// if (contentRemovalError)
|
||||||
|
// err(@"Content removal error: %@", contentRemovalError);
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
|
||||||
|
[_persistentStoreCoordinator lock];
|
||||||
|
@try {
|
||||||
|
NSError *error = nil;
|
||||||
|
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL
|
||||||
|
options:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
|
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
|
||||||
|
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
|
||||||
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||||
|
NSFileProtectionComplete, NSPersistentStoreFileProtectionKey,
|
||||||
|
#endif
|
||||||
|
contentURL, NSPersistentStoreUbiquitousContentURLKey,
|
||||||
|
contentName, NSPersistentStoreUbiquitousContentNameKey,
|
||||||
|
nil]
|
||||||
|
error:&error]) {
|
||||||
|
ftl(@"Unresolved error %@, %@", error, [error userInfo]);
|
||||||
|
#if DEBUG
|
||||||
|
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];
|
||||||
|
wrn(@"Deleted datastore: %@", storeURL);
|
||||||
|
#endif
|
||||||
|
@throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@finally {
|
||||||
|
[_persistentStoreCoordinator unlock];
|
||||||
|
}
|
||||||
|
|
||||||
|
return _persistentStoreCoordinator;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)saveContext {
|
||||||
|
|
||||||
|
[self.managedObjectContext performBlock:^{
|
||||||
|
NSError *error = nil;
|
||||||
|
if ([self.managedObjectContext hasChanges] && ![self.managedObjectContext save:&error])
|
||||||
|
err(@"Unresolved error %@", error);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)printStore {
|
||||||
|
|
||||||
|
if (!_managedObjectModel || !_managedObjectContext) {
|
||||||
|
trc(@"Not printing store: store not initialized.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[self.managedObjectContext performBlock:^{
|
||||||
|
trc(@"=== All entities ===");
|
||||||
|
for(NSEntityDescription *entity in [_managedObjectModel entities]) {
|
||||||
|
NSFetchRequest *request = [NSFetchRequest new];
|
||||||
|
[request setEntity:entity];
|
||||||
|
NSError *error;
|
||||||
|
NSArray *results = [_managedObjectContext executeFetchRequest:request error:&error];
|
||||||
|
for(NSManagedObject *o in results) {
|
||||||
|
if ([o isKindOfClass:[MPElementEntity class]]) {
|
||||||
|
MPElementEntity *e = (MPElementEntity *)o;
|
||||||
|
trc(@"For descriptor: %@, found: %@: %@ (%@)", entity.name, [o class], e.name, e.mpHashHex);
|
||||||
|
} else {
|
||||||
|
trc(@"For descriptor: %@, found: %@", entity.name, [o class]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trc(@"---");
|
||||||
|
if ([MPAppDelegate get].keyHashHex) {
|
||||||
|
trc(@"=== Known sites ===");
|
||||||
|
NSFetchRequest *fetchRequest = [_managedObjectModel
|
||||||
|
fetchRequestFromTemplateWithName:@"MPElements"
|
||||||
|
substitutionVariables:[NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
|
@"", @"query",
|
||||||
|
[MPAppDelegate get].keyHashHex, @"mpHashHex",
|
||||||
|
nil]];
|
||||||
|
[fetchRequest setSortDescriptors:
|
||||||
|
[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"uses" ascending:NO]]];
|
||||||
|
|
||||||
|
NSError *error = nil;
|
||||||
|
for (MPElementEntity *e in [_managedObjectContext executeFetchRequest:fetchRequest error:&error]) {
|
||||||
|
trc(@"Found site: %@ (%@): %@", e.name, e.mpHashHex, e);
|
||||||
|
}
|
||||||
|
trc(@"---");
|
||||||
|
} else
|
||||||
|
trc(@"Not printing sites: master password not set.");
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)forgetKey {
|
- (void)forgetKey {
|
||||||
|
|
||||||
dbg(@"Deleting master key and hash from key chain.");
|
dbg(@"Deleting master key and hash from key chain.");
|
||||||
@ -42,7 +217,9 @@ static NSDictionary *keyHashQuery() {
|
|||||||
[PearlKeyChain deleteItemForQuery:keyHashQuery()];
|
[PearlKeyChain deleteItemForQuery:keyHashQuery()];
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPNotificationKeyForgotten object:self];
|
[[NSNotificationCenter defaultCenter] postNotificationName:MPNotificationKeyForgotten object:self];
|
||||||
|
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||||
[TestFlight passCheckpoint:MPTestFlightCheckpointMPForgotten];
|
[TestFlight passCheckpoint:MPTestFlightCheckpointMPForgotten];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)signOut {
|
- (void)signOut {
|
||||||
@ -61,7 +238,9 @@ static NSDictionary *keyHashQuery() {
|
|||||||
// Key should not be stored in keychain. Delete it.
|
// Key should not be stored in keychain. Delete it.
|
||||||
dbg(@"Deleting key from key chain.");
|
dbg(@"Deleting key from key chain.");
|
||||||
[PearlKeyChain deleteItemForQuery:keyQuery()];
|
[PearlKeyChain deleteItemForQuery:keyQuery()];
|
||||||
|
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||||
[TestFlight passCheckpoint:MPTestFlightCheckpointMPUnstored];
|
[TestFlight passCheckpoint:MPTestFlightCheckpointMPUnstored];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,11 +271,15 @@ static NSDictionary *keyHashQuery() {
|
|||||||
if (![keyHash isEqual:tryKeyHash]) {
|
if (![keyHash isEqual:tryKeyHash]) {
|
||||||
dbg(@"Key phrase hash mismatch. Expected: %@, answer: %@.", keyHash, tryKeyHash);
|
dbg(@"Key phrase hash mismatch. Expected: %@, answer: %@.", keyHash, tryKeyHash);
|
||||||
|
|
||||||
|
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||||
[TestFlight passCheckpoint:MPTestFlightCheckpointMPMismatch];
|
[TestFlight passCheckpoint:MPTestFlightCheckpointMPMismatch];
|
||||||
|
#endif
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||||
[TestFlight passCheckpoint:MPTestFlightCheckpointMPAsked];
|
[TestFlight passCheckpoint:MPTestFlightCheckpointMPAsked];
|
||||||
|
#endif
|
||||||
|
|
||||||
[self updateKey:tryKey];
|
[self updateKey:tryKey];
|
||||||
return YES;
|
return YES;
|
||||||
@ -134,7 +317,9 @@ static NSDictionary *keyHashQuery() {
|
|||||||
nil]];
|
nil]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||||
[TestFlight passCheckpoint:[NSString stringWithFormat:MPTestFlightCheckpointSetKeyphraseLength, key.length]];
|
[TestFlight passCheckpoint:[NSString stringWithFormat:MPTestFlightCheckpointSetKeyphraseLength, key.length]];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,16 +16,15 @@
|
|||||||
|
|
||||||
- (id)content {
|
- (id)content {
|
||||||
|
|
||||||
assert(self.type & MPElementTypeClassCalculated);
|
if (!(self.type & MPElementTypeClassCalculated)) {
|
||||||
|
err(@"Corrupt element: %@, type: %d, does not match class: %@", self.name, self.type, [self class]);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
if (![self.name length])
|
if (![self.name length])
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
if (self.type & MPElementTypeClassCalculated)
|
|
||||||
return MPCalculateContent((unsigned)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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -104,14 +104,24 @@ NSString *ClassNameFromMPElementType(MPElementType type) {
|
|||||||
static NSDictionary *MPTypes_ciphers = nil;
|
static NSDictionary *MPTypes_ciphers = nil;
|
||||||
NSString *MPCalculateContent(MPElementType type, NSString *name, NSData *key, int16_t counter) {
|
NSString *MPCalculateContent(MPElementType type, NSString *name, NSData *key, int16_t counter) {
|
||||||
|
|
||||||
assert(type & MPElementTypeClassCalculated);
|
if (!name) {
|
||||||
|
err(@"Missing name.");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
if (!(type & MPElementTypeClassCalculated)) {
|
||||||
|
err(@"Incorrect type (is not MPElementTypeClassCalculated): %d, for: %@", type, name);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
if (!key) {
|
||||||
|
err(@"Key not set.");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
if (MPTypes_ciphers == nil)
|
if (MPTypes_ciphers == nil)
|
||||||
MPTypes_ciphers = [NSDictionary dictionaryWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"ciphers"
|
MPTypes_ciphers = [NSDictionary dictionaryWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"ciphers"
|
||||||
withExtension:@"plist"]];
|
withExtension:@"plist"]];
|
||||||
|
|
||||||
// Determine the hash whose bytes will be used for calculating a password: md4(name-key)
|
// Determine the hash whose bytes will be used for calculating a password: md4(name-key)
|
||||||
assert(name && key);
|
|
||||||
uint16_t ncounter = htons(counter);
|
uint16_t ncounter = htons(counter);
|
||||||
trc(@"key hash from: %@-%@-%u", name, key, ncounter);
|
trc(@"key hash from: %@-%@-%u", name, key, ncounter);
|
||||||
NSData *keyHash = [[NSData dataByConcatenatingWithDelimitor:'-' datas:
|
NSData *keyHash = [[NSData dataByConcatenatingWithDelimitor:'-' datas:
|
||||||
|
@ -13,13 +13,6 @@
|
|||||||
|
|
||||||
@property (assign) IBOutlet NSWindow *window;
|
@property (assign) IBOutlet NSWindow *window;
|
||||||
|
|
||||||
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
|
|
||||||
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
|
|
||||||
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
|
|
||||||
|
|
||||||
+ (NSManagedObjectModel *)managedObjectModel;
|
|
||||||
+ (NSManagedObjectContext *)managedObjectContext;
|
|
||||||
|
|
||||||
- (IBAction)saveAction:(id)sender;
|
- (IBAction)saveAction:(id)sender;
|
||||||
|
|
||||||
- (void)loadKey;
|
- (void)loadKey;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#import "MPAppDelegate_Key.h"
|
#import "MPAppDelegate_Key.h"
|
||||||
#import "MPConfig.h"
|
#import "MPConfig.h"
|
||||||
|
#import "MPElementEntity.h"
|
||||||
|
|
||||||
|
|
||||||
@interface MPAppDelegate ()
|
@interface MPAppDelegate ()
|
||||||
@ -18,11 +19,9 @@
|
|||||||
|
|
||||||
@implementation MPAppDelegate
|
@implementation MPAppDelegate
|
||||||
@synthesize window = _window;
|
@synthesize window = _window;
|
||||||
@synthesize persistentStoreCoordinator = __persistentStoreCoordinator;
|
|
||||||
@synthesize managedObjectModel = __managedObjectModel;
|
|
||||||
@synthesize managedObjectContext = __managedObjectContext;
|
|
||||||
@synthesize passwordWindow;
|
@synthesize passwordWindow;
|
||||||
|
|
||||||
|
@dynamic persistentStoreCoordinator, managedObjectModel, managedObjectContext;
|
||||||
@synthesize key;
|
@synthesize key;
|
||||||
@synthesize keyHash;
|
@synthesize keyHash;
|
||||||
@synthesize keyHashHex;
|
@synthesize keyHashHex;
|
||||||
@ -32,22 +31,14 @@
|
|||||||
[MPConfig get];
|
[MPConfig get];
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
[PearlLogger get].autoprintLevel = PearlLogLevelDebug;
|
[PearlLogger get].autoprintLevel = PearlLogLevelTrace
|
||||||
|
;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSManagedObjectContext *)managedObjectContext {
|
|
||||||
|
|
||||||
return [[self get] managedObjectContext];
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (NSManagedObjectModel *)managedObjectModel {
|
|
||||||
|
|
||||||
return [[self get] managedObjectModel];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||||
|
|
||||||
|
[self managedObjectContext];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applicationDidBecomeActive:(NSNotification *)notification {
|
- (void)applicationDidBecomeActive:(NSNotification *)notification {
|
||||||
@ -73,6 +64,7 @@
|
|||||||
informativeTextWithFormat:@"Your master password is required to unlock the application."];
|
informativeTextWithFormat:@"Your master password is required to unlock the application."];
|
||||||
NSTextField *passwordField = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 22)];
|
NSTextField *passwordField = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 22)];
|
||||||
[alert setAccessoryView:passwordField];
|
[alert setAccessoryView:passwordField];
|
||||||
|
[passwordField becomeFirstResponder];
|
||||||
[alert layout];
|
[alert layout];
|
||||||
do {
|
do {
|
||||||
NSInteger button = [alert runModal];
|
NSInteger button = [alert runModal];
|
||||||
@ -96,97 +88,11 @@
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (![self tryMasterPassword:[passwordField stringValue]]);
|
} while (![self tryMasterPassword:[passwordField stringValue]]);
|
||||||
|
|
||||||
|
[self printStore];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSURL *)applicationFilesDirectory {
|
|
||||||
|
|
||||||
NSURL *appSupportURL = [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask] lastObject];
|
|
||||||
NSURL *applicationFilesDirectory = [appSupportURL URLByAppendingPathComponent:@"com.lyndir.lhunath.MasterPassword"];
|
|
||||||
|
|
||||||
NSError *error = nil;
|
|
||||||
[[NSFileManager defaultManager] createDirectoryAtURL:applicationFilesDirectory withIntermediateDirectories:YES attributes:nil error:&error];
|
|
||||||
if (error)
|
|
||||||
[[NSApplication sharedApplication] presentError:error];
|
|
||||||
|
|
||||||
return applicationFilesDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Core Data stack
|
|
||||||
|
|
||||||
- (NSManagedObjectModel *)managedObjectModel {
|
|
||||||
|
|
||||||
if (__managedObjectModel)
|
|
||||||
return __managedObjectModel;
|
|
||||||
|
|
||||||
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MasterPassword" withExtension:@"momd"];
|
|
||||||
return __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSManagedObjectContext *)managedObjectContext {
|
|
||||||
|
|
||||||
if (__managedObjectContext)
|
|
||||||
return __managedObjectContext;
|
|
||||||
|
|
||||||
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
|
|
||||||
if (coordinator) {
|
|
||||||
__managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
|
||||||
__managedObjectContext.persistentStoreCoordinator = coordinator;
|
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSPersistentStoreDidImportUbiquitousContentChangesNotification
|
|
||||||
object:coordinator
|
|
||||||
queue:nil
|
|
||||||
usingBlock:^(NSNotification *note) {
|
|
||||||
dbg(@"Ubiquitous content change: %@", note);
|
|
||||||
|
|
||||||
[__managedObjectContext performBlock:^{
|
|
||||||
[__managedObjectContext mergeChangesFromContextDidSaveNotification:note];
|
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] postNotification:
|
|
||||||
[NSNotification notificationWithName:MPNotificationStoreUpdated
|
|
||||||
object:self userInfo:[note userInfo]]];
|
|
||||||
}];
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
return __managedObjectContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
|
|
||||||
|
|
||||||
if (__persistentStoreCoordinator)
|
|
||||||
return __persistentStoreCoordinator;
|
|
||||||
|
|
||||||
NSURL *storeURL = [[self applicationFilesDirectory] URLByAppendingPathComponent:@"MasterPassword.sqlite"];
|
|
||||||
|
|
||||||
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
|
|
||||||
[__persistentStoreCoordinator lock];
|
|
||||||
NSError *error = nil;
|
|
||||||
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL
|
|
||||||
options:[NSDictionary dictionaryWithObjectsAndKeys:
|
|
||||||
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
|
|
||||||
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
|
|
||||||
[[[NSFileManager defaultManager]
|
|
||||||
URLForUbiquityContainerIdentifier:nil]
|
|
||||||
URLByAppendingPathComponent:@"store"
|
|
||||||
isDirectory:YES], NSPersistentStoreUbiquitousContentURLKey,
|
|
||||||
@"MasterPassword.store", NSPersistentStoreUbiquitousContentNameKey,
|
|
||||||
nil]
|
|
||||||
error:&error]) {
|
|
||||||
err(@"Unresolved error %@, %@", error, [error userInfo]);
|
|
||||||
#if DEBUG
|
|
||||||
wrn(@"Deleted datastore: %@", storeURL);
|
|
||||||
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
[[NSApplication sharedApplication] presentError:error];
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
[__persistentStoreCoordinator unlock];
|
|
||||||
|
|
||||||
return __persistentStoreCoordinator;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window {
|
- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window {
|
||||||
|
|
||||||
return [[self managedObjectContext] undoManager];
|
return [[self managedObjectContext] undoManager];
|
||||||
@ -210,7 +116,7 @@
|
|||||||
{
|
{
|
||||||
// Save changes in the application's managed object context before the application terminates.
|
// Save changes in the application's managed object context before the application terminates.
|
||||||
|
|
||||||
if (!__managedObjectContext) {
|
if (!_managedObjectContext) {
|
||||||
return NSTerminateNow;
|
return NSTerminateNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,5 +11,6 @@
|
|||||||
@interface MPPasswordWindowController : NSWindowController <NSTextFieldDelegate>
|
@interface MPPasswordWindowController : NSWindowController <NSTextFieldDelegate>
|
||||||
@property (weak) IBOutlet NSTextField *siteField;
|
@property (weak) IBOutlet NSTextField *siteField;
|
||||||
@property (weak) IBOutlet NSTextField *contentField;
|
@property (weak) IBOutlet NSTextField *contentField;
|
||||||
|
- (IBAction)empty:(id)sender;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -66,10 +66,17 @@
|
|||||||
if (self.siteResults)
|
if (self.siteResults)
|
||||||
for (MPElementEntity *element in self.siteResults)
|
for (MPElementEntity *element in self.siteResults)
|
||||||
[mutableResults addObject:element.name];
|
[mutableResults addObject:element.name];
|
||||||
[mutableResults addObject:query];
|
// [mutableResults addObject:query]; // For when the app should be able to create new sites.
|
||||||
return mutableResults;
|
return mutableResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector {
|
||||||
|
|
||||||
|
dbg(@"Selector = %@", NSStringFromSelector(commandSelector));
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)controlTextDidEndEditing:(NSNotification *)obj {
|
- (void)controlTextDidEndEditing:(NSNotification *)obj {
|
||||||
|
|
||||||
if (obj.object == self.siteField) {
|
if (obj.object == self.siteField) {
|
||||||
@ -92,24 +99,37 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
else
|
// For when the app should be able to create new sites.
|
||||||
[[MPAppDelegate get].managedObjectContext performBlock:^{
|
// else
|
||||||
MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([MPElementGeneratedEntity class])
|
// [[MPAppDelegate get].managedObjectContext performBlock:^{
|
||||||
inManagedObjectContext:[MPAppDelegate get].managedObjectContext];
|
// MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([MPElementGeneratedEntity class])
|
||||||
assert([element isKindOfClass:ClassFromMPElementType(element.type)]);
|
// inManagedObjectContext:[MPAppDelegate get].managedObjectContext];
|
||||||
assert([MPAppDelegate get].keyHashHex);
|
// assert([element isKindOfClass:ClassFromMPElementType(element.type)]);
|
||||||
|
// assert([MPAppDelegate get].keyHashHex);
|
||||||
element.name = siteName;
|
//
|
||||||
element.mpHashHex = [MPAppDelegate get].keyHashHex;
|
// element.name = siteName;
|
||||||
|
// element.mpHashHex = [MPAppDelegate get].keyHashHex;
|
||||||
NSString *description = [element description];
|
//
|
||||||
[element use];
|
// NSString *description = [element description];
|
||||||
|
// [element use];
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
//
|
||||||
[self.contentField setStringValue:description? description: @""];
|
// dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
});
|
// [self.contentField setStringValue:description? description: @""];
|
||||||
}];
|
// });
|
||||||
|
// }];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (IBAction)empty:(id)sender {
|
||||||
|
|
||||||
|
for(NSEntityDescription *entity in [[MPAppDelegate managedObjectModel] entities]) {
|
||||||
|
NSFetchRequest *request = [NSFetchRequest new];
|
||||||
|
[request setEntity:entity];
|
||||||
|
NSError *error;
|
||||||
|
NSArray *results = [[MPAppDelegate managedObjectContext] executeFetchRequest:request error:&error];
|
||||||
|
for(NSManagedObject *o in results) {
|
||||||
|
[[MPAppDelegate managedObjectContext] deleteObject:o];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
@ -3,20 +3,22 @@
|
|||||||
<data>
|
<data>
|
||||||
<int key="IBDocument.SystemTarget">1070</int>
|
<int key="IBDocument.SystemTarget">1070</int>
|
||||||
<string key="IBDocument.SystemVersion">11D50</string>
|
<string key="IBDocument.SystemVersion">11D50</string>
|
||||||
<string key="IBDocument.InterfaceBuilderVersion">2177</string>
|
<string key="IBDocument.InterfaceBuilderVersion">2182</string>
|
||||||
<string key="IBDocument.AppKitVersion">1138.32</string>
|
<string key="IBDocument.AppKitVersion">1138.32</string>
|
||||||
<string key="IBDocument.HIToolboxVersion">568.00</string>
|
<string key="IBDocument.HIToolboxVersion">568.00</string>
|
||||||
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
|
||||||
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
<string key="NS.object.0">2177</string>
|
<string key="NS.object.0">2182</string>
|
||||||
</object>
|
</object>
|
||||||
<array key="IBDocument.IntegratedClassDependencies">
|
<array key="IBDocument.IntegratedClassDependencies">
|
||||||
<string>NSTextField</string>
|
<string>NSTextField</string>
|
||||||
<string>NSTextFieldCell</string>
|
|
||||||
<string>NSWindowTemplate</string>
|
|
||||||
<string>NSView</string>
|
<string>NSView</string>
|
||||||
<string>IBNSLayoutConstraint</string>
|
<string>NSWindowTemplate</string>
|
||||||
<string>NSCustomObject</string>
|
<string>NSCustomObject</string>
|
||||||
|
<string>IBNSLayoutConstraint</string>
|
||||||
|
<string>NSButtonCell</string>
|
||||||
|
<string>NSButton</string>
|
||||||
|
<string>NSTextFieldCell</string>
|
||||||
</array>
|
</array>
|
||||||
<array key="IBDocument.PluginDependencies">
|
<array key="IBDocument.PluginDependencies">
|
||||||
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
@ -55,7 +57,7 @@
|
|||||||
<int key="NSvFlags">268</int>
|
<int key="NSvFlags">268</int>
|
||||||
<string key="NSFrame">{{140, 92}, {200, 22}}</string>
|
<string key="NSFrame">{{140, 92}, {200, 22}}</string>
|
||||||
<reference key="NSSuperview" ref="258451033"/>
|
<reference key="NSSuperview" ref="258451033"/>
|
||||||
<reference key="NSNextKeyView" ref="226215720"/>
|
<reference key="NSNextKeyView" ref="524129387"/>
|
||||||
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
<string key="NSReuseIdentifierKey">_NS:9</string>
|
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||||
<bool key="NSEnabled">YES</bool>
|
<bool key="NSEnabled">YES</bool>
|
||||||
@ -63,7 +65,7 @@
|
|||||||
<int key="NSCellFlags">-1804468671</int>
|
<int key="NSCellFlags">-1804468671</int>
|
||||||
<int key="NSCellFlags2">138413120</int>
|
<int key="NSCellFlags2">138413120</int>
|
||||||
<string key="NSContents"/>
|
<string key="NSContents"/>
|
||||||
<object class="NSFont" key="NSSupport">
|
<object class="NSFont" key="NSSupport" id="590895625">
|
||||||
<string key="NSName">LucidaGrande</string>
|
<string key="NSName">LucidaGrande</string>
|
||||||
<double key="NSSize">13</double>
|
<double key="NSSize">13</double>
|
||||||
<int key="NSfFlags">1044</int>
|
<int key="NSfFlags">1044</int>
|
||||||
@ -128,6 +130,30 @@
|
|||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="NSButton" id="524129387">
|
||||||
|
<reference key="NSNextResponder" ref="258451033"/>
|
||||||
|
<int key="NSvFlags">268</int>
|
||||||
|
<string key="NSFrame">{{384, 85}, {82, 32}}</string>
|
||||||
|
<reference key="NSSuperview" ref="258451033"/>
|
||||||
|
<reference key="NSNextKeyView" ref="226215720"/>
|
||||||
|
<int key="NSViewLayerContentsRedrawPolicy">2</int>
|
||||||
|
<string key="NSReuseIdentifierKey">_NS:9</string>
|
||||||
|
<bool key="NSEnabled">YES</bool>
|
||||||
|
<object class="NSButtonCell" key="NSCell" id="1001833466">
|
||||||
|
<int key="NSCellFlags">67239424</int>
|
||||||
|
<int key="NSCellFlags2">134217728</int>
|
||||||
|
<string key="NSContents">Empty</string>
|
||||||
|
<reference key="NSSupport" ref="590895625"/>
|
||||||
|
<string key="NSCellIdentifier">_NS:9</string>
|
||||||
|
<reference key="NSControlView" ref="524129387"/>
|
||||||
|
<int key="NSButtonFlags">-2038284033</int>
|
||||||
|
<int key="NSButtonFlags2">129</int>
|
||||||
|
<string key="NSAlternateContents"/>
|
||||||
|
<string key="NSKeyEquivalent"/>
|
||||||
|
<int key="NSPeriodicDelay">200</int>
|
||||||
|
<int key="NSPeriodicInterval">25</int>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
</array>
|
</array>
|
||||||
<string key="NSFrameSize">{480, 134}</string>
|
<string key="NSFrameSize">{480, 134}</string>
|
||||||
<reference key="NSSuperview"/>
|
<reference key="NSSuperview"/>
|
||||||
@ -168,6 +194,14 @@
|
|||||||
</object>
|
</object>
|
||||||
<int key="connectionID">42</int>
|
<int key="connectionID">42</int>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="IBConnectionRecord">
|
||||||
|
<object class="IBActionConnection" key="connection">
|
||||||
|
<string key="label">empty:</string>
|
||||||
|
<reference key="source" ref="1001"/>
|
||||||
|
<reference key="destination" ref="524129387"/>
|
||||||
|
</object>
|
||||||
|
<int key="connectionID">48</int>
|
||||||
|
</object>
|
||||||
<object class="IBConnectionRecord">
|
<object class="IBConnectionRecord">
|
||||||
<object class="IBOutletConnection" key="connection">
|
<object class="IBOutletConnection" key="connection">
|
||||||
<string key="label">delegate</string>
|
<string key="label">delegate</string>
|
||||||
@ -385,6 +419,39 @@
|
|||||||
</object>
|
</object>
|
||||||
<reference ref="226215720"/>
|
<reference ref="226215720"/>
|
||||||
<reference ref="291791585"/>
|
<reference ref="291791585"/>
|
||||||
|
<reference ref="524129387"/>
|
||||||
|
<object class="IBNSLayoutConstraint" id="118079668">
|
||||||
|
<reference key="firstItem" ref="258451033"/>
|
||||||
|
<int key="firstAttribute">6</int>
|
||||||
|
<int key="relation">0</int>
|
||||||
|
<reference key="secondItem" ref="524129387"/>
|
||||||
|
<int key="secondAttribute">6</int>
|
||||||
|
<float key="multiplier">1</float>
|
||||||
|
<object class="IBNSLayoutSymbolicConstant" key="constant">
|
||||||
|
<double key="value">20</double>
|
||||||
|
</object>
|
||||||
|
<float key="priority">1000</float>
|
||||||
|
<int key="scoringType">8</int>
|
||||||
|
<float key="scoringTypeFloat">29</float>
|
||||||
|
<int key="contentType">3</int>
|
||||||
|
<reference key="containingView" ref="258451033"/>
|
||||||
|
</object>
|
||||||
|
<object class="IBNSLayoutConstraint" id="840794562">
|
||||||
|
<reference key="firstItem" ref="524129387"/>
|
||||||
|
<int key="firstAttribute">11</int>
|
||||||
|
<int key="relation">0</int>
|
||||||
|
<reference key="secondItem" ref="291791585"/>
|
||||||
|
<int key="secondAttribute">11</int>
|
||||||
|
<float key="multiplier">1</float>
|
||||||
|
<object class="IBLayoutConstant" key="constant">
|
||||||
|
<double key="value">0.0</double>
|
||||||
|
</object>
|
||||||
|
<float key="priority">1000</float>
|
||||||
|
<int key="scoringType">6</int>
|
||||||
|
<float key="scoringTypeFloat">24</float>
|
||||||
|
<int key="contentType">2</int>
|
||||||
|
<reference key="containingView" ref="258451033"/>
|
||||||
|
</object>
|
||||||
</array>
|
</array>
|
||||||
<reference key="parent" ref="45434518"/>
|
<reference key="parent" ref="45434518"/>
|
||||||
</object>
|
</object>
|
||||||
@ -485,6 +552,29 @@
|
|||||||
<reference key="object" ref="254722226"/>
|
<reference key="object" ref="254722226"/>
|
||||||
<reference key="parent" ref="226215720"/>
|
<reference key="parent" ref="226215720"/>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">44</int>
|
||||||
|
<reference key="object" ref="524129387"/>
|
||||||
|
<array class="NSMutableArray" key="children">
|
||||||
|
<reference ref="1001833466"/>
|
||||||
|
</array>
|
||||||
|
<reference key="parent" ref="258451033"/>
|
||||||
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">45</int>
|
||||||
|
<reference key="object" ref="1001833466"/>
|
||||||
|
<reference key="parent" ref="524129387"/>
|
||||||
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">46</int>
|
||||||
|
<reference key="object" ref="118079668"/>
|
||||||
|
<reference key="parent" ref="258451033"/>
|
||||||
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">47</int>
|
||||||
|
<reference key="object" ref="840794562"/>
|
||||||
|
<reference key="parent" ref="258451033"/>
|
||||||
|
</object>
|
||||||
</array>
|
</array>
|
||||||
</object>
|
</object>
|
||||||
<dictionary class="NSMutableDictionary" key="flattenedProperties">
|
<dictionary class="NSMutableDictionary" key="flattenedProperties">
|
||||||
@ -495,7 +585,7 @@
|
|||||||
<boolean value="YES" key="22.IBNSWindowAutoPositionCentersVertical"/>
|
<boolean value="YES" key="22.IBNSWindowAutoPositionCentersVertical"/>
|
||||||
<string key="22.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string key="22.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
<boolean value="YES" key="22.NSWindowTemplate.visibleAtLaunch"/>
|
<boolean value="YES" key="22.NSWindowTemplate.visibleAtLaunch"/>
|
||||||
<array class="NSMutableArray" key="23.IBNSViewMetadataConstraints">
|
<array key="23.IBNSViewMetadataConstraints">
|
||||||
<reference ref="137127436"/>
|
<reference ref="137127436"/>
|
||||||
<reference ref="582018795"/>
|
<reference ref="582018795"/>
|
||||||
<reference ref="453166348"/>
|
<reference ref="453166348"/>
|
||||||
@ -506,6 +596,8 @@
|
|||||||
<reference ref="490796257"/>
|
<reference ref="490796257"/>
|
||||||
<reference ref="51508433"/>
|
<reference ref="51508433"/>
|
||||||
<reference ref="456428551"/>
|
<reference ref="456428551"/>
|
||||||
|
<reference ref="118079668"/>
|
||||||
|
<reference ref="840794562"/>
|
||||||
</array>
|
</array>
|
||||||
<string key="23.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string key="23.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
<string key="24.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string key="24.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
@ -528,12 +620,17 @@
|
|||||||
<string key="36.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string key="36.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
<string key="37.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string key="37.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
<string key="38.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
<string key="38.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
|
<boolean value="NO" key="44.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
|
||||||
|
<string key="44.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
|
<string key="45.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
|
<string key="46.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
|
<string key="47.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
|
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
|
||||||
<nil key="activeLocalization"/>
|
<nil key="activeLocalization"/>
|
||||||
<dictionary class="NSMutableDictionary" key="localizations"/>
|
<dictionary class="NSMutableDictionary" key="localizations"/>
|
||||||
<nil key="sourceID"/>
|
<nil key="sourceID"/>
|
||||||
<int key="maxID">43</int>
|
<int key="maxID">48</int>
|
||||||
</object>
|
</object>
|
||||||
<object class="IBClassDescriber" key="IBDocument.Classes"/>
|
<object class="IBClassDescriber" key="IBDocument.Classes"/>
|
||||||
<int key="IBDocument.localizationMode">0</int>
|
<int key="IBDocument.localizationMode">0</int>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>iTunesArtwork-Rounded.png</string>
|
<string>iTunesArtwork-Rounded.png</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>com.lyndir.lhunath.${PRODUCT_NAME:rfc1034identifier}</string>
|
<string>com.lyndir.lhunath.${PRODUCT_NAME:rfc1034identifier}.Mac</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
@ -17,11 +17,11 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.0</string>
|
<string>[auto]</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1</string>
|
<string>[auto]</string>
|
||||||
<key>LSApplicationCategoryType</key>
|
<key>LSApplicationCategoryType</key>
|
||||||
<string>public.app-category.productivity</string>
|
<string>public.app-category.productivity</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
12
MasterPassword/MasterPassword.entitlements
Normal file
12
MasterPassword/MasterPassword.entitlements
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.developer.ubiquity-container-identifiers</key>
|
||||||
|
<array>
|
||||||
|
<string>$(TeamIdentifierPrefix)com.lyndir.lhunath.MasterPassword.1</string>
|
||||||
|
</array>
|
||||||
|
<key>com.apple.security.app-sandbox</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@ -10,16 +10,6 @@
|
|||||||
|
|
||||||
@interface MPAppDelegate : PearlAppDelegate
|
@interface MPAppDelegate : PearlAppDelegate
|
||||||
|
|
||||||
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
|
|
||||||
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
|
|
||||||
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
|
|
||||||
|
|
||||||
+ (NSManagedObjectModel *)managedObjectModel;
|
|
||||||
+ (NSManagedObjectContext *)managedObjectContext;
|
|
||||||
|
|
||||||
- (void)saveContext;
|
|
||||||
- (NSURL *)applicationDocumentsDirectory;
|
|
||||||
|
|
||||||
- (void)showGuide;
|
- (void)showGuide;
|
||||||
- (void)loadKey:(BOOL)animated;
|
- (void)loadKey:(BOOL)animated;
|
||||||
|
|
||||||
|
@ -263,118 +263,6 @@
|
|||||||
[TestFlight passCheckpoint:MPTestFlightCheckpointDeactivated];
|
[TestFlight passCheckpoint:MPTestFlightCheckpointDeactivated];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSManagedObjectContext *)managedObjectContext {
|
|
||||||
|
|
||||||
return [[self get] managedObjectContext];
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (NSManagedObjectModel *)managedObjectModel {
|
|
||||||
|
|
||||||
return [[self get] managedObjectModel];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)saveContext {
|
|
||||||
|
|
||||||
[self.managedObjectContext performBlock:^{
|
|
||||||
NSError *error = nil;
|
|
||||||
if ([self.managedObjectContext hasChanges] && ![self.managedObjectContext save:&error])
|
|
||||||
err(@"Unresolved error %@", error);
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Core Data stack
|
|
||||||
|
|
||||||
- (NSManagedObjectModel *)managedObjectModel {
|
|
||||||
|
|
||||||
if (__managedObjectModel)
|
|
||||||
return __managedObjectModel;
|
|
||||||
|
|
||||||
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MasterPassword" withExtension:@"momd"];
|
|
||||||
return __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSManagedObjectContext *)managedObjectContext {
|
|
||||||
|
|
||||||
if (__managedObjectContext)
|
|
||||||
return __managedObjectContext;
|
|
||||||
|
|
||||||
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
|
|
||||||
if (coordinator) {
|
|
||||||
__managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
|
||||||
__managedObjectContext.persistentStoreCoordinator = coordinator;
|
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] addObserverForName:NSPersistentStoreDidImportUbiquitousContentChangesNotification
|
|
||||||
object:coordinator
|
|
||||||
queue:nil
|
|
||||||
usingBlock:^(NSNotification *note) {
|
|
||||||
dbg(@"Ubiquitous content change: %@", note);
|
|
||||||
|
|
||||||
[__managedObjectContext performBlock:^{
|
|
||||||
[__managedObjectContext mergeChangesFromContextDidSaveNotification:note];
|
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter] postNotification:
|
|
||||||
[NSNotification notificationWithName:MPNotificationStoreUpdated
|
|
||||||
object:self userInfo:[note userInfo]]];
|
|
||||||
}];
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
return __managedObjectContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
|
|
||||||
|
|
||||||
if (__persistentStoreCoordinator)
|
|
||||||
return __persistentStoreCoordinator;
|
|
||||||
|
|
||||||
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"MasterPassword.sqlite"];
|
|
||||||
|
|
||||||
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
|
|
||||||
[__persistentStoreCoordinator lock];
|
|
||||||
NSError *error = nil;
|
|
||||||
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL
|
|
||||||
options:[NSDictionary dictionaryWithObjectsAndKeys:
|
|
||||||
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
|
|
||||||
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
|
|
||||||
[[[NSFileManager defaultManager]
|
|
||||||
URLForUbiquityContainerIdentifier:nil]
|
|
||||||
URLByAppendingPathComponent:@"store"
|
|
||||||
isDirectory:YES], NSPersistentStoreUbiquitousContentURLKey,
|
|
||||||
@"MasterPassword.store", NSPersistentStoreUbiquitousContentNameKey,
|
|
||||||
nil]
|
|
||||||
error:&error]) {
|
|
||||||
err(@"Unresolved error %@, %@", error, [error userInfo]);
|
|
||||||
#if DEBUG
|
|
||||||
wrn(@"Deleted datastore: %@", storeURL);
|
|
||||||
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
[TestFlight passCheckpoint:MPTestFlightCheckpointStoreIncompatible];
|
|
||||||
|
|
||||||
@throw [NSException exceptionWithName:error.domain reason:error.localizedDescription
|
|
||||||
userInfo:[NSDictionary dictionaryWithObject:error forKey:@"cause"]];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (![[NSFileManager defaultManager] setAttributes:[NSDictionary dictionaryWithObject:NSFileProtectionComplete
|
|
||||||
forKey:NSFileProtectionKey]
|
|
||||||
ofItemAtPath:storeURL.path error:&error])
|
|
||||||
err(@"Unresolved error %@, %@", error, [error userInfo]);
|
|
||||||
[__persistentStoreCoordinator unlock];
|
|
||||||
|
|
||||||
return __persistentStoreCoordinator;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Application's Documents directory
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns the URL to the application's Documents directory.
|
|
||||||
*/
|
|
||||||
- (NSURL *)applicationDocumentsDirectory
|
|
||||||
{
|
|
||||||
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - TestFlight
|
#pragma mark - TestFlight
|
||||||
|
|
||||||
|
|
||||||
|
@ -479,6 +479,7 @@
|
|||||||
@"Go to %@ and set or change the password for your account to the password above.\n"
|
@"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.",
|
@"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.activeElement.name, self.activeElement.name)];
|
||||||
|
[[MPAppDelegate get] saveContext];
|
||||||
|
|
||||||
[self.searchDisplayController setActive:NO animated:YES];
|
[self.searchDisplayController setActive:NO animated:YES];
|
||||||
self.searchDisplayController.searchBar.text = self.activeElement.name;
|
self.searchDisplayController.searchBar.text = self.activeElement.name;
|
||||||
|
@ -4,10 +4,8 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.developer.ubiquity-container-identifiers</key>
|
<key>com.apple.developer.ubiquity-container-identifiers</key>
|
||||||
<array>
|
<array>
|
||||||
<string>$(TeamIdentifierPrefix)com.lyndir.lhunath.MasterPassword</string>
|
<string>$(TeamIdentifierPrefix)com.lyndir.lhunath.MasterPassword.1</string>
|
||||||
</array>
|
</array>
|
||||||
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
|
|
||||||
<string>$(TeamIdentifierPrefix)com.lyndir.lhunath.MasterPassword</string>
|
|
||||||
<key>keychain-access-groups</key>
|
<key>keychain-access-groups</key>
|
||||||
<array>
|
<array>
|
||||||
<string>$(AppIdentifierPrefix)com.lyndir.lhunath.MasterPassword</string>
|
<string>$(AppIdentifierPrefix)com.lyndir.lhunath.MasterPassword</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user