aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/SPPreferenceController.h14
-rw-r--r--Source/SPPreferenceController.m198
2 files changed, 97 insertions, 115 deletions
diff --git a/Source/SPPreferenceController.h b/Source/SPPreferenceController.h
index 221508a2..f5035787 100644
--- a/Source/SPPreferenceController.h
+++ b/Source/SPPreferenceController.h
@@ -45,22 +45,13 @@
IBOutlet NSArrayController *favoritesController;
IBOutlet NSTabView *favoritesTabView;
- IBOutlet NSTextField *nameField;
- IBOutlet NSTextField *standardSQLHostField;
- IBOutlet NSTextField *standardUserField;
IBOutlet NSSecureTextField *standardPasswordField;
- IBOutlet NSTextField *standardDatabaseField;
- IBOutlet NSTextField *socketUserField;
IBOutlet NSSecureTextField *socketPasswordField;
- IBOutlet NSTextField *socketDatabaseField;
- IBOutlet NSTextField *sshSQLHostField;
- IBOutlet NSTextField *sshSQLUserField;
IBOutlet NSSecureTextField *sshSQLPasswordField;
- IBOutlet NSTextField *sshDatabaseField;
- IBOutlet NSTextField *sshHostField;
- IBOutlet NSTextField *sshUserField;
IBOutlet NSSecureTextField *sshPasswordField;
+
KeyChain *keychain;
+ NSDictionary *currentFavorite;
IBOutlet NSTextField *editorFontName;
@@ -104,5 +95,6 @@
- (void)selectFavoriteAtIndex:(unsigned int)theIndex;
- (void)changeFont:(id)sender;
- (IBAction)favoriteTypeDidChange:(id)sender;
+- (void)updateFavoritePasswordsFromField:(NSControl *)passwordControl;
@end
diff --git a/Source/SPPreferenceController.m b/Source/SPPreferenceController.m
index 9550e897..78d16a20 100644
--- a/Source/SPPreferenceController.m
+++ b/Source/SPPreferenceController.m
@@ -61,6 +61,7 @@
if (self = [super initWithWindowNibName:@"Preferences"]) {
prefs = [NSUserDefaults standardUserDefaults];
[self applyRevisionChanges];
+ currentFavorite = nil;
}
return self;
@@ -597,7 +598,7 @@
[favoritesController setSelectionIndexes:[favoritesTableView selectedRowIndexes]];
}
- // If no selection is present, blank the field.
+ // If no selection is present, blank the password fields (which can't use bindings)
if ([[favoritesTableView selectedRowIndexes] count] == 0) {
[standardPasswordField setStringValue:@""];
[socketPasswordField setStringValue:@""];
@@ -605,18 +606,22 @@
[sshPasswordField setStringValue:@""];
return;
}
+
+ // Keep a copy of the favorite as it currently stands
+ if (currentFavorite) [currentFavorite release];
+ currentFavorite = [[[favoritesController selectedObjects] objectAtIndex:0] copy];
- // Otherwise retrieve and set the password.
- NSString *keychainName = [keychain nameForFavoriteName:[favoritesController valueForKeyPath:@"selection.name"] id:[favoritesController valueForKeyPath:@"selection.id"]];
- NSString *keychainAccount = [keychain accountForUser:[favoritesController valueForKeyPath:@"selection.user"] host:[favoritesController valueForKeyPath:@"selection.host"] database:[favoritesController valueForKeyPath:@"selection.database"]];
+ // Retrieve and set the password.
+ NSString *keychainName = [keychain nameForFavoriteName:[currentFavorite objectForKey:@"name"] id:[currentFavorite objectForKey:@"id"]];
+ NSString *keychainAccount = [keychain accountForUser:[currentFavorite objectForKey:@"user"] host:[currentFavorite objectForKey:@"host"] database:[currentFavorite objectForKey:@"database"]];
NSString *passwordValue = [keychain getPasswordForName:keychainName account:keychainAccount];
[standardPasswordField setStringValue:passwordValue];
[socketPasswordField setStringValue:passwordValue];
[sshSQLPasswordField setStringValue:passwordValue];
// Retrieve the SSH keychain password if appropriate.
- NSString *keychainSSHName = [keychain nameForSSHForFavoriteName:[favoritesController valueForKeyPath:@"selection.name"] id:[favoritesController valueForKeyPath:@"selection.id"]];
- NSString *keychainSSHAccount = [keychain accountForSSHUser:[favoritesController valueForKeyPath:@"selection.sshUser"] sshHost:[favoritesController valueForKeyPath:@"selection.sshHost"]];
+ NSString *keychainSSHName = [keychain nameForSSHForFavoriteName:[currentFavorite objectForKey:@"name"] id:[currentFavorite objectForKey:@"id"]];
+ NSString *keychainSSHAccount = [keychain accountForSSHUser:[currentFavorite objectForKey:@"sshUser"] sshHost:[currentFavorite objectForKey:@"sshHost"]];
[sshPasswordField setStringValue:[keychain getPasswordForName:keychainSSHName account:keychainSSHAccount]];
}
@@ -709,130 +714,112 @@
// -------------------------------------------------------------------------------
- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
{
- NSString *nameValue, *hostValue, *userValue, *databaseValue, *passwordValue;
+
+ // Request a password refresh to keep keychain references in synch with favorites
+ [self updateFavoritePasswordsFromField:control];
+
+ // Proceed with editing
+ return YES;
+}
+
+// -------------------------------------------------------------------------------
+// favoriteTypeDidChange:
+// Update the favorite host when the type changes.
+// -------------------------------------------------------------------------------
+- (IBAction)favoriteTypeDidChange:(id)sender
+{
+ if ([sender indexOfSelectedItem] == 1) { // Socket
+ [favoritesController setValue:@"localhost" forKeyPath:@"selection.host"];
+ } else if ([[favoritesController valueForKeyPath:@"selection.host"] isEqualToString:@"localhost"]) {
+ [favoritesController setValue:@"" forKeyPath:@"selection.host"];
+ }
+
+ // Request a password refresh to keep keychain references in synch with the favorites
+ [self updateFavoritePasswordsFromField:nil];
+}
+
+// -------------------------------------------------------------------------------
+// updateFavoritePasswordsFromField:
+// Check all fields used in the keychain names against the old values for that
+// favorite, and update the keychain names to match if necessary.
+// If an (optional) recognised password field is supplied, that field is assumed
+// to have changed and is used to supply the new value.
+// -------------------------------------------------------------------------------
+- (void)updateFavoritePasswordsFromField:(NSControl *)passwordControl
+{
+ if (!currentFavorite) return;
+
+ NSString *passwordValue;
NSString *oldKeychainName, *newKeychainName;
NSString *oldKeychainAccount, *newKeychainAccount;
- // Only proceed for name, host, user or database changes, for standard, socket or SSH
- if (control != nameField && control != standardSQLHostField && control != standardUserField
- && control != standardPasswordField && control != standardDatabaseField
- && control != socketUserField && control != socketPasswordField
- && control != socketDatabaseField && control != sshSQLHostField
- && control != sshSQLUserField && control != sshSQLPasswordField
- && control != sshDatabaseField && control != sshHostField
- && control != sshUserField && control != sshPasswordField)
- return YES;
-
- // Determine the appropriate name, host, user and database details
- nameValue = [nameField stringValue];
- switch ([[favoritesController valueForKeyPath:@"selection.type"] intValue]) {
- case 0: // Standard
- hostValue = [standardSQLHostField stringValue];
- userValue = [standardUserField stringValue];
- databaseValue = [standardDatabaseField stringValue];
- passwordValue = [standardPasswordField stringValue];
- break;
+ // SQL passwords are indexed by name, host, user and database. If any of these
+ // have changed, or a standard password field has, alter the keychain item to match.
+ if (![[currentFavorite objectForKey:@"name"] isEqualToString:[favoritesController valueForKeyPath:@"selection.name"]]
+ || ![[currentFavorite objectForKey:@"host"] isEqualToString:[favoritesController valueForKeyPath:@"selection.host"]]
+ || ![[currentFavorite objectForKey:@"user"] isEqualToString:[favoritesController valueForKeyPath:@"selection.user"]]
+ || ![[currentFavorite objectForKey:@"database"] isEqualToString:[favoritesController valueForKeyPath:@"selection.database"]]
+ || passwordControl == standardPasswordField || passwordControl == socketPasswordField || passwordControl == sshSQLPasswordField)
+ {
- case 1: // Socket
- hostValue = @"localhost";
- userValue = [socketUserField stringValue];
- databaseValue = [socketDatabaseField stringValue];
+ // Determine the correct password field to read the password from, defaulting to standard
+ if (passwordControl == socketPasswordField) {
passwordValue = [socketPasswordField stringValue];
- break;
-
- case 2: // SSH
- hostValue = [sshSQLHostField stringValue];
- userValue = [sshSQLUserField stringValue];
- databaseValue = [sshDatabaseField stringValue];
+ } else if (passwordControl == sshSQLPasswordField) {
passwordValue = [sshSQLPasswordField stringValue];
- break;
- }
-
- // If account/password details have changed, update the keychain to match
- if (![nameValue isEqualToString:[favoritesController valueForKeyPath:@"selection.name"]]
- || ![hostValue isEqualToString:[favoritesController valueForKeyPath:@"selection.host"]]
- || ![userValue isEqualToString:[favoritesController valueForKeyPath:@"selection.user"]]
- || ![databaseValue isEqualToString:[favoritesController valueForKeyPath:@"selection.database"]]
- || control == standardPasswordField || control == socketPasswordField || control == sshSQLPasswordField) {
-
- // Get the current keychain name and account strings
- oldKeychainName = [keychain nameForFavoriteName:[favoritesController valueForKeyPath:@"selection.name"] id:[favoritesController valueForKeyPath:@"selection.id"]];
- oldKeychainAccount = [keychain accountForUser:[favoritesController valueForKeyPath:@"selection.user"] host:[favoritesController valueForKeyPath:@"selection.host"] database:[favoritesController valueForKeyPath:@"selection.database"]];
+ } else {
+ passwordValue = [standardPasswordField stringValue];
+ }
- // Set up the new keychain name and account strings
- newKeychainName = [keychain nameForFavoriteName:nameValue id:[favoritesController valueForKeyPath:@"selection.id"]];
- newKeychainAccount = [keychain accountForUser:userValue host:hostValue database:databaseValue];
+ // Get the old keychain name and account strings
+ oldKeychainName = [keychain nameForFavoriteName:[currentFavorite objectForKey:@"name"] id:[favoritesController valueForKeyPath:@"selection.id"]];
+ oldKeychainAccount = [keychain accountForUser:[currentFavorite objectForKey:@"user"] host:[currentFavorite objectForKey:@"host"] database:[currentFavorite objectForKey:@"database"]];
// Delete the old keychain item
[keychain deletePasswordForName:oldKeychainName account:oldKeychainAccount];
+ // Set up the new keychain name and account strings
+ newKeychainName = [keychain nameForFavoriteName:[favoritesController valueForKeyPath:@"selection.name"] id:[favoritesController valueForKeyPath:@"selection.id"]];
+ newKeychainAccount = [keychain accountForUser:[favoritesController valueForKeyPath:@"selection.user"] host:[favoritesController valueForKeyPath:@"selection.host"] database:[favoritesController valueForKeyPath:@"selection.database"]];
+
// Add the new keychain item if the password field has a value
if ([passwordValue length])
[keychain addPassword:passwordValue forName:newKeychainName account:newKeychainAccount];
+
+ // Synch password changes
+ [standardPasswordField setStringValue:passwordValue];
+ [socketPasswordField setStringValue:passwordValue];
+ [sshSQLPasswordField setStringValue:passwordValue];
+
+ passwordValue = @"";
}
-
- // Synch password changes
- [standardPasswordField setStringValue:passwordValue];
- [socketPasswordField setStringValue:passwordValue];
- [sshSQLPasswordField setStringValue:passwordValue];
// If SSH account/password details have changed, update the keychain to match
- if (![[nameField stringValue] isEqualToString:[favoritesController valueForKeyPath:@"selection.name"]]
- || ![[sshHostField stringValue] isEqualToString:[favoritesController valueForKeyPath:@"selection.sshHost"]]
- || ![[sshUserField stringValue] isEqualToString:[favoritesController valueForKeyPath:@"selection.sshUser"]]
- || control == sshPasswordField) {
-
- // Get the current keychain name and account strings
- oldKeychainName = [keychain nameForSSHForFavoriteName:[favoritesController valueForKeyPath:@"selection.name"] id:[favoritesController valueForKeyPath:@"selection.id"]];
- oldKeychainAccount = [keychain accountForSSHUser:[favoritesController valueForKeyPath:@"selection.sshUser"] sshHost:[favoritesController valueForKeyPath:@"selection.sshHost"]];
+ if (![[currentFavorite objectForKey:@"name"] isEqualToString:[favoritesController valueForKeyPath:@"selection.name"]]
+ || ![[currentFavorite objectForKey:@"sshHost"] isEqualToString:[favoritesController valueForKeyPath:@"selection.sshHost"]]
+ || ![[currentFavorite objectForKey:@"sshUser"] isEqualToString:[favoritesController valueForKeyPath:@"selection.sshUser"]]
+ || passwordControl == sshPasswordField) {
- // Set up the new keychain name and account strings
- newKeychainName = [keychain nameForSSHForFavoriteName:nameValue id:[favoritesController valueForKeyPath:@"selection.id"]];
- newKeychainAccount = [keychain accountForSSHUser:[sshUserField stringValue] sshHost:[sshHostField stringValue]];
+ // Get the old keychain name and account strings
+ oldKeychainName = [keychain nameForSSHForFavoriteName:[currentFavorite objectForKey:@"name"] id:[favoritesController valueForKeyPath:@"selection.id"]];
+ oldKeychainAccount = [keychain accountForSSHUser:[currentFavorite objectForKey:@"sshUser"] sshHost:[currentFavorite objectForKey:@"sshHost"]];
// Delete the old keychain item
[keychain deletePasswordForName:oldKeychainName account:oldKeychainAccount];
+ // Set up the new keychain name and account strings
+ newKeychainName = [keychain nameForSSHForFavoriteName:[favoritesController valueForKeyPath:@"selection.name"] id:[favoritesController valueForKeyPath:@"selection.id"]];
+ newKeychainAccount = [keychain accountForSSHUser:[favoritesController valueForKeyPath:@"selection.sshUser"] sshHost:[favoritesController valueForKeyPath:@"selection.sshHost"]];
+
// Add the new keychain item if the password field has a value
if ([[sshPasswordField stringValue] length])
[keychain addPassword:[sshPasswordField stringValue] forName:newKeychainName account:newKeychainAccount];
}
- // Proceed with editing
- return YES;
-}
-
-// -------------------------------------------------------------------------------
-// favoriteTypeDidChange:
-// Update the favorite host when the type changes.
-// -------------------------------------------------------------------------------
-- (IBAction)favoriteTypeDidChange:(id)sender
-{
- NSString *oldKeychainName, *newKeychainName;
- NSString *oldKeychainAccount, *newKeychainAccount;
-
- // Get the current keychain name and account strings
- oldKeychainName = [keychain nameForFavoriteName:[favoritesController valueForKeyPath:@"selection.name"] id:[favoritesController valueForKeyPath:@"selection.id"]];
- oldKeychainAccount = [keychain accountForUser:[favoritesController valueForKeyPath:@"selection.user"] host:[favoritesController valueForKeyPath:@"selection.host"] database:[favoritesController valueForKeyPath:@"selection.database"]];
-
- // Delete the old keychain item
- [keychain deletePasswordForName:oldKeychainName account:oldKeychainAccount];
-
- if ([sender indexOfSelectedItem] == 1) { // Socket
- [favoritesController setValue:@"localhost" forKeyPath:@"selection.host"];
- [self control:socketPasswordField textShouldEndEditing:nil];
- } else if ([[favoritesController valueForKeyPath:@"selection.host"] isEqualToString:@"localhost"]) {
- [favoritesController setValue:@"" forKeyPath:@"selection.host"];
- [self control:standardPasswordField textShouldEndEditing:nil];
- }
-
- // Set up the new keychain name and account strings
- newKeychainName = [keychain nameForFavoriteName:[favoritesController valueForKeyPath:@"selection.name"] id:[favoritesController valueForKeyPath:@"selection.id"]];
- newKeychainAccount = [keychain accountForUser:[favoritesController valueForKeyPath:@"selection.user"] host:[favoritesController valueForKeyPath:@"selection.host"] database:[favoritesController valueForKeyPath:@"selection.database"]];
-
- // Add the new keychain item if the password field has a value
- if ([[standardPasswordField stringValue] length])
- [keychain addPassword:[standardPasswordField stringValue] forName:newKeychainName account:newKeychainAccount];
+ // Update the current favorite
+ if (currentFavorite) [currentFavorite release], currentFavorite = nil;
+ if ([[favoritesTableView selectedRowIndexes] count] > 0)
+ currentFavorite = [[[favoritesController selectedObjects] objectAtIndex:0] copy];
}
#pragma mark -
@@ -913,6 +900,7 @@
- (void)selectFavorites:(NSArray *)favorites
{
[favoritesController setSelectedObjects:favorites];
+ [favoritesTableView scrollRowToVisible:[favoritesController selectionIndex]];
}
// -------------------------------------------------------------------------------
@@ -923,6 +911,7 @@
- (void)selectFavoriteAtIndex:(unsigned int)theIndex
{
[favoritesController setSelectionIndex:theIndex];
+ [favoritesTableView scrollRowToVisible:theIndex];
}
// -------------------------------------------------------------------------------
@@ -970,7 +959,8 @@
- (void)dealloc
{
[keychain release], keychain = nil;
-
+ if (currentFavorite) [currentFavorite release];
+
[super dealloc];
}