aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/SPConnectionController.m44
-rw-r--r--Source/SPSSHTunnel.m2
-rw-r--r--Source/SPTableData.m7
3 files changed, 40 insertions, 13 deletions
diff --git a/Source/SPConnectionController.m b/Source/SPConnectionController.m
index 34446959..5d93a4f4 100644
--- a/Source/SPConnectionController.m
+++ b/Source/SPConnectionController.m
@@ -27,6 +27,7 @@
#import "SPAppController.h"
#import "SPPreferenceController.h"
#import "ImageAndTextCell.h"
+#import "RegexKitLite.h"
@implementation SPConnectionController
@@ -145,7 +146,6 @@
*/
- (IBAction)initiateConnection:(id)sender
{
-
// Ensure that host is not empty if this is a TCP/IP or SSH connection
if (([self type] == SP_CONNECTION_TCPIP || [self type] == SP_CONNECTION_SSHTUNNEL) && ![[self host] length]) {
NSRunAlertPanel(NSLocalizedString(@"Insufficient connection details", @"insufficient details message"), NSLocalizedString(@"Insufficient details provided to establish a connection. Please provide at least a host.", @"insufficient details informative message"), NSLocalizedString(@"OK", @"OK button"), nil, nil);
@@ -260,6 +260,7 @@
[progressIndicatorText setStringValue:NSLocalizedString(@"MySQL connecting...", @"MySQL connecting very short status message")];
else
[progressIndicatorText setStringValue:NSLocalizedString(@"Connecting...", @"Generic connecting very short status message")];
+
[progressIndicatorText display];
// Initialise to socket if appropriate.
@@ -366,6 +367,8 @@
*/
- (void)failConnectionWithTitle:(NSString *)theTitle errorMessage:(NSString *)theErrorMessage detail:(NSString *)errorDetail
{
+ BOOL isSSHTunnelBindError = NO;
+
// Clean up the interface
[progressIndicator stopAnimation:self];
[progressIndicator display];
@@ -376,23 +379,29 @@
[tableDocument clearStatusIcon];
// Release as appropriate
- if (sshTunnel) [sshTunnel disconnect], [sshTunnel release], sshTunnel = nil;
+ if (sshTunnel) {
+ [sshTunnel disconnect], [sshTunnel release], sshTunnel = nil;
+
+ // If the SSH tunnel connection failed because the port it was trying to bind to was already in use take note
+ // of it so we can give the user the option of connecting via standard connection and use the existing tunnel.
+ if ([theErrorMessage rangeOfString:@"bind"].location != NSNotFound) {
+ isSSHTunnelBindError = YES;
+ }
+ }
if (errorDetail) [errorDetailText setString:errorDetail];
// Display the connection error message
- NSBeginAlertSheet(theTitle, NSLocalizedString(@"OK", @"OK button"), errorDetail?NSLocalizedString(@"Show detail", @"Show detail button"):nil, nil, documentWindow, self, nil, @selector(errorSheetDidEnd:returnCode:contextInfo:), @"connect", theErrorMessage);
+ NSBeginAlertSheet(theTitle, NSLocalizedString(@"OK", @"OK button"), (errorDetail) ? NSLocalizedString(@"Show Detail", @"Show detail button") : nil, (isSSHTunnelBindError) ? NSLocalizedString(@"Use Standard Connection", @"use standard connection button") : nil, documentWindow, self, nil, @selector(errorSheetDidEnd:returnCode:contextInfo:), @"connect", theErrorMessage);
}
-
/**
* Alert sheet callback method - invoked when an error sheet is closed.
*/
- (void)errorSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(NSString *)contextInfo
{
[sheet orderOut:self];
- if (returnCode == NSAlertAlternateReturn) [errorDetailWindow makeKeyAndOrderFront:self];
-
+
// Restore the passwords from keychain for editing if appropriate
if (connectionKeychainItemName) {
[self setPassword:[keychain getPasswordForName:connectionKeychainItemName account:connectionKeychainItemAccount]];
@@ -400,6 +409,29 @@
if (connectionSSHKeychainItemName) {
[self setSshPassword:[keychain getPasswordForName:connectionSSHKeychainItemName account:connectionSSHKeychainItemAccount]];
}
+
+ if (returnCode == NSAlertAlternateReturn) {
+ [errorDetailWindow makeKeyAndOrderFront:self];
+ }
+ // Currently only SSH port bind errors offer a 3rd option in the error dialog, but if this ever changes
+ // this will definitely need to be updated.
+ else if (returnCode == NSAlertOtherReturn) {
+ // Extract the local port number that SSH attempted to bind to from the debug output
+ NSString *tunnelPort = [[[errorDetailText string] componentsMatchedByRegex:@"LOCALHOST:([0-9]+)" capture:1L] lastObject];
+
+ // Change the connection type to standard TCP/IP
+ [self setType:SP_CONNECTION_TCPIP];
+
+ // Change connection details
+ [self setPort:tunnelPort];
+ [self setHost:@"127.0.0.1"];
+
+ // Change to standard TCP/IP connection view
+ [self resizeTabViewToConnectionType:SP_CONNECTION_TCPIP animating:YES];
+
+ // Initiate the connection after half a second to give the connection view a chance to resize
+ [self performSelector:@selector(initiateConnection:) withObject:self afterDelay:0.5];
+ }
}
/**
diff --git a/Source/SPSSHTunnel.m b/Source/SPSSHTunnel.m
index 3623a2f2..6c5be81c 100644
--- a/Source/SPSSHTunnel.m
+++ b/Source/SPSSHTunnel.m
@@ -387,7 +387,7 @@
connectionState = PROXY_STATE_IDLE;
[task terminate];
if (lastError) [lastError release];
- lastError = [[NSString alloc] initWithString:NSLocalizedString(@"The SSH Tunnel was unable to bind to the local port. This error may occur if you already have an SSH connection to the same server and are using a 'LocalForward' option in your SSH configuration.", @"SSH tunnel unable to bind to local port message")];
+ lastError = [[NSString alloc] initWithString:NSLocalizedString(@"The SSH Tunnel was unable to bind to the local port. This error may occur if you already have an SSH connection to the same server and are using a 'LocalForward' setting in your SSH configuration.\n\nWould you like to fall back to a standard connection to localhost in order to use the existing tunnel?", @"SSH tunnel unable to bind to local port message")];
if (delegate) [delegate performSelectorOnMainThread:stateChangeSelector withObject:self waitUntilDone:NO];
}
diff --git a/Source/SPTableData.m b/Source/SPTableData.m
index e61eb552..083de094 100644
--- a/Source/SPTableData.m
+++ b/Source/SPTableData.m
@@ -433,9 +433,8 @@
int nextOffs = 12;
if( [parts count] > 8 ) {
- // NOTE: this won't get SET NULL | NO ACTION
+ // NOTE: this won't get SET NULL | NO ACTION | RESTRICT
if( [[parts objectAtIndex:9] hasPrefix:@"UPDATE"] ) {
- //NSLog( @"update: %@", [parts objectAtIndex:10] );
if( [NSArrayObjectAtIndex(parts, 10) hasPrefix:@"SET"] ) {
[constraintDetails setObject:@"SET NULL"
forKey:@"update"];
@@ -450,7 +449,6 @@
}
}
else if( [NSArrayObjectAtIndex(parts, 9) hasPrefix:@"DELETE"] ) {
- //NSLog( @"delete: %@", [parts objectAtIndex:10] );
if( [NSArrayObjectAtIndex(parts, 10) hasPrefix:@"SET"] ) {
[constraintDetails setObject:@"SET NULL"
forKey:@"delete"];
@@ -467,7 +465,6 @@
}
if( [parts count] > nextOffs - 1 ) {
if( [NSArrayObjectAtIndex(parts, nextOffs) hasPrefix:@"UPDATE"] ) {
- //NSLog( @"update: %@", [parts objectAtIndex:13] );
if( [NSArrayObjectAtIndex(parts, nextOffs+1) hasPrefix:@"SET"] ) {
[constraintDetails setObject:@"SET NULL"
forKey:@"update"];
@@ -480,7 +477,6 @@
}
}
else if( [NSArrayObjectAtIndex(parts, nextOffs) hasPrefix:@"DELETE"] ) {
- //NSLog( @"delete: %@", [parts objectAtIndex:13] );
if( [NSArrayObjectAtIndex(parts, nextOffs+1) hasPrefix:@"SET"] ) {
[constraintDetails setObject:@"SET NULL"
forKey:@"delete"];
@@ -498,7 +494,6 @@
}
// primary key
else if( [NSArrayObjectAtIndex(parts, 0) hasPrefix:@"PRIMARY"] ) {
- //NSLog( @"pkey is %@", [[parts objectAtIndex:2] stringByTrimmingCharactersInSet:junk] );
}
// key
else if( [NSArrayObjectAtIndex(parts, 0) hasPrefix:@"KEY"] ) {