mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 11:35:05 +08:00
* initial commit * initial commit * add port files * ios: Changes to allow creating app bundle without xcode projects * ios: Added mic perms request * ios: Very basic app bundle creation script * ios: Fix -log parameter * ios: Sdk no longer hardcoded and option to compile for simulator * general: Update gitignore * ios: Enable game mode for the app * ios: Compile instructions and updated ipa creation script * ios: Code cleanup * ios: Remove dylibs * general: Remove extra submodules * ios: Remove dylibs again * ios: Implement suggested changes * ios: Fix building as dylib instead of binary * ios: Scripts for building mods * ios: Move 'ios' contents to engine/platform/ios/bundle and modify scripts * ios: Update createipa.sh to use waf install * ios: Clean script and updated README * general: Fix spelling mistake and outdated instructions * ios: Clean up in xcompile.py * ios: Fix createipa.sh generating an invalid ipa * ios: Temporary fix for launch dialog textfield colors in dark mode
1221 lines
45 KiB
Objective-C
1221 lines
45 KiB
Objective-C
/*
|
|
iosFtpServer
|
|
Copyright (C) 2008 Richard Dearlove ( monsta )
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
#import "FtpConnection.h"
|
|
#import "FtpServer.h"
|
|
|
|
|
|
@implementation FtpConnection
|
|
|
|
@synthesize transferMode;
|
|
@synthesize currentFile;
|
|
@synthesize currentDir;
|
|
@synthesize rnfrFilename;
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(id)initWithAsyncSocket:(AsyncSocket*)newSocket forServer:(id)myServer
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
self = [super init ];
|
|
if (self)
|
|
{
|
|
connectionSocket = [newSocket retain ];
|
|
server = myServer;
|
|
[ connectionSocket setDelegate:self ];
|
|
[ connectionSocket writeData:DATASTR(@"220 iosFtp server ready.\r\n") withTimeout:-1 tag:0 ]; // send out the welcome message to the client
|
|
[ connectionSocket readDataToData:[AsyncSocket CRLFData] withTimeout:READ_TIMEOUT tag:FTP_CLIENT_REQUEST ]; // start listening for commands on this connection to client
|
|
dataListeningSocket = nil;
|
|
dataPort=2001;
|
|
transferMode = pasvftp;
|
|
queuedData = [[ NSMutableArray alloc ] init ]; // A buffer for sending data when the connection isn't quite up yet
|
|
self.currentDir = [ server.baseDir copy]; // the working directory for this connection, Starts in the directory the server is set to. set chroot=true in server code to sandbox in
|
|
currentFile = nil;
|
|
currentFileHandle = nil; // not saving to a file yet
|
|
rnfrFilename = nil;
|
|
|
|
currentUser = nil;
|
|
NSLog(@"FC: Current Directory starting at %@",currentDir );
|
|
}
|
|
return self;
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)dealloc
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
if(connectionSocket)
|
|
{
|
|
[connectionSocket setDelegate:nil];
|
|
[connectionSocket disconnect];
|
|
[connectionSocket release];
|
|
}
|
|
|
|
if(dataListeningSocket){ // 12/2/10 - think this code is now redundant, dataListeningSocket, does it do anything anymore...?
|
|
[dataListeningSocket setDelegate:nil];
|
|
[dataListeningSocket disconnect];
|
|
[dataListeningSocket release];
|
|
|
|
}
|
|
if(dataSocket)
|
|
{
|
|
[dataSocket setDelegate:nil];
|
|
[dataSocket disconnect];
|
|
[dataSocket release];
|
|
|
|
}
|
|
if(dataConnection)[dataConnection release];
|
|
// [msgComponents release];
|
|
if(queuedData)[queuedData release];
|
|
if(currentFile)[currentFile release];
|
|
if(currentUser)[currentUser release];
|
|
[currentDir release];
|
|
if(currentFileHandle) [currentFileHandle release];
|
|
|
|
[super dealloc];
|
|
}
|
|
#pragma mark STATE
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
//-(void)setTransferMode:(int)mode
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
//{
|
|
// transferMode = mode;
|
|
//}
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(NSString*)connectionAddress
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
return [connectionSocket connectedHost];
|
|
|
|
}
|
|
|
|
|
|
// ==========================================================================================================
|
|
#pragma mark CHOOSE DATA SOCKET
|
|
// ==========================================================================================================
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(BOOL)openDataSocket:(int)portNumber
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
NSString *responseString;
|
|
NSError *error = nil;
|
|
|
|
if (dataSocket) // Code changed 2010-02-12 - As per Jon's fix. stops memory leak on socket and connection
|
|
{
|
|
[dataSocket release];
|
|
dataSocket = nil;
|
|
}
|
|
dataSocket = [ [ AsyncSocket alloc ] initWithDelegate:self ]; // create our socket for Listening or Direct Connection
|
|
if (dataConnection)
|
|
{
|
|
[dataConnection release];
|
|
dataConnection = nil;
|
|
}
|
|
|
|
|
|
|
|
switch (transferMode) {
|
|
case portftp:
|
|
dataPort = portNumber;
|
|
responseString = [ NSString stringWithFormat:@"200 PORT command successful."];
|
|
[ dataSocket connectToHost:[self connectionAddress] onPort:portNumber error:&error ];
|
|
// sleep(1);
|
|
dataConnection = [[ FtpDataConnection alloc ] initWithAsyncSocket:dataSocket forConnection:self withQueuedData:queuedData ];
|
|
|
|
break;
|
|
|
|
case lprtftp: // FIXME wrong return message
|
|
dataPort = portNumber;
|
|
responseString = [ NSString stringWithFormat:@"228 Entering Long Passive Mode (af, hal, h1, h2, h3,..., pal, p1, p2...)", dataPort >>8, dataPort & 0xff];
|
|
[ dataSocket connectToHost:[self connectionAddress] onPort:portNumber error:&error ];
|
|
dataConnection = [[ FtpDataConnection alloc ] initWithAsyncSocket:dataSocket forConnection:self withQueuedData:queuedData ];
|
|
break;
|
|
|
|
case eprtftp:
|
|
dataPort = portNumber;
|
|
responseString = @"200 EPRT command successful.";
|
|
[ dataSocket connectToHost:[self connectionAddress] onPort:portNumber error:&error ];
|
|
dataConnection = [[ FtpDataConnection alloc ] initWithAsyncSocket:dataSocket forConnection:self withQueuedData:queuedData ];
|
|
break;
|
|
|
|
case pasvftp:
|
|
dataPort = [ self choosePasvDataPort ];
|
|
NSString *address = [ [connectionSocket localHost ] stringByReplacingOccurrencesOfString:@"." withString:@"," ]; // autoreleased
|
|
responseString = [ NSString stringWithFormat:@"227 Entering Passive Mode (%@,%d,%d)",address, dataPort >>8, dataPort & 0xff];
|
|
[ dataSocket acceptOnPort: dataPort error:&error ];
|
|
dataConnection = nil; // will pickup from the listening socket
|
|
break;
|
|
|
|
case epsvftp:
|
|
dataPort = [ self choosePasvDataPort ];
|
|
responseString = [ NSString stringWithFormat:@"229 Entering Extended Passive Mode (|||%d|)", dataPort ];
|
|
[ dataSocket acceptOnPort: dataPort error:&error ];
|
|
|
|
dataConnection = nil; // will pickup from the listening socket
|
|
break;
|
|
|
|
|
|
default:
|
|
break;
|
|
}
|
|
NSLog( @"-- %@", [ error localizedDescription ] );
|
|
|
|
[ self sendMessage:responseString ];
|
|
|
|
return YES;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(int)choosePasvDataPort
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
struct timeval tv;
|
|
unsigned short int seed[3];
|
|
|
|
gettimeofday(&tv, NULL);
|
|
seed[0] = (tv.tv_sec >> 16) & 0xFFFF;
|
|
seed[1] = tv.tv_sec & 0xFFFF;
|
|
seed[2] = tv.tv_usec & 0xFFFF;
|
|
seed48(seed);
|
|
|
|
int portNumber;
|
|
portNumber = (lrand48() % 64512) + 1024;
|
|
// NSLog(@"New Port number is %i", portNumber );
|
|
|
|
return portNumber; // FIXME - presetting to 2001 for the moment
|
|
|
|
//return 2001;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ==========================================================================================================
|
|
#pragma mark ASYNCSOCKET DATACONNECTION
|
|
// ==========================================================================================================
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(BOOL)onSocketWillConnect:(AsyncSocket *)sock
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
NSLog(@"FC:onSocketWillConnect");
|
|
[ sock readDataWithTimeout:READ_TIMEOUT tag:0 ];
|
|
|
|
return YES;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket // should be for a data connection on 2001
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
// opened socket for passive data - new socket connected to this which is the passive connection
|
|
|
|
NSLog(@"FC:New Connection -- should be for the data port");
|
|
|
|
dataConnection = [[ FtpDataConnection alloc ] initWithAsyncSocket:newSocket forConnection:self withQueuedData:queuedData];
|
|
}
|
|
|
|
|
|
|
|
// ==========================================================================================================
|
|
#pragma mark ASYNCSOCKET FTPCLIENT CONNECTION
|
|
// ==========================================================================================================
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)onSocket:(AsyncSocket*)sock didReadData:(NSData*)data withTag:(long)tag // DATA READ
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
|
|
NSLog(@"FC:didReadData");
|
|
[ connectionSocket readDataToData:[AsyncSocket CRLFData] withTimeout:READ_TIMEOUT tag:FTP_CLIENT_REQUEST ]; // start reading again
|
|
|
|
[ self processDataRead:data ];
|
|
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)onSocket:(AsyncSocket*)sock didWriteDataWithTag:(long)tag // DATA WRITTEN
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
[ connectionSocket readDataToData:[AsyncSocket CRLFData] withTimeout:READ_TIMEOUT tag:FTP_CLIENT_REQUEST ]; // start reading again
|
|
// NSLog(@"FC:didWriteData");
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)sendMessage:(NSString*)ftpMessage // REDUNDANT really - FIXME
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
NSLog(@">%@",ftpMessage );
|
|
NSMutableData *dataString = [[ ftpMessage dataUsingEncoding:NSUTF8StringEncoding ] mutableCopy]; // Autoreleased
|
|
[ dataString appendData:[AsyncSocket CRLFData] ];
|
|
|
|
[ connectionSocket writeData:dataString withTimeout:READ_TIMEOUT tag:FTP_CLIENT_REQUEST ];
|
|
[dataString release];
|
|
[ connectionSocket readDataToData:[AsyncSocket CRLFData] withTimeout:READ_TIMEOUT tag:FTP_CLIENT_REQUEST ]; // start reading again
|
|
// [ connectionSocket readDataWithTimeout:READ_TIMEOUT tag:FTP_CLIENT_REQUEST ];
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)sendDataString:(NSString*)dataString
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
NSMutableString *message = [[NSMutableString alloc] initWithString:dataString];
|
|
CFStringNormalize((CFMutableStringRef)message, kCFStringNormalizationFormC);
|
|
NSMutableData *data = [[ message dataUsingEncoding:server.clientEncoding ] mutableCopy]; // Autoreleased
|
|
[message release];
|
|
|
|
if (dataConnection )
|
|
{ NSLog(@"FC:sendData");
|
|
[ dataConnection writeData:data ];
|
|
|
|
}
|
|
else
|
|
{
|
|
[ queuedData addObject:data ];
|
|
}
|
|
[data release];
|
|
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)sendData:(NSMutableData*)data
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
if (dataConnection )
|
|
{ NSLog(@"FC:sendData");
|
|
[ dataConnection writeData:data ];
|
|
}
|
|
else
|
|
{
|
|
[ queuedData addObject:data ];
|
|
}
|
|
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)didReceiveDataWritten // notification from FtpDataConnection that the dataWasWritten
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
|
|
|
|
|
|
NSLog(@"SENDING COMPLETED");
|
|
|
|
[ self sendMessage:@"226 Transfer complete." ]; // send completed message to client
|
|
[ dataConnection closeConnection ];
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)didReceiveDataRead // notification from FtpDataConnection that the dataWasWritten
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
|
|
NSLog(@"FC:didReceiveDataRead");
|
|
|
|
// must have sent a file
|
|
|
|
// Should start writing file out if not written yet : FIXNOW
|
|
|
|
if ( currentFileHandle != nil )
|
|
{
|
|
// Append data on
|
|
NSLog(@"FC:Writing File to %@", currentFile );
|
|
[ currentFileHandle writeData:dataConnection.receivedData ];
|
|
|
|
}
|
|
else
|
|
{
|
|
NSLog(@"Couldnt write data");
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)didFinishReading // Called at the end of a data connection from the client we presume
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
if (currentFile)
|
|
{
|
|
|
|
NSLog(@"Closing File Handle");
|
|
[currentFile release];
|
|
currentFile = nil;
|
|
}
|
|
else
|
|
{
|
|
NSLog(@"FC:Data Sent but not sure where its for ");
|
|
}
|
|
|
|
[ self sendMessage:@"226 Transfer complete." ]; // send completed message to client
|
|
|
|
// [ dataConnection closeConnection ]; // It must be closed, it dropped us
|
|
|
|
if ( currentFileHandle != nil )
|
|
{
|
|
NSLog(@"Closing File Handle");
|
|
|
|
[ currentFileHandle closeFile ]; // Close the file handle
|
|
[ currentFileHandle release ];
|
|
currentFileHandle = nil;
|
|
[ server didReceiveFileListChanged];
|
|
}
|
|
|
|
dataConnection.connectionState = clientQuiet;
|
|
|
|
}
|
|
|
|
|
|
// ==========================================================================================================
|
|
#pragma mark PROCESS
|
|
// =========================================================================================================
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)processDataRead:(NSData*)data // convert to commands as Client Connection
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
NSData *strData = [data subdataWithRange:NSMakeRange(0, [data length] - 2)]; // remove last 2 chars
|
|
NSString *crlfmessage = [[[NSString alloc] initWithData:strData encoding:server.clientEncoding] autorelease];
|
|
NSString *message;
|
|
|
|
// message = [ crlfmessage stringByReplacingOccurrencesOfString:@"\r\n" withString:@""]; // gets autoreleased
|
|
|
|
message = [ crlfmessage stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet ]];
|
|
NSLog(@"<%@",message );
|
|
msgComponents = [message componentsSeparatedByString:@" "]; // change this to use spaces - for the FTP protocol
|
|
|
|
[ self processCommand ];
|
|
|
|
[connectionSocket readDataToData:[AsyncSocket CRLFData] withTimeout:-1 tag:0 ]; // force to readdata CHECK
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)processCommand // assumes data has been place in Array msgComponents
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
NSString *commandString = [ msgComponents objectAtIndex:0];
|
|
|
|
if ([ commandString length ] > 0) // If there is a command here
|
|
{
|
|
// Search through dictionary for correct matching command and method that it calls
|
|
|
|
NSString *commandSelector = [ [[server commands] objectForKey:[commandString lowercaseString] ] stringByAppendingString:@"arguments:"];
|
|
|
|
if ( commandSelector ) // If we have a matching command
|
|
{
|
|
|
|
SEL action = NSSelectorFromString(commandSelector); // Turn into a method
|
|
|
|
if ( [ self respondsToSelector:action ]) // If we respond to this method
|
|
{
|
|
// DO COMMAND
|
|
[self performSelector:action withObject:self withObject:msgComponents ]; // Preform method with arguments
|
|
}
|
|
else
|
|
{ // UNKNOWN COMMAND
|
|
NSString *outputString =[ NSString stringWithFormat:@"500 '%@': command not understood.", commandString ];
|
|
[ self sendMessage:outputString ];
|
|
|
|
NSLog(@"DONT UNDERSTAND");
|
|
}
|
|
}
|
|
else // UNKNOWN COMMAND
|
|
{
|
|
NSString *outputString =[ NSString stringWithFormat:@"500 '%@': command not understood.", commandString ];
|
|
[ self sendMessage:outputString ];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Write out an error msg
|
|
}
|
|
|
|
}
|
|
|
|
// ==========================================================================================================
|
|
#pragma mark COMMANDS
|
|
// ==========================================================================================================
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doQuit:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
NSLog(@"Quit : %@",arguments);
|
|
|
|
[ self sendMessage:@"221- Data traffic for this session was 0 bytes in 0 files"];
|
|
|
|
[self sendMessage:@"221 Thank you for using the FTP service on localhost." ];
|
|
|
|
if(connectionSocket)
|
|
{
|
|
[connectionSocket disconnectAfterWriting ]; // Will this close the socket ?
|
|
// [connectionSocket disconnect];
|
|
}
|
|
|
|
[ server closeConnection:self ]; // Tell the server to close us down, remove us from the list of connections
|
|
|
|
|
|
// FIXME - delete the dataconnection if its open
|
|
|
|
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doUser:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
// send out confirmation message -- 331 password required for
|
|
if ( currentUser != nil )
|
|
[currentUser release];
|
|
currentUser = [[ arguments objectAtIndex:1 ] retain];
|
|
NSString *outputString = [ NSString stringWithFormat:@"331 Password required for %@", currentUser ];
|
|
[ sender sendMessage:outputString];
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doPass:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
// NSString *pass = [ arguments objectAtIndex:1 ];
|
|
NSString *outputString = [ NSString stringWithFormat:@"230 User %@ logged in.", currentUser ];
|
|
[ sender sendMessage:outputString];
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doStat:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
// Send out stat message
|
|
[ sender sendMessage:@"211-localhost FTP server status:"];
|
|
// FIXME - add in the stats
|
|
[ sender sendMessage:@"211 End of Status"];
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doFeat:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
[ sender sendMessage:@"211-Features supported"];
|
|
|
|
// If encoding is UTF8, notify the client
|
|
if (server.clientEncoding == NSUTF8StringEncoding)
|
|
[ sender sendMessage:@" UTF8" ];
|
|
|
|
[ sender sendMessage:@"211 End"];
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doList:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
// Get the name of any additional directory that we are asked to list, if its empty we use the current directory
|
|
|
|
NSString *lsDir = [ self fileNameFromArgs:arguments] ; // autoreleased, get the directory that we're being asked for
|
|
NSString *listText;
|
|
|
|
|
|
if ([lsDir length]<1) {
|
|
lsDir = currentDir;
|
|
}
|
|
else {
|
|
lsDir = [self rootedPath:lsDir ];
|
|
}
|
|
|
|
|
|
|
|
NSLog( @"doList currentDir(%@) changeRoot%d", lsDir, server.changeRoot );
|
|
NSLog(@"Will list %@ ",lsDir);
|
|
listText = [ [ server createList:lsDir] retain ]; // Can list directory so do it
|
|
// if ([self canChangeDirectoryTo:lsDir]) {
|
|
// listText = [ [ server createList:lsDir] retain ]; // Can list directory so do it
|
|
// }
|
|
// else {
|
|
// listText = @""; // return nothing as not in chroot
|
|
// }
|
|
|
|
NSLog( @"doList sending this. %@", listText );
|
|
|
|
[ sender sendMessage:@"150 Opening ASCII mode data connection for '/bin/ls'."];
|
|
|
|
[ sender sendDataString:listText ];
|
|
[listText release ];
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doPwd:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
|
|
NSLog(@"Will PWD %@ ",[self visibleCurrentDir]);
|
|
|
|
// CHECKME - changed to show basedir - currentdir
|
|
|
|
|
|
NSString *cmdString = [ NSString stringWithFormat:@"257 \"%@\" is the current directory.", [self visibleCurrentDir] ]; // autoreleased
|
|
[ sender sendMessage:cmdString ]; // FIXME - seems to be buggy on ftp command line client
|
|
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doNoop:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
[sender sendMessage:@"200 NOOP command successful." ];
|
|
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doSyst:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
[ sender sendMessage:@"215 UNIX Type: L8 Version: iosFtp 20080912" ];
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doLprt:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
// LPRT,"6,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,231,92"
|
|
NSString *socketDesc = [ arguments objectAtIndex:1 ] ;
|
|
NSArray *socketAddr = [ socketDesc componentsSeparatedByString:@"," ];
|
|
|
|
int hb = [[socketAddr objectAtIndex:19] intValue ];
|
|
int lb = [[socketAddr objectAtIndex:20] intValue ];
|
|
|
|
NSLog(@"%d %d %d",hb <<8, hb,lb );
|
|
int clientPort = (hb <<8 ) + lb;
|
|
|
|
[sender setTransferMode:lprtftp];
|
|
|
|
[ sender openDataSocket:clientPort ];
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doEprt:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
// EPRT |2|1080::8:800:200C:417A|5282|
|
|
|
|
NSString *socketDesc = [ arguments objectAtIndex:1 ] ;
|
|
NSArray *socketAddr = [ socketDesc componentsSeparatedByString:@"|" ];
|
|
|
|
NSString *item;
|
|
for (item in socketAddr) {
|
|
NSLog(@"%@", item);
|
|
}
|
|
int clientPort = [[ socketAddr objectAtIndex:3 ] intValue ];
|
|
|
|
NSLog(@"Got Send Port %d", clientPort );
|
|
|
|
[sender setTransferMode:eprtftp];
|
|
// [ sender initDataSocket:clientPort ];
|
|
[ sender openDataSocket:clientPort ];
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doPasv:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
[sender setTransferMode:pasvftp];
|
|
// [ sender initDataSocket:0 ];
|
|
[ sender openDataSocket:0 ];
|
|
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doEpsv:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
// FIXME - open a port random high address
|
|
[sender setTransferMode:epsvftp];
|
|
// [ sender initDataSocket:0 ];
|
|
[ sender openDataSocket:0 ];
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doPort:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
int hb, lb;
|
|
|
|
// PORT 127,0,0,1,197,251 looks like this
|
|
// get 2nd argument and split up by , and then take the last 2 bits
|
|
|
|
NSString *socketDesc = [ arguments objectAtIndex:1 ] ;
|
|
NSArray *socketAddr = [ socketDesc componentsSeparatedByString:@"," ];
|
|
|
|
hb = [[socketAddr objectAtIndex:4] intValue ];
|
|
lb = [[socketAddr objectAtIndex:5] intValue ];
|
|
|
|
|
|
int clientPort = (hb <<8 ) + lb;
|
|
|
|
|
|
[sender setTransferMode:portftp];
|
|
|
|
[ sender openDataSocket:clientPort ];
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doOpts:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
NSString *cmd = [ arguments objectAtIndex:1 ];
|
|
NSString *cmdstr = [ NSString stringWithFormat:@"502 Unknown command '%@'",cmd ];
|
|
[ sender sendMessage:cmdstr ];
|
|
// 502 Unknown command 'sj'
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doType:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
// 200 Type set to A.
|
|
|
|
// FIXME - change the data output to the matching type -- we dont do anything with this yet,, there are many types apart from this one.
|
|
|
|
NSString *cmd = [ arguments objectAtIndex:1 ];
|
|
|
|
//if ( [ [cmd lowercaseString] isEqualToString:@"i" ])
|
|
// {
|
|
NSString *cmdstr = [ NSString stringWithFormat:@"200 Type set to %@.",cmd ];
|
|
[ sender sendMessage:cmdstr ];
|
|
// }
|
|
// else
|
|
// {
|
|
// NSString *cmdstr = [ NSString stringWithFormat:@"500 'type %@': command not understood.",cmd ];
|
|
// [ sender sendMessage:cmdstr ];
|
|
// }
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doCwd:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
// 250
|
|
// 500, 501, 502, 421, 530, 550
|
|
// 250 CWD command successful.
|
|
|
|
NSLog(@"DoCwd arguments is %@",arguments);
|
|
|
|
NSString *cmdstr;
|
|
NSString *cwdDir = [ self fileNameFromArgs:arguments] ; // autoreleased, get the directory that we're being asked for
|
|
|
|
if ( [ self changedCurrentDirectoryTo:cwdDir ] ) // tries to change to that directory, checks in bounds and viable
|
|
{
|
|
cmdstr = [ NSString stringWithFormat:@"250 OK. Current directory is %@", [self visibleCurrentDir]]; // currentDir is now in the new place
|
|
cmdstr = @"250 CWD command successful.";
|
|
}
|
|
else
|
|
{
|
|
cmdstr = @"550 CWD failed.";
|
|
}
|
|
|
|
[ sender sendMessage:cmdstr];
|
|
|
|
NSLog(@"currentDir is now %@",currentDir );
|
|
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doNlst:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
[self doList:sender arguments:arguments ];
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doStor:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
// eg STOR my filename here.mp3 STOR=0 my=1 filename=2 etc
|
|
|
|
NSFileManager *fs = [NSFileManager defaultManager];
|
|
NSString *filename = [ self fileNameFromArgs:arguments]; // autoreleased
|
|
NSString *cmdstr;
|
|
|
|
self.currentFile = [self makeFilePathFrom:filename]; // makes a filepath, using absolute or relative filename
|
|
|
|
// Check this falls within the area of filesystem we are allowed to write to
|
|
if ( [self validNewFilePath:self.currentFile] ) // FIXME - finish function for test
|
|
{
|
|
// CREATE and then OPEN NEW FILE FOR WRITING
|
|
if ([fs createFileAtPath:self.currentFile contents:nil attributes:nil]==YES)
|
|
{
|
|
currentFileHandle = [[ NSFileHandle fileHandleForWritingAtPath:currentFile] retain]; // Open the file handle to write to
|
|
cmdstr = [ NSString stringWithFormat:@"150 Opening BINARY mode data connection for '%@'.",filename ]; // autoreleased
|
|
}
|
|
else
|
|
{
|
|
// couldn't make file, send out the error
|
|
cmdstr = [ NSString stringWithFormat:@"553 %@: Permission denied.", filename ];
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// couldn't make file as out of root area
|
|
cmdstr = [ NSString stringWithFormat:@"553 %@: Permission denied.", filename ];
|
|
}
|
|
|
|
NSLog(@"FC:doStor %@", currentFile );
|
|
|
|
|
|
[sender sendMessage:cmdstr];
|
|
|
|
// CHECKME - data connection should have been brought up by client?
|
|
if (dataConnection ) // if not we're in trouble. mind u currentFile is doing similar job.
|
|
{
|
|
NSLog(@"FC:setting connection state to clientSending");
|
|
dataConnection.connectionState = clientSending;
|
|
}
|
|
else
|
|
{
|
|
NSLog(@"FC:Erorr Cant set connection state to Client Sending : no Connection yet ");
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doRetr:(id)sender arguments:(NSArray*)arguments // DOWNLOAD to CLIENT
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
BOOL isDir;
|
|
NSString *cmdstr;
|
|
|
|
NSString *filename = [self fileNameFromArgs:arguments]; // autoreleased
|
|
NSString *filePath = [self makeFilePathFrom:filename]; // turns relative or absolute path into format we need
|
|
|
|
NSLog(@"FC:doRetr: %@", filePath );
|
|
|
|
if ( [self accessibleFilePath:filePath ] ) // if this filepath is in rooted area, and is a real file
|
|
{
|
|
if ( [ [ NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory: &isDir ]) // FIXME - fold into previous line
|
|
{
|
|
if ( isDir ){ // reject if its a directory request
|
|
[ sender sendMessage: [NSString stringWithFormat:@"550 %@: Not a plain file.",filename]];
|
|
}
|
|
else // SEND FILE
|
|
{ // FIXME URGENT - need to stop loading whole file into memory to send
|
|
NSMutableData *fileData = [[ NSMutableData dataWithContentsOfFile:filePath ] retain]; // FIXME - open in bits ? seems risky opening file in one piece
|
|
cmdstr = [ NSString stringWithFormat:@"150 Opening BINARY mode data connection for '%@'.",filename ];
|
|
[sender sendMessage:cmdstr];
|
|
|
|
[ sender sendData:fileData ]; // Send file
|
|
[fileData release ];
|
|
}
|
|
}
|
|
}
|
|
else // doesn't exist or not in basedir sandbox
|
|
{
|
|
cmdstr = [ NSString stringWithFormat:@"50 %@ No such file or directory.",filename ];
|
|
NSLog(@"FC:doRetr: file %@ doesnt' exist ", filePath);
|
|
[sender sendMessage:cmdstr];
|
|
}
|
|
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doDele:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
NSString *cmdStr;
|
|
NSError *error;
|
|
NSString *filename =[self fileNameFromArgs:arguments]; // autoreleased
|
|
NSString *filePath = [self makeFilePathFrom:filename];
|
|
|
|
NSLog(@"filename is %@",filename);
|
|
|
|
// attempt to delete the file
|
|
|
|
if ( [self accessibleFilePath:filePath ]) // exists and can access
|
|
{
|
|
if ([[ NSFileManager defaultManager ] removeItemAtPath:filePath error:&error ])
|
|
{
|
|
cmdStr = [ NSString stringWithFormat:@"250 DELE command successful.",filename ];
|
|
[ server didReceiveFileListChanged]; // Addition by Brendan copied in by Rich 16/12/08
|
|
}
|
|
else
|
|
{
|
|
cmdStr = [ NSString stringWithFormat:@"550 DELE command unsuccessful.",filename ]; // FIXME put correct error code in
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cmdStr = [ NSString stringWithFormat:@"550 %@ No such file or directory.", filename];
|
|
}
|
|
|
|
[ sender sendMessage:cmdStr ];
|
|
|
|
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doMlst:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
NSString *filename = [self fileNameFromArgs: arguments];
|
|
NSString *cmdstr = [ NSString stringWithFormat:@"150 Opening BINARY mode data connection for '%@'.",filename ];
|
|
// tell connection to expect a file
|
|
|
|
[sender sendMessage:cmdstr]; // FIXME - this doesn't do anything beyond respond with first message
|
|
/* typiccal output to generate
|
|
250: MLST 2012.pdf
|
|
Type=file;Size=2420017;Modify=20080808074805;Perm=adfrw;Unique=AgAADpIHZwA; /Users/monsta/Documents/2012.pdf
|
|
End
|
|
*/
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doSize:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
NSString *cmdStr;
|
|
NSString *filename = [self fileNameFromArgs: arguments]; // Autoreleased
|
|
NSString *filePath = [self makeFilePathFrom:filename]; // Autoreleased
|
|
|
|
if ([self accessibleFilePath:filePath]) // Can we reach that file ?
|
|
{
|
|
if ([self fileSize:filePath] < 10240) // If small enough for old style size command
|
|
{
|
|
cmdStr = [ NSString stringWithFormat:@"213 %qu",[self fileSize:filePath] ]; // report size
|
|
}
|
|
else
|
|
{
|
|
cmdStr = [ NSString stringWithFormat:@"550 %@ file too large for SIZE.",filename ];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cmdStr = [ NSString stringWithFormat:@"550 %@ No such file or directory.",filename ]; // report file not found
|
|
}
|
|
|
|
// tell connection to expect a file
|
|
|
|
[sender sendMessage:cmdStr];
|
|
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doMkdir:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
NSLog(@"current dir is %@",currentDir);
|
|
|
|
NSString *cmdStr;
|
|
NSString *p = [self makeFilePathFrom:[self fileNameFromArgs:arguments]];
|
|
NSFileManager *fs = [NSFileManager defaultManager];
|
|
|
|
if ( [self validNewFilePath:p ]) // FIXME - make sure function works. see function
|
|
{
|
|
if( [fs fileExistsAtPath:p isDirectory:nil] )
|
|
{
|
|
cmdStr = [ NSString stringWithFormat:@"Error %@ exists",[self fileNameFromArgs:arguments] ];
|
|
}
|
|
else
|
|
{
|
|
// FIXME - check that its ok to make a directory in this position
|
|
|
|
[fs createDirectoryAtPath:p withIntermediateDirectories:YES attributes:nil error:nil];
|
|
cmdStr = [ NSString stringWithFormat:@"250 MKD command successful."];
|
|
|
|
}
|
|
}
|
|
[sender sendMessage:cmdStr];
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doCdUp:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
NSLog(@"CurrentDir is %@",[self visibleCurrentDir]);
|
|
|
|
NSString *upDir=[[self visibleCurrentDir] stringByDeletingLastPathComponent];
|
|
|
|
|
|
|
|
if ( [self changedCurrentDirectoryTo:upDir] ) // checks to see if its ok before moving
|
|
{
|
|
[sender sendMessage:@"250 CDUP command successful."];
|
|
}
|
|
else
|
|
{
|
|
// create message saying you cant go to that directory - FIXME
|
|
[ sender sendMessage:@"550 CDUP command failed." ]; // CHECKME - look at a typical ftp mkdr command failure message
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doRnfr:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
self.rnfrFilename = [self makeFilePathFrom:[self fileNameFromArgs:arguments]];
|
|
|
|
if ( [ self accessibleFilePath:self.rnfrFilename ] ) // FIXME - finish function
|
|
{
|
|
|
|
if ( [[ NSFileManager defaultManager] fileExistsAtPath: rnfrFilename ] )
|
|
{
|
|
[ sender sendMessage:@"350 RNFR command successful." ];
|
|
}
|
|
else
|
|
[ sender sendMessage:@"550 RNFR command failed." ];
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(void)doRnto:(id)sender arguments:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
// FIXME - check its ok to use the new filename - ie in sandbox/basedir
|
|
|
|
if ( self.rnfrFilename == nil ){
|
|
[ sender sendMessage:@"550 RNTO command failed." ];
|
|
return;
|
|
}
|
|
|
|
NSError *error;
|
|
NSString *rntoFilename = [self makeFilePathFrom:[self fileNameFromArgs:arguments]];
|
|
|
|
NSLog( @"%@", rnfrFilename );
|
|
NSLog( @"%@", rntoFilename );
|
|
|
|
if ([self validNewFilePath:rntoFilename]) // FIXME - finish function
|
|
{
|
|
if ( [[ NSFileManager defaultManager] moveItemAtPath:rnfrFilename toPath: rntoFilename error:&error ] ){
|
|
[ server didReceiveFileListChanged];
|
|
[ sender sendMessage:@"250 RNTO command successful." ];
|
|
}
|
|
else{
|
|
NSString *errorString = [error localizedDescription];
|
|
NSLog( @"RNTO failed %@", errorString );
|
|
[ sender sendMessage:@"550 RNTO command failed." ];
|
|
}
|
|
// [rnfrFilename release];
|
|
// rnfrFilename = nil;
|
|
// [rntoFilename release]; // auto released, should be fine to just forget
|
|
|
|
}
|
|
else
|
|
{
|
|
[ sender sendMessage:@"550 RNTO command failed." ]; // CHECKME - have a look at a typical server response for this error
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////
|
|
#pragma mark UTILITIES
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(NSString*)makeFilePathFrom:(NSString*)filename
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
if ( [filename characterAtIndex:0] == '/' ) // if absolute file position
|
|
{
|
|
if ( server.changeRoot ) // then its actually relative to basedir
|
|
{
|
|
return [ [server.baseDir stringByAppendingPathComponent: filename] stringByResolvingSymlinksInPath ];
|
|
}
|
|
else
|
|
{
|
|
return [[filename copy] autorelease ]; // Don't want to hang onto a variable, user should retain if needed.
|
|
}
|
|
|
|
}
|
|
else // add onto the current file postion
|
|
{
|
|
return [ currentDir stringByAppendingPathComponent:filename]; // FIXME / CHECKME - need to set autorelease or retain etc.
|
|
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(unsigned long long)fileSize:(NSString*)filePath
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
|
|
|
|
NSError *error;
|
|
NSDictionary *fileAttribs = [ [ NSFileManager defaultManager ] attributesOfItemAtPath:filePath error:&error ];
|
|
|
|
NSNumber *fileSize = [ fileAttribs valueForKey:NSFileSize ];
|
|
NSLog(@"File size is %qu ", [fileSize unsignedLongLongValue]);
|
|
return [ fileSize unsignedLongLongValue];
|
|
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(NSString*)fileNameFromArgs:(NSArray*)arguments
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
NSString *filename = [NSString string];
|
|
NSLog(@"%@", [arguments description ] );
|
|
if ([arguments count] >1) {
|
|
|
|
|
|
for ( int n=1; n<[arguments count]; n++) { // Start at arg2,
|
|
// test to see if argument begins with a - as it might be just a parameter, not the name
|
|
if (![[[arguments objectAtIndex:n] substringToIndex:1] isEqualToString:@"-"])
|
|
{
|
|
if ([filename length]==0) {
|
|
filename = [arguments objectAtIndex:n ];
|
|
}
|
|
else {
|
|
filename = [ NSString stringWithFormat:@"%@ %@", filename, [arguments objectAtIndex:n ] ]; // autoreleased
|
|
}
|
|
|
|
|
|
}
|
|
else {
|
|
NSLog(@"HYPHEN FOUND IGNORE");
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return filename ; // autoreleased
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
- (Boolean)changedCurrentDirectoryTo:(NSString *)newDirectory // NOTE - there is probably a unix way of expanding pathnames and taking all the ../. stuff out. : should look this up
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
NSFileManager *fileManager = [ NSFileManager defaultManager ];
|
|
|
|
NSString *currentDirectory = [ fileManager currentDirectoryPath ]; // store current directory
|
|
NSString *testDirectory, *expandedPath;
|
|
|
|
|
|
expandedPath = [[self rootedPath:newDirectory ] retain ];
|
|
|
|
// TEST IF ALLOWED TO USE THAT DIRECTORY ( ie is it in allowable filesystem )
|
|
|
|
if (![self canChangeDirectoryTo:expandedPath]) {
|
|
return false;
|
|
}
|
|
|
|
|
|
// CHANGE TO NEW DIRECTORY & GET SYSTEM FILE PATH ( no .. etc )
|
|
if ( ! [ fileManager changeCurrentDirectoryPath:expandedPath ] ) // try changing to new directory
|
|
{
|
|
return false; // Not a valid directory
|
|
}
|
|
|
|
testDirectory = [ fileManager currentDirectoryPath ]; // get new directory as string
|
|
|
|
|
|
// CHANGE BACK
|
|
if ( ! [ fileManager changeCurrentDirectoryPath:currentDirectory ] )// Change back to our own directory
|
|
{
|
|
return false; // Not a valid directory, shouldnt happen, but could u know
|
|
}
|
|
|
|
|
|
|
|
self.currentDir = [ testDirectory copy ]; // make a copy, and retain release
|
|
|
|
[ expandedPath release];
|
|
return true; // its fine. would have failed before if not possible
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(Boolean)canChangeDirectoryTo:(NSString *)testDirectory // NOTE - there is probably a unix way of expanding pathnames and taking all the ../. stuff out. : should look this up
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
if ( [server changeRoot] && ( ! [ testDirectory hasPrefix:server.baseDir ]) ) {
|
|
return false;
|
|
}
|
|
else {
|
|
return true;
|
|
}
|
|
|
|
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
- (Boolean)accessibleFilePath:(NSString*)filePath // checks its a proper name, and also in the chroot sandbox if set
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
// check, file is accessible within servers rights
|
|
// && file exists
|
|
|
|
// FIXME - need to expand the filename reference somehow to check where it really is, whether in sandbox. praps look at tnftpd src code for this.
|
|
|
|
return [ [ NSFileManager defaultManager ] fileExistsAtPath:filePath ];
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
- (Boolean)validNewFilePath:(NSString*)filePath
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
return true; // FIXME - check this is within the area we can write to
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
- (NSString *)visibleCurrentDir
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
|
|
if ( server.changeRoot ) // if root changed, to basedir
|
|
{
|
|
int alength = [server.baseDir length ]; // length of basedir
|
|
|
|
NSLog(@"Length is %u", alength );
|
|
NSString *aString = [ currentDir substringFromIndex:alength ]; // get the bit after basedir
|
|
|
|
if ( ! [ aString hasSuffix:@"/" ] ) // add a / if needed
|
|
{
|
|
aString = [ aString stringByAppendingString:@"/" ];
|
|
}
|
|
|
|
|
|
// return with basedir prefix removed.
|
|
|
|
return aString; // returns just the end part, not the base part
|
|
}
|
|
else
|
|
{
|
|
return currentDir; // return complete path
|
|
}
|
|
|
|
|
|
}
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
-(NSString *)rootedPath:(NSString*)path
|
|
// ----------------------------------------------------------------------------------------------------------
|
|
{
|
|
NSString *expandedPath;
|
|
|
|
// GET FULL PATH OF NEW DIRECTORY
|
|
if ( [ path characterAtIndex:0 ] == '/') // if its an absolute path
|
|
{
|
|
if ( server.changeRoot ) // if rooted, its a relative path really, so add to basedir
|
|
{
|
|
expandedPath = [ [server.baseDir stringByAppendingPathComponent: path] stringByResolvingSymlinksInPath ];
|
|
}
|
|
else // it really is an absolute path
|
|
{
|
|
expandedPath = path; // use the absolute path
|
|
}
|
|
}
|
|
else // or append onto currentdir ( the one the client chose ), as its a relative path
|
|
{
|
|
expandedPath =[[ currentDir stringByAppendingPathComponent:path ] stringByResolvingSymlinksInPath];
|
|
}
|
|
|
|
expandedPath = [ expandedPath stringByStandardizingPath ];
|
|
|
|
return expandedPath; // Autoreleased etc
|
|
|
|
}
|
|
@end
|