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:
Richard Frith-Macdonald 2002-06-16 14:54:26 +00:00
parent da65452469
commit 1437a6fff4
3 changed files with 141 additions and 36 deletions

View file

@ -1,9 +1,7 @@
2002-06-16 Richard Frith-Macdonald <rfm@gnu.org>
* 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.

View file

@ -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 <code>ftp</code> 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

View file

@ -11,14 +11,21 @@
#include <Foundation/Foundation.h>
@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;