diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/SPSSHTunnel.h | 7 | ||||
-rw-r--r-- | Source/SPSSHTunnel.m | 139 |
2 files changed, 89 insertions, 57 deletions
diff --git a/Source/SPSSHTunnel.h b/Source/SPSSHTunnel.h index 1a061619..836611f3 100644 --- a/Source/SPSSHTunnel.h +++ b/Source/SPSSHTunnel.h @@ -67,6 +67,10 @@ enum spsshtunnel_password_modes NSInteger localPort; NSInteger localPortFallback; NSInteger connectionState; + + BOOL isAnswerAvailable; + NSCondition *answerAvailableCondition; + NSString *currentKeyName; } - (id) initToHost:(NSString *) theHost port:(NSInteger) thePort login:(NSString *) theLogin tunnellingToPort:(NSInteger) targetPort onHost:(NSString *) targetHost; @@ -88,6 +92,7 @@ enum spsshtunnel_password_modes - (void) workerGetResponseForQuestion:(NSString *)theQuestion; - (NSString *) getPasswordForQuery:(NSString *)theQuery verificationHash:(NSString *)theHash; - (void) workerGetPasswordForQuery:(NSString *)theQuery; -- (IBAction) closeSheet:(id)sender; +- (IBAction) closeSSHQuestionSheet:(id)sender; +- (IBAction) closeSSHPasswordSheet:(id)sender; @end diff --git a/Source/SPSSHTunnel.m b/Source/SPSSHTunnel.m index 4779e6a1..9b53adda 100644 --- a/Source/SPSSHTunnel.m +++ b/Source/SPSSHTunnel.m @@ -469,9 +469,24 @@ */ - (BOOL) getResponseForQuestion:(NSString *)theQuestion { + // prepare the condition + [answerAvailableCondition lock]; + isAnswerAvailable = NO; + + // request an answer on the main thread (UI stuff must be done on main thread) [self performSelectorOnMainThread:@selector(workerGetResponseForQuestion:) withObject:theQuestion waitUntilDone:YES]; - return requestedResponse; + // wait until an answer is available + while (!isAnswerAvailable) [answerAvailableCondition wait]; + + // save the answer + BOOL response = requestedResponse; + + //unlock condition + [answerAvailableCondition unlock]; + + //return the answer + return response; } - (void) workerGetResponseForQuestion:(NSString *)theQuestion { @@ -479,29 +494,28 @@ NSSize questionTextSize; NSRect windowFrameRect; - // Ask how to proceed, sizing the window appropriately to fit the question + // set up the question window [sshQuestionText setStringValue:theQuestion]; questionTextSize = [[sshQuestionText cell] cellSizeForBounds:NSMakeRect(0, 0, [sshQuestionText bounds].size.width, 500)]; windowFrameRect = [sshQuestionDialog frame]; windowFrameRect.size.height = ((questionTextSize.height < 100)?100:questionTextSize.height) + 70 + ([sshPasswordDialog isSheet]?0:22); [sshQuestionDialog setFrame:windowFrameRect display:NO]; + + //show the question window [NSApp beginSheet:sshQuestionDialog modalForWindow:parentWindow modalDelegate:self didEndSelector:nil contextInfo:nil]; - NSInteger sshQueryResponseCode = [NSApp runModalForWindow:sshQuestionDialog]; - [NSApp endSheet:sshQuestionDialog]; +} +/* + * Ends an existing modal session + */ +- (IBAction) closeSSHQuestionSheet:(id)sender +{ + [answerAvailableCondition lock]; + requestedResponse = [sender tag]==1 ? YES : NO; + [NSApp endSheet:sshQuestionDialog]; [sshQuestionDialog orderOut:nil]; - - switch (sshQueryResponseCode) { - - // Yes - case 1: - requestedResponse = YES; - return; - - // No - default: - requestedResponse = NO; - return; - } + isAnswerAvailable = YES; + [answerAvailableCondition signal]; + [answerAvailableCondition unlock]; } /* @@ -512,30 +526,44 @@ { if (![theHash isEqualToString:tunnelConnectionVerifyHash]) return nil; - NSString *thePassword; - + // prepare the condition + [answerAvailableCondition lock]; + isAnswerAvailable = NO; + + // request password on the main thread (UI stuff must be done on main thread) [self performSelectorOnMainThread:@selector(workerGetPasswordForQuery:) withObject:theQuery waitUntilDone:YES]; - if (!requestedPassphrase) return nil; - thePassword = [NSString stringWithString:requestedPassphrase]; - [requestedPassphrase release], requestedPassphrase = nil; + // wait until an answer is available + while (!isAnswerAvailable) [answerAvailableCondition wait]; + + // save the answer + NSString *thePassword = nil; + if (requestedPassphrase) { + thePassword = [NSString stringWithString:requestedPassphrase]; + [requestedPassphrase release], requestedPassphrase = nil; + } + + //unlock condition + [answerAvailableCondition unlock]; + + //return the answer return thePassword; } - (void) workerGetPasswordForQuery:(NSString *)theQuery { NSSize queryTextSize; NSRect windowFrameRect; - NSString *thePassword; - SPKeychain *keychain; // Work out whether a passphrase is being requested, extracting the key name NSString *keyName = [theQuery stringByMatching:@"^\\s*Enter passphrase for key \\'(.*)\\':\\s*$" capture:1L]; if (keyName) { [sshPasswordText setStringValue:[NSString stringWithFormat:@"Enter your password for the SSH key\n\"%@\"", keyName]]; [sshPasswordKeychainCheckbox setHidden:NO]; + currentKeyName = [keyName retain]; } else { [sshPasswordText setStringValue:theQuery]; - [sshPasswordKeychainCheckbox setHidden:YES]; + [sshPasswordKeychainCheckbox setHidden:YES]; + currentKeyName = nil; } // Request the password, sizing the window appropriately to fit the query @@ -544,45 +572,44 @@ windowFrameRect.size.height = ((queryTextSize.height < 40)?40:queryTextSize.height) + 140 + ([sshPasswordDialog isSheet]?0:22); [sshPasswordDialog setFrame:windowFrameRect display:NO]; [NSApp beginSheet:sshPasswordDialog modalForWindow:parentWindow modalDelegate:self didEndSelector:nil contextInfo:nil]; - NSInteger sshQueryResponseCode = [NSApp runModalForWindow:sshPasswordDialog]; - [NSApp endSheet:sshPasswordDialog]; - [sshPasswordDialog orderOut:nil]; - - switch (sshQueryResponseCode) { - - // OK - case 1: - thePassword = [NSString stringWithString:[sshPasswordField stringValue]]; - [sshPasswordField setStringValue:@""]; - if ([delegate respondsToSelector:@selector(setUndoManager:)] && [delegate undoManager]) { - [[delegate undoManager] removeAllActionsWithTarget:sshPasswordField]; - } else if ([[parentWindow windowController] document] && [[[parentWindow windowController] document] undoManager]) { - [[[[parentWindow windowController] document] undoManager] removeAllActionsWithTarget:sshPasswordField]; - } - requestedPassphrase = [[NSString alloc] initWithString:thePassword]; - - // Add to keychain if appropriate - if (keyName && [sshPasswordKeychainCheckbox state] == NSOnState) { - keychain = [[SPKeychain alloc] init]; - [keychain addPassword:thePassword forName:@"SSH" account:keyName withLabel:[NSString stringWithFormat:@"SSH: %@", keyName]]; - [keychain release]; - } - return; - - // Cancel - default: - return; - } } /* * Ends an existing modal session */ -- (IBAction) closeSheet:(id)sender +- (IBAction) closeSSHPasswordSheet:(id)sender { - [NSApp stopModalWithCode:[sender tag]]; + [answerAvailableCondition lock]; + requestedResponse = [sender tag]==1 ? YES : NO; + [NSApp endSheet:sshPasswordDialog]; + [sshPasswordDialog orderOut:nil]; + + if (requestedResponse) { + NSString *thePassword = [NSString stringWithString:[sshPasswordField stringValue]]; + [sshPasswordField setStringValue:@""]; + if ([delegate respondsToSelector:@selector(setUndoManager:)] && [delegate undoManager]) { + [[delegate undoManager] removeAllActionsWithTarget:sshPasswordField]; + } else if ([[parentWindow windowController] document] && [[[parentWindow windowController] document] undoManager]) { + [[[[parentWindow windowController] document] undoManager] removeAllActionsWithTarget:sshPasswordField]; + } + requestedPassphrase = [[NSString alloc] initWithString:thePassword]; + + // Add to keychain if appropriate + if (currentKeyName && [sshPasswordKeychainCheckbox state] == NSOnState) { + SPKeychain *keychain = [[SPKeychain alloc] init]; + [keychain addPassword:thePassword forName:@"SSH" account:currentKeyName withLabel:[NSString stringWithFormat:@"SSH: %@", currentKeyName]]; + [keychain release]; + [currentKeyName release]; + currentKeyName = nil; + } + } + + isAnswerAvailable = YES; + [answerAvailableCondition signal]; + [answerAvailableCondition unlock]; } + - (void)dealloc { delegate = nil; |