diff options
Diffstat (limited to 'SSHTunnel_old.m')
-rwxr-xr-x | SSHTunnel_old.m | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/SSHTunnel_old.m b/SSHTunnel_old.m new file mode 100755 index 00000000..57a458eb --- /dev/null +++ b/SSHTunnel_old.m @@ -0,0 +1,225 @@ +/* + +SSHTunnel.m + +Original code by tynsoe.org, Copyright 2002 +Modified by Lorenz Textor for use with CocoaMySQL + +*/ + +#import "SSHTunnel.h" +#include <unistd.h> + +// start diff lorenz textor +/* +#define T_START @"START: %@" +#define T_STOP @"STOP: %@" +#define S_IDLE @"Idle" +#define S_CONNECTING @"Connecting..." +#define S_CONNECTED @"Connected" +#define S_AUTH @"Authenticated" +#define S_PORT "Port %@ forwarded" +*/ +#define T_START @"START: %@" +#define T_STOP @"STOP: %@" +#define S_IDLE @"Idle" +#define S_CONNECTING @"Connecting..." +#define S_CONNECTED @"Connected" +#define S_AUTH @"Authenticated" +#define S_PORT "Port %@ forwarded" +// end diff lorenz textor + +@implementation SSHTunnel + +// initialization +- (id)init +{ + self = [super init]; + + // Make this class the root one for AppleEvent calls +// [[ NSScriptExecutionContext sharedScriptExecutionContext] setTopLevelObject: self ]; + + return self; +} + +// Getting tunnels informations +- (BOOL)isRunning +/* returns YES if tunnel is running */ +{ + return [ task isRunning ]; +} + +- (NSString*)status +{ + if (status) + return status; + return S_IDLE; +} + +// starting & stopping the tunnel +- (void)startTunnel +/* starts tunnel with saved arguments */ +{ + [self startTunnelWithArguments:tunnelArguments]; +} + +- (void)startTunnelWithArguments:(NSDictionary *)args +/* starts the tunnel */ +{ + NSMutableArray *arguments = [[ NSMutableArray alloc] init ]; + + if (tunnelArguments ) + [tunnelArguments release]; + tunnelArguments = [args retain]; + + // stop tunnel if already running + if ( [self isRunning] ) +// [self stopTunnel]; + return; + + shouldStop = NO; + +// get arguments + [ arguments addObject: @"-N" ]; + [ arguments addObject: @"-v" ]; + +// [ arguments addObject: @"-p" ]; +// [ arguments addObject: @"-p" ]; +// [ arguments addObject: @"22" ]; + +// [ arguments addObject: @"-c"]; +// [ arguments addObject: @"3des"]; + + [ arguments addObject: [ NSString stringWithFormat: @"%@@%@", [args objectForKey:@"connUser"], [args objectForKey:@"connHost"] ]]; + + [ arguments addObject: @"-L" ]; + [ arguments addObject: [NSString stringWithFormat:@"%@/%@/%@", [args objectForKey:@"localPort"], [args objectForKey:@"host"], [args objectForKey:@"remotePort"]] ]; + + [ NSThread detachNewThreadSelector:@selector(launchTunnel:) + toTarget: self + withObject: arguments ]; + + [ arguments release ]; +} + +- (void)stopTunnel +/* stops the tunnel */ +{ + if (! [ self isRunning ]) + return; + shouldStop=YES; + [ self setValue: nil forKey: @"status" ]; + [ task terminate ]; + [[ NSNotificationCenter defaultCenter] postNotificationName:@"STMStatusChanged" object:self ]; +} + +- (void)launchTunnel:(NSArray*)arguments +/* launches the tunnel in a separate thread */ +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + if (task) + [ task release ]; + task = [[ NSTask alloc ] init ]; + NSMutableDictionary *environment = [ NSMutableDictionary dictionaryWithDictionary: [[ NSProcessInfo processInfo ] environment ]]; + NSString *pathToAuthentifier = [[ NSBundle mainBundle ] pathForResource: @"askForPass" ofType: @"sh" ]; + + [ task setLaunchPath: @"/usr/bin/ssh" ]; + [ task setArguments: arguments ]; + +// really necessary??? + [ environment removeObjectForKey: @"SSH_AGENT_PID" ]; + [ environment removeObjectForKey: @"SSH_AUTH_SOCK" ]; + [ environment setObject: pathToAuthentifier forKey: @"SSH_ASKPASS" ]; + [ environment setObject:@":0" forKey:@"DISPLAY" ]; + + [ environment setObject: @"CocoaMySQL Tunnel" forKey: @"TUNNEL_NAME" ]; + [ task setEnvironment: environment ]; + + stdErrPipe = [[ NSPipe alloc ] init ]; + [ task setStandardError: stdErrPipe ]; + + [[ NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(stdErr:) + name: @"NSFileHandleDataAvailableNotification" + object:[ stdErrPipe fileHandleForReading]]; + + [[ stdErrPipe fileHandleForReading] waitForDataInBackgroundAndNotify ]; + + NSLog(T_START,@"CocoaMySQL Tunnel"); + [ self setValue: S_CONNECTING forKey: @"status" ]; + [ task launch ]; + [[ NSNotificationCenter defaultCenter] postNotificationName:@"STMStatusChanged" object:self ]; + [ task waitUntilExit ]; + sleep(1); + [ self setValue: S_IDLE forKey: @"status" ]; + NSLog(T_STOP,@"CocoaMySQL Tunnel"); + [[ NSNotificationCenter defaultCenter] removeObserver:self + name: @"NSFileHandleDataAvailableNotification" + object:[ stdErrPipe fileHandleForReading]]; + [ task release ]; + task = nil; + [ stdErrPipe release ]; + stdErrPipe = nil; + [[ NSNotificationCenter defaultCenter] postNotificationName:@"STMStatusChanged" object:self ]; + if (! shouldStop) + [ self startTunnel ]; + [ pool release ]; +} + +- (void)stdErr:(NSNotification*)aNotification +{ + NSData *data = [[ aNotification object ] availableData ]; + NSString *log = [[ NSString alloc ] initWithData: data encoding: NSASCIIStringEncoding ]; + BOOL wait = YES; + if ([ log length ]) + { + NSLog(log); + NSArray *lines = [ log componentsSeparatedByString:@"\n" ]; + NSEnumerator *e = [ lines objectEnumerator ]; + NSString *line; + while (line = [ e nextObject ]) + { + if ([ line rangeOfString:@"Entering interactive session." ].location != NSNotFound) + { + [ self setValue: S_CONNECTED forKey: @"status"]; + } + if ([ line rangeOfString:@"Authentication succeeded" ].location != NSNotFound) + [ self setValue: S_AUTH forKey: @"status"]; + if ([ line rangeOfString:@"Connections to local port" ].location != NSNotFound) + { + NSScanner *s; + NSString *port; + s = [ NSScanner scannerWithString:log]; + [ s scanUpToString: @"Connections to local port " intoString: nil ]; + [ s scanString: @"Connections to local port " intoString: nil ]; + [ s scanUpToString: @"forwarded" intoString:&port]; + [ self setValue: [ NSString stringWithFormat: @"Port %@ forwarded", port ] forKey: @"status"]; + } + if ([ line rangeOfString:@"closed by remote host." ].location != NSNotFound) + { + [ task terminate]; + [ self setValue: @"Connection closed" forKey: @"status"]; + wait = NO; + } + [[ NSNotificationCenter defaultCenter] postNotificationName:@"STMStatusChanged" object:self ]; + } + if (wait) + [[ stdErrPipe fileHandleForReading ] waitForDataInBackgroundAndNotify ]; + } + [ log release] ; +} + +// deallocation +- (void) dealloc +{ + [self stopTunnel]; + + [task release]; + [stdErrPipe release]; + [status release]; + [tunnelArguments release]; + + [super dealloc]; +} + +@end |