diff --git a/ChangeLog b/ChangeLog index 93af3f4a9..68c7acee3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,7 @@ 2002-06-16 Richard Frith-Macdonald - * Source/GSFTPURLHandle.m: partial implementation added (compiles - but does not work). - * Source/NSURLHandle.m: Register GSFTPURLHandle so once it works - it can be used. + * Source/GSFTPURLHandle.m: simple implementation added + * Source/NSURLHandle.m: Register GSFTPURLHandle for ftp scheme. * Source/GSHTTPURLHandle.m: modified so that data being read is reported periodically during the read proces rather than just at end. diff --git a/Source/GSFTPURLHandle.m b/Source/GSFTPURLHandle.m index 5533c8cb8..1f6937013 100644 --- a/Source/GSFTPURLHandle.m +++ b/Source/GSFTPURLHandle.m @@ -269,7 +269,7 @@ NSString * const GSTelnetTextKey = @"GSTelnetTextKey"; if (d != nil) { -//NSLog(@"Read - '%@'", d); +// NSLog(@"Read - '%@'", d); [ibuf appendData: d]; } old = len = [ibuf length]; @@ -487,6 +487,7 @@ NSString * const GSTelnetTextKey = @"GSTelnetTextKey"; sentType, // Sent data type sentPasv, // Requesting host/port information for data link data, // Establishing or using data connection + list, // listing directory } state; } - (void) _control: (NSNotification*)n; @@ -721,6 +722,23 @@ static NSLock *urlLock = nil; } else if (state == data) { + if ([line hasPrefix: @"550"] == YES && wData == nil) + { + state = list; + [cHandle putTelnetLine: + [NSString stringWithFormat: @"NLST %@", [url path]]]; + } + else if ([line hasPrefix: @"1"] == NO && [line hasPrefix: @"2"] == NO) + { + e = line; + } + } + else if (state == list) + { + if ([line hasPrefix: @"1"] == NO && [line hasPrefix: @"2"] == NO) + { + e = line; + } } else { @@ -826,11 +844,29 @@ static NSLock *urlLock = nil; } else { + NSNotificationCenter *nc; + NSData *tmp; + + nc = [NSNotificationCenter defaultCenter]; + if (dHandle != nil) + { + [nc removeObserver: self name: nil object: dHandle]; + [dHandle closeFile]; + DESTROY(dHandle); + } + [nc removeObserver: self + name: GSTelnetNotification + object: cHandle]; + DESTROY(cHandle); + state = idle; + /* * Tell superclass that we have successfully loaded the data. */ - [self didLoadBytes: wData loadComplete: YES]; - DESTROY(wData); + tmp = wData; + wData = nil; + [self didLoadBytes: tmp loadComplete: YES]; + DESTROY(tmp); } } } @@ -904,17 +940,38 @@ static NSLock *urlLock = nil; } /** - * Writes the specified data as the ftp file. - * Returns YES on success, - * NO on failure. - * On completion, the resource data for this handle is set to the - * data written. + * We cannot get/set any properties for FTP */ -- (BOOL) writeData: (NSData*)d +- (id) propertyForKey: (NSString*)propertyKey { - ASSIGN(wData, d); + return nil; +} + +/** + * We cannot get/set any properties for FTP + */ +- (id) propertyForKeyIfAvailable: (NSString*)propertyKey +{ + return nil; +} + +/** + * Sets the specified data to be written to the URL on the next load. + */ +- (BOOL) writeData: (NSData*)data +{ + ASSIGN(wData, data); return YES; } +/** + * We cannot get/set any properties for FTP + */ +- (BOOL) writeProperty: (id)propertyValue + forKey: (NSString*)propertyKey +{ + return NO; +} + @end diff --git a/Testing/call.m b/Testing/call.m index 358b88bf6..899b84e39 100644 --- a/Testing/call.m +++ b/Testing/call.m @@ -11,14 +11,21 @@ #include +@class GSTelnetHandle; +extern NSString * const GSTelnetNotification; +extern NSString * const GSTelnetErrorKey; +extern NSString * const GSTelnetTextKey; + @interface Call : NSObject { NSFileHandle *ichan; NSFileHandle *ochan; - NSFileHandle *remote; + GSTelnetHandle *remote; + NSMutableData *buf; } - (void) didRead: (NSNotification*)notification; - (void) didWrite: (NSNotification*)notification; +- (void) gotTelnet: (NSNotification*)notification; @end @@ -29,13 +36,13 @@ RELEASE(ichan); RELEASE(ochan); RELEASE(remote); + RELEASE(buf); [super dealloc]; } - (void) didRead: (NSNotification*)notification { NSDictionary *userInfo = [notification userInfo]; - NSFileHandle *object = [notification object]; NSData *d; d = [userInfo objectForKey: NSFileHandleNotificationDataItem]; @@ -46,16 +53,39 @@ } else { - if (object == ichan) + char *ptr; + unsigned len; + int i; + + [buf appendData: d]; + ptr = [buf mutableBytes]; + len = [buf length]; + for (i = 0; i < len; i++) { - [remote writeInBackgroundAndNotify: d]; - [ichan readInBackgroundAndNotify]; - } - else - { - [ochan writeInBackgroundAndNotify: d]; - [remote readInBackgroundAndNotify]; + if (ptr[i] == '\n') + { + NSString *s; + + if (i > 0 && ptr[i-1] == '\r') + { + s = [NSString stringWithCString: ptr length: i-1]; + } + else + { + s = [NSString stringWithCString: ptr length: i]; + } + len -= (i + 1); + if (len > 0) + { + memcpy(ptr, &ptr[i+1], len); + } + [buf setLength: len]; + ptr = [buf mutableBytes]; + i = -1; + [remote putTelnetLine: s]; + } } + [ichan readInBackgroundAndNotify]; } } @@ -72,6 +102,29 @@ } } +- (void) gotTelnet: (NSNotification*)notification +{ + NSDictionary *info = [notification userInfo]; + NSArray *text; + + text = [info objectForKey: GSTelnetTextKey]; + if (text == nil) + { + NSLog(@"Lost telnet - %@", [info objectForKey: GSTelnetErrorKey]); + exit(0); + } + else + { + unsigned i; + + for (i = 0; i < [text count]; i++) + { + [ochan writeInBackgroundAndNotify: + [[text objectAtIndex: i] dataUsingEncoding: NSUTF8StringEncoding]]; + } + } +} + - (id) init { NSArray *args = [[NSProcessInfo processInfo] arguments]; @@ -91,10 +144,12 @@ } } } + buf = [NSMutableData new]; ichan = RETAIN([NSFileHandle fileHandleWithStandardInput]); ochan = RETAIN([NSFileHandle fileHandleWithStandardOutput]); - remote = RETAIN([NSFileHandle fileHandleAsClientAtAddress: - host service: service protocol: protocol]); + remote = [[GSTelnetHandle alloc] initWithHandle: + [NSFileHandle fileHandleAsClientAtAddress: + host service: service protocol: protocol] isConnected: YES]; if (remote == nil) { NSLog(@"Failed to create connection"); @@ -107,20 +162,15 @@ [nc addObserver: self selector: @selector(didRead:) name: NSFileHandleReadCompletionNotification - object: (id)ichan]; + object: ichan]; [nc addObserver: self selector: @selector(didWrite:) name: GSFileHandleWriteCompletionNotification - object: (id)ochan]; + object: ochan]; [nc addObserver: self - selector: @selector(didRead:) - name: NSFileHandleReadCompletionNotification - object: (id)remote]; - [nc addObserver: self - selector: @selector(didWrite:) - name: GSFileHandleWriteCompletionNotification - object: (id)remote]; - [remote readInBackgroundAndNotify]; + selector: @selector(gotTelnet:) + name: GSTelnetNotification + object: remote]; [ichan readInBackgroundAndNotify]; } return self;