Files
MacPass/MacPass/MPSettingsHelper.m
michael starke 07a8085705 Extended plugin settings
Plugins can be installed via drag and drop
Plugins can be uninstalled via the remove button
2017-11-17 17:45:10 +01:00

272 lines
14 KiB
Objective-C

//
// MPSettingsHelper.m
// MacPass
//
// Created by Michael Starke on 30.03.13.
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
//
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#import "MPSettingsHelper.h"
#import "NSString+MPPasswordCreation.h"
#import "NSString+MPHash.h"
#import "MPEntrySearchContext.h"
#import "DDHotKey+MacPassAdditions.h" // Default hotkey;
NSString *const kMPSettingsKeyPasteboardClearTimeout = @"ClipboardClearTimeout";
NSString *const kMPSettingsKeyClearPasteboardOnQuit = @"ClearClipboardOnQuit";
NSString *const kMPSettingsKeyBrowserBundleId = @"BrowserBundleId";
NSString *const kMPSettingsKeyOpenEmptyDatabaseOnLaunch = @"OpenEmptyDatabaseOnLaunch";
NSString *const kMPSettingsKeyReopenLastDatabaseOnLaunch = @"ReopenLastDatabaseOnLaunch";
NSString *const kMPSettingsKeyFileChangeStrategy = @"FileChangeStrategy";
NSString *const kMPSettingsKeyLockOnSleep = @"LockOnSleep";
NSString *const kMPSettingskeyLockOnLogout = @"LockOnLogout";
NSString *const kMPSettingsKeyIdleLockTimeOut = @"IdleLockTimeOut";
NSString *const kMPSettingsKeyShowInspector = @"ShowInspector";
NSString *const kMPSettingsKeyEntryTableSortDescriptors = @"EntryTableSortDescriptors";
NSString *const kMPSettingsKeyLegacyHideTitle = @"LegacyHideTitle";
NSString *const kMPSettingsKeyLegacyHideUsername = @"LegacyHideUsername ";
NSString *const kMPSettingsKeyLegacyHidePassword = @"LegacyHidePassword";
NSString *const kMPSettingsKeyLegacyHideNotes = @"LegacyHideNotes";
NSString *const kMPSettingsKeyLegacyHideURL = @"LegacyHideURL";
NSString *const kMPSettingsKeyLastDatabasePath = @"LastDatabasePath";
NSString *const kMPSettingsKeyRememberKeyFilesForDatabases = @"RememberKeyFilesForDatabases";
NSString *const kMPSettingsKeyRememeberdKeysForDatabases = @"RememeberdKeysForDatabases";
NSString *const kMPSettingsKeySendCommandForControlKey = @"SendCommandKeyForControlKey";
NSString *const kMPSettingsKeyEnableGlobalAutotype = @"EnableGlobalAutotype";
NSString *const kMPSettingsKeyGlobalAutotypeKeyDataKey = @"GlobalAutotypeKeyDataKey";
NSString *const kMPSettingsKeyDefaultGlobalAutotypeSequence = @"DefaultGlobalAutotypeSequence";
NSString *const kMPSettingsKeyAutotypeMatchTitle = @"AutotypeMatchTitle";
NSString *const kMPSettingsKeyAutotypeMatchURL = @"AutotypeMatchURL";
NSString *const kMPSettingsKeyAutotypeMatchHost = @"AutotypeMatchHost";
NSString *const kMPSettingsKeyAutotypeMatchTags = @"AutotypeMatchTags";
NSString *const kMPSettingsKeyEntrySearchFilterContext = @"EntrySearchFilterContext";
NSString *const kMPSettingsKeyEnableQuicklookPreview = @"EnableQuicklookPreview";
NSString *const kMPSettingsKeyCopyGeneratedPasswordToClipboard = @"CopyGeneratedPasswordToClipboard";
NSString *const kMPSettingsKeyDefaultPasswordLength = @"DefaultPasswordLength";
NSString *const kMPSettingsKeyPasswordCharacterFlags = @"PasswordCharacterFlags";
NSString *const kMPSettingsKeyPasswordUseCustomString = @"PasswordUseCustomString";
NSString *const kMPSettingsKeyPasswordCustomString = @"PasswordCustomString";
NSString *const kMPSettingsKeyPasswordDefaultsForEntry = @"PasswordDefaultsForEntry";
NSString *const kMPSettingsKeyDoubleClickURLAction = @"DoubleClickURLAction";
NSString *const kMPSettingsKeyDoubleClickTitleAction = @"DoubleClickTitleAction";
NSString *const kMPSettingsKeyUpdatePasswordOnTemplateEntries = @"UpdatePasswordOnTemplateEntries";
NSString *const kMPSettingsKeyLoadUnsecurePlugins = @"LoadUnsecurePlugins";
NSString *const kMPSettingsKeyDisabledPlugins = @"DisabledPlugins";
/* Deprecated */
NSString *const kMPDeprecatedSettingsKeyRememberKeyFilesForDatabases = @"kMPSettingsKeyRememberKeyFilesForDatabases";
NSString *const kMPDeprecatedSettingsKeyLastDatabasePath = @"MPLastDatabasePath";
NSString *const kMPDeprecatedSettingsKeyDocumentsAutotypeFixNoteWasShown = @"DocumentsAutotypeFixNoteWasShown";
NSString *const kMPDeprecatedSettingsKeyDoubleClickURLToLaunch = @"DoubleClickURLToLaunch";
NSString *const kMPDeprecatedSettingsKeyEntrySearchFilterMode = @"EntrySearchFilterMode";
NSString *const kMPDeprecatedSettingsKeyHttpPort = @"HttpPort";
NSString *const kMPDeprecatedSettingsKeyEnableHttpServer = @"EnableHttpServer";
NSString *const kMPDeprecatedSettingsKeyShowMenuItem = @"ShowMenuItem";
NSString *const kMPDeprecatedSettingsKeyDefaultPasswordRounds = @"KeyDefaultPasswordRounds";
NSString *const kMPDepricatedSettingsKeyLoadUnsecurePlugins = @"MPLoadUnsecurePlugins";
@implementation MPSettingsHelper
+ (void)setupDefaults {
[[NSUserDefaults standardUserDefaults] registerDefaults:[self _standardDefaults]];
}
+ (void)migrateDefaults {
[self _fixEntryTableSortDescriptors];
[self _migrateURLDoubleClickPreferences];
[self _migrateEntrySearchFlags];
[self _migrateRememberedKeyFiles];
[self _migrateLoadUnsecurePlugins];
[self _removeDeprecatedValues];
}
+ (NSString *)defaultControllerPathForKey:(NSString *)key {
return [NSString stringWithFormat:@"values.%@", key];
}
+ (NSDictionary *)_standardDefaults {
static NSDictionary *standardDefaults;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
standardDefaults = @{
kMPSettingsKeyShowInspector: @YES, // Show the Inspector by default
kMPSettingsKeyPasteboardClearTimeout: @30, // 30 seconds
kMPSettingsKeyClearPasteboardOnQuit: @YES,
kMPSettingsKeyOpenEmptyDatabaseOnLaunch: @NO,
kMPSettingsKeyReopenLastDatabaseOnLaunch: @YES,
kMPSettingsKeyFileChangeStrategy: @(MPFileChangeStrategyAsk), // Ask what to do on a file change!
kMPSettingsKeyLockOnSleep: @YES,
kMPSettingskeyLockOnLogout: @NO,
kMPSettingsKeyIdleLockTimeOut: @0, // 5 minutes
kMPSettingsKeyLegacyHideNotes: @NO,
kMPSettingsKeyLegacyHidePassword: @YES,
kMPSettingsKeyLegacyHideTitle: @NO,
kMPSettingsKeyLegacyHideURL: @NO,
kMPSettingsKeyLegacyHideUsername: @NO,
kMPSettingsKeyRememberKeyFilesForDatabases: @NO,
kMPSettingsKeySendCommandForControlKey: @YES,
kMPSettingsKeyEnableGlobalAutotype: @NO,
kMPSettingsKeyGlobalAutotypeKeyDataKey: [DDHotKey defaultHotKeyData],
kMPSettingsKeyDefaultGlobalAutotypeSequence: @"{USERNAME}{TAB}{PASSWORD}{ENTER}",
kMPSettingsKeyAutotypeMatchTitle: @YES,
kMPSettingsKeyAutotypeMatchURL: @NO,
kMPSettingsKeyAutotypeMatchHost: @NO,
kMPSettingsKeyAutotypeMatchTags: @NO,
kMPSettingsKeyEnableQuicklookPreview: @NO,
kMPSettingsKeyCopyGeneratedPasswordToClipboard: @NO,
kMPSettingsKeyDefaultPasswordLength: @12,
kMPSettingsKeyPasswordCharacterFlags: @(MPPasswordCharactersAll),
kMPSettingsKeyPasswordUseCustomString: @NO,
kMPSettingsKeyPasswordCustomString: @"",
kMPSettingsKeyDoubleClickURLAction: @(MPDoubleClickURLActionCopy),
kMPSettingsKeyDoubleClickTitleAction: @(MPDoubleClickTitleActionInspect),
kMPSettingsKeyLoadUnsecurePlugins: @NO,
kMPSettingsKeyUpdatePasswordOnTemplateEntries: @YES,
kMPSettingsKeyDisabledPlugins: @[]
};
});
return standardDefaults;
}
+ (NSArray *)_deprecatedSettingsKeys {
static NSArray *deprecatedSettings;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
deprecatedSettings = @[ kMPDeprecatedSettingsKeyRememberKeyFilesForDatabases,
kMPDeprecatedSettingsKeyLastDatabasePath,
kMPDeprecatedSettingsKeyDocumentsAutotypeFixNoteWasShown,
kMPDeprecatedSettingsKeyDoubleClickURLToLaunch,
kMPDeprecatedSettingsKeyEntrySearchFilterMode,
kMPDeprecatedSettingsKeyDefaultPasswordRounds,
/* Moved to KeePassHttp Plugin */
kMPDeprecatedSettingsKeyHttpPort,
kMPDeprecatedSettingsKeyEnableHttpServer,
kMPDeprecatedSettingsKeyShowMenuItem,
kMPDepricatedSettingsKeyLoadUnsecurePlugins
];
});
return deprecatedSettings;
}
+ (void)_removeDeprecatedValues {
/* Clear old style values */
for(NSString *key in [self _deprecatedSettingsKeys]) {
[[NSUserDefaults standardUserDefaults] removeObjectForKey:key];
}
}
+ (void)_fixEntryTableSortDescriptors {
/*
MacPass < 0.4 did use compare: for the entry table view,
this was changed in 0.4 to localizedCaseInsensitiveCompare:
MacPass < 0.5.2 did use parent.name for group names,
this was changed in 0.6. to parent.title
*/
NSData *descriptorData = [[NSUserDefaults standardUserDefaults] dataForKey:kMPSettingsKeyEntryTableSortDescriptors];
if(!descriptorData) {
return; // No user defaults
}
NSArray *sortDescriptors = [NSUnarchiver unarchiveObjectWithData:descriptorData];
for(NSSortDescriptor *descriptor in sortDescriptors) {
/* Brute force, just kill the settings if they might cause trouble */
if(descriptor.selector == @selector(compare:)
|| [descriptor.key isEqualToString:@"timeInfo.modificationDate"]
|| [descriptor.key isEqualToString:@"parent.name"] ) {
[[NSUserDefaults standardUserDefaults] removeObjectForKey:kMPSettingsKeyEntryTableSortDescriptors];
break;
}
}
}
+ (void)_migrateURLDoubleClickPreferences {
/* Default was NO so if the key was not set, we also get NO, which is what we want */
BOOL openURL = [[NSUserDefaults standardUserDefaults] boolForKey:kMPDeprecatedSettingsKeyDoubleClickURLToLaunch];
if(NO == openURL) {
[[NSUserDefaults standardUserDefaults] setInteger:MPDoubleClickURLActionOpen forKey:kMPSettingsKeyDoubleClickURLAction];
}
}
+ (void)_migrateEntrySearchFlags {
/* Entry filters are now stored as archivd search context not just flags */
NSInteger flags = [[NSUserDefaults standardUserDefaults] integerForKey:kMPDeprecatedSettingsKeyEntrySearchFilterMode];
if(flags != 0) {
MPEntrySearchContext *context = [[MPEntrySearchContext alloc] initWithString:nil flags:flags];
NSData *contextData = [NSKeyedArchiver archivedDataWithRootObject:context];
[[NSUserDefaults standardUserDefaults] setObject:contextData forKey:kMPSettingsKeyEntrySearchFilterContext];
}
}
+ (void)_migrateRememberedKeyFiles {
/*
Database file paths was stored as plain text in keyfile mapping.
We only need to store the key file url in plain text, thus hashing the path is sufficent
*/
NSDictionary<NSString *, NSString *> *currentMapping = [[NSUserDefaults standardUserDefaults] dictionaryForKey:kMPSettingsKeyRememeberdKeysForDatabases];
if(!currentMapping) {
return;
}
NSMutableDictionary *hashedDict = [[NSMutableDictionary alloc] initWithCapacity:MAX(1,currentMapping.count)];
BOOL didHash = NO;
for(NSString *key in currentMapping) {
NSURL *fileURL = [NSURL URLWithString:key];
/* Only hash file paths */
if(fileURL.isFileURL) {
NSString *digest = key.sha1HexDigest;
if(digest) {
hashedDict[key.sha1HexDigest] = currentMapping[key];
didHash = YES;
}
}
/* keep all hashed or unknown data */
else {
hashedDict[key] = currentMapping[key];
}
}
if(didHash) {
[[NSUserDefaults standardUserDefaults] setObject:hashedDict forKey:kMPSettingsKeyRememeberdKeysForDatabases];
}
}
+ (void)_migrateLoadUnsecurePlugins {
id value = [NSUserDefaults.standardUserDefaults objectForKey:kMPDepricatedSettingsKeyLoadUnsecurePlugins];
if(!value) {
return; // value already migrated or was set to default value
}
BOOL oldValue = [NSUserDefaults.standardUserDefaults boolForKey:kMPDepricatedSettingsKeyLoadUnsecurePlugins];
if(oldValue != [[self _standardDefaults][kMPDepricatedSettingsKeyLoadUnsecurePlugins] boolValue]) {
[NSUserDefaults.standardUserDefaults setBool:oldValue forKey:kMPSettingsKeyLoadUnsecurePlugins];
}
}
@end