diff options
author | stuconnolly <stuart02@gmail.com> | 2009-08-28 18:27:36 +0000 |
---|---|---|
committer | stuconnolly <stuart02@gmail.com> | 2009-08-28 18:27:36 +0000 |
commit | aea8e96f2adc91b64e7c521f34890e93f27da36c (patch) | |
tree | cfdaf58dfe18e46c890023cbe53f17231097beb5 | |
parent | 480e035307bfc2dfa5feee16dacd43150b520d6a (diff) | |
download | sequelpro-aea8e96f2adc91b64e7c521f34890e93f27da36c.tar.gz sequelpro-aea8e96f2adc91b64e7c521f34890e93f27da36c.tar.bz2 sequelpro-aea8e96f2adc91b64e7c521f34890e93f27da36c.zip |
If the SSH tunnel is unable to bind to the local port because there is already an existing tunnel, give the user the option of using a standard connection to localhost on the port that is in use in order to use the existing tunnel. Fixes issue #371.
-rw-r--r-- | Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m | 21 | ||||
-rw-r--r-- | Interfaces/English.lproj/ConnectionView.xib | 13 | ||||
-rw-r--r-- | Source/SPConnectionController.m | 44 | ||||
-rw-r--r-- | Source/SPSSHTunnel.m | 2 | ||||
-rw-r--r-- | Source/SPTableData.m | 7 |
5 files changed, 60 insertions, 27 deletions
diff --git a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m index 06a8a757..fd2d6444 100644 --- a/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m +++ b/Frameworks/MCPKit/MCPFoundationKit/MCPConnection.m @@ -192,8 +192,7 @@ static BOOL sTruncateLongFieldInLogs = YES; { delegate = connectionDelegate; - // Check that the delegate implements willQueryString:connection: and cache the result as its used - // vert frequently. + // Check that the delegate implements willQueryString:connection: and cache the result as its used very frequently. delegateResponseToWillQueryString = [delegate respondsToSelector:@selector(willQueryString:connection:)]; } @@ -273,11 +272,11 @@ static BOOL sTruncateLongFieldInLogs = YES; */ - (BOOL)connect { - const char *theLogin = [self cStringFromString:connectionLogin]; - const char *theHost; - const char *thePass; - const char *theSocket; - void *theRet; + const char *theLogin = [self cStringFromString:connectionLogin]; + const char *theHost; + const char *thePass; + const char *theSocket; + void *theRet; // Disconnect if a connection is already active if (mConnected) { @@ -301,8 +300,6 @@ static BOOL sTruncateLongFieldInLogs = YES; // Set the host as appropriate if (!connectionHost || ![connectionHost length]) { theHost = NULL; - - } else { theHost = [self cStringFromString:connectionHost]; } @@ -559,7 +556,7 @@ static BOOL sTruncateLongFieldInLogs = YES; * ping, but cause long queries to be terminated. * Unlike mysql_ping, this function returns FALSE on failure and TRUE on success. */ -- (BOOL) pingConnection +- (BOOL)pingConnection { struct sigaction timeoutAction; NSDate *startDate = [[NSDate alloc] initWithTimeIntervalSinceNow:0]; @@ -1531,7 +1528,7 @@ static void forcePingTimeout(NSInteger signalNumber) const char *theCDBsName = (const char *)[self cStringFromString:dbsName]; if (theResPtr = mysql_list_dbs(mConnection, theCDBsName)) { - [theResult initWithResPtr: theResPtr encoding: mEncoding timeZone:mTimeZone]; + [theResult initWithResPtr:theResPtr encoding:mEncoding timeZone:mTimeZone]; } else { [theResult init]; @@ -1593,11 +1590,13 @@ static void forcePingTimeout(NSInteger signalNumber) [theResult init]; } } + [queryLock unlock]; if (theResult) { [theResult autorelease]; } + return theResult; } diff --git a/Interfaces/English.lproj/ConnectionView.xib b/Interfaces/English.lproj/ConnectionView.xib index 2eb2d7a1..c47e0ab7 100644 --- a/Interfaces/English.lproj/ConnectionView.xib +++ b/Interfaces/English.lproj/ConnectionView.xib @@ -2,9 +2,9 @@ <archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03"> <data> <int key="IBDocument.SystemTarget">1050</int> - <string key="IBDocument.SystemVersion">9J61</string> + <string key="IBDocument.SystemVersion">9L30</string> <string key="IBDocument.InterfaceBuilderVersion">677</string> - <string key="IBDocument.AppKitVersion">949.46</string> + <string key="IBDocument.AppKitVersion">949.54</string> <string key="IBDocument.HIToolboxVersion">353.00</string> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -3673,7 +3673,7 @@ <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> - <string>{{61, 193}, {882, 563}}</string> + <string>{{280, 258}, {882, 563}}</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> @@ -4069,6 +4069,13 @@ </object> <object class="IBPartialClassDescription"> <string key="className">NSObject</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">Source/SPQueryFavoriteManager.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> <object class="NSMutableDictionary" key="actions"> <string key="NS.key.0">toggleCollapse:</string> <string key="NS.object.0">id</string> 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"] ) { |