Implement ftp upload and download.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@13897 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2002-06-16 14:54:26 +00:00
parent b694b824d6
commit 13aa2c1ad0
3 changed files with 141 additions and 36 deletions

View file

@ -1,9 +1,7 @@
2002-06-16 Richard Frith-Macdonald <rfm@gnu.org> 2002-06-16 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSFTPURLHandle.m: partial implementation added (compiles * Source/GSFTPURLHandle.m: simple implementation added
but does not work). * Source/NSURLHandle.m: Register GSFTPURLHandle for ftp scheme.
* Source/NSURLHandle.m: Register GSFTPURLHandle so once it works
it can be used.
* Source/GSHTTPURLHandle.m: modified so that data being read is * Source/GSHTTPURLHandle.m: modified so that data being read is
reported periodically during the read proces rather than just at end. reported periodically during the read proces rather than just at end.

View file

@ -269,7 +269,7 @@ NSString * const GSTelnetTextKey = @"GSTelnetTextKey";
if (d != nil) if (d != nil)
{ {
//NSLog(@"Read - '%@'", d); // NSLog(@"Read - '%@'", d);
[ibuf appendData: d]; [ibuf appendData: d];
} }
old = len = [ibuf length]; old = len = [ibuf length];
@ -487,6 +487,7 @@ NSString * const GSTelnetTextKey = @"GSTelnetTextKey";
sentType, // Sent data type sentType, // Sent data type
sentPasv, // Requesting host/port information for data link sentPasv, // Requesting host/port information for data link
data, // Establishing or using data connection data, // Establishing or using data connection
list, // listing directory
} state; } state;
} }
- (void) _control: (NSNotification*)n; - (void) _control: (NSNotification*)n;
@ -721,6 +722,23 @@ static NSLock *urlLock = nil;
} }
else if (state == data) 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 else
{ {
@ -826,11 +844,29 @@ static NSLock *urlLock = nil;
} }
else 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. * Tell superclass that we have successfully loaded the data.
*/ */
[self didLoadBytes: wData loadComplete: YES]; tmp = wData;
DESTROY(wData); wData = nil;
[self didLoadBytes: tmp loadComplete: YES];
DESTROY(tmp);
} }
} }
} }
@ -904,17 +940,38 @@ static NSLock *urlLock = nil;
} }
/** /**
* Writes the specified data as the <code>ftp</code> file. * We cannot get/set any properties for FTP
* Returns YES on success,
* NO on failure.
* On completion, the resource data for this handle is set to the
* data written.
*/ */
- (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; return YES;
} }
/**
* We cannot get/set any properties for FTP
*/
- (BOOL) writeProperty: (id)propertyValue
forKey: (NSString*)propertyKey
{
return NO;
}
@end @end

View file

@ -11,14 +11,21 @@
#include <Foundation/Foundation.h> #include <Foundation/Foundation.h>
@class GSTelnetHandle;
extern NSString * const GSTelnetNotification;
extern NSString * const GSTelnetErrorKey;
extern NSString * const GSTelnetTextKey;
@interface Call : NSObject @interface Call : NSObject
{ {
NSFileHandle *ichan; NSFileHandle *ichan;
NSFileHandle *ochan; NSFileHandle *ochan;
NSFileHandle *remote; GSTelnetHandle *remote;
NSMutableData *buf;
} }
- (void) didRead: (NSNotification*)notification; - (void) didRead: (NSNotification*)notification;
- (void) didWrite: (NSNotification*)notification; - (void) didWrite: (NSNotification*)notification;
- (void) gotTelnet: (NSNotification*)notification;
@end @end
@ -29,13 +36,13 @@
RELEASE(ichan); RELEASE(ichan);
RELEASE(ochan); RELEASE(ochan);
RELEASE(remote); RELEASE(remote);
RELEASE(buf);
[super dealloc]; [super dealloc];
} }
- (void) didRead: (NSNotification*)notification - (void) didRead: (NSNotification*)notification
{ {
NSDictionary *userInfo = [notification userInfo]; NSDictionary *userInfo = [notification userInfo];
NSFileHandle *object = [notification object];
NSData *d; NSData *d;
d = [userInfo objectForKey: NSFileHandleNotificationDataItem]; d = [userInfo objectForKey: NSFileHandleNotificationDataItem];
@ -46,16 +53,39 @@
} }
else 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]; if (ptr[i] == '\n')
[ichan readInBackgroundAndNotify]; {
} NSString *s;
else
{ if (i > 0 && ptr[i-1] == '\r')
[ochan writeInBackgroundAndNotify: d]; {
[remote readInBackgroundAndNotify]; 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 - (id) init
{ {
NSArray *args = [[NSProcessInfo processInfo] arguments]; NSArray *args = [[NSProcessInfo processInfo] arguments];
@ -91,10 +144,12 @@
} }
} }
} }
buf = [NSMutableData new];
ichan = RETAIN([NSFileHandle fileHandleWithStandardInput]); ichan = RETAIN([NSFileHandle fileHandleWithStandardInput]);
ochan = RETAIN([NSFileHandle fileHandleWithStandardOutput]); ochan = RETAIN([NSFileHandle fileHandleWithStandardOutput]);
remote = RETAIN([NSFileHandle fileHandleAsClientAtAddress: remote = [[GSTelnetHandle alloc] initWithHandle:
host service: service protocol: protocol]); [NSFileHandle fileHandleAsClientAtAddress:
host service: service protocol: protocol] isConnected: YES];
if (remote == nil) if (remote == nil)
{ {
NSLog(@"Failed to create connection"); NSLog(@"Failed to create connection");
@ -107,20 +162,15 @@
[nc addObserver: self [nc addObserver: self
selector: @selector(didRead:) selector: @selector(didRead:)
name: NSFileHandleReadCompletionNotification name: NSFileHandleReadCompletionNotification
object: (id)ichan]; object: ichan];
[nc addObserver: self [nc addObserver: self
selector: @selector(didWrite:) selector: @selector(didWrite:)
name: GSFileHandleWriteCompletionNotification name: GSFileHandleWriteCompletionNotification
object: (id)ochan]; object: ochan];
[nc addObserver: self [nc addObserver: self
selector: @selector(didRead:) selector: @selector(gotTelnet:)
name: NSFileHandleReadCompletionNotification name: GSTelnetNotification
object: (id)remote]; object: remote];
[nc addObserver: self
selector: @selector(didWrite:)
name: GSFileHandleWriteCompletionNotification
object: (id)remote];
[remote readInBackgroundAndNotify];
[ichan readInBackgroundAndNotify]; [ichan readInBackgroundAndNotify];
} }
return self; return self;