Added checks to see if the client is logged in or not and other improvements in order to increase responsiveness
This commit is contained in:
parent
f7fc5abad5
commit
28103022cd
@ -5,7 +5,7 @@
|
||||
#include "SDCardManager.h"
|
||||
#include "definition.h"
|
||||
#include "Dictionary.h"
|
||||
#define DEBUG_FTPS
|
||||
//#define DEBUG_FTPS
|
||||
#define READ_BUFFER_SIZE 2500 //2500 is max to read sd card, more will crash
|
||||
|
||||
template <typename T>
|
||||
@ -13,9 +13,10 @@ class FTPServer : public TCPServer<T>
|
||||
{
|
||||
public:
|
||||
enum FTPClientState {INIT, WAITING_FOR_COMMANDS};
|
||||
enum FTPClientDataTransfer {NONE, LIST_DF, NLST_DF, RETR_DF, STOR_DF};
|
||||
enum FTPClientDataTransfer {NONE = 0, LIST_DF, NLST_DF, RETR_DF, STOR_DF, APPE_DF};
|
||||
enum FileTransferStatus {OK, NOT_FOUND, NO_FILE_NAME};
|
||||
enum BinaryFlag {OFF = 0, ON};
|
||||
enum FtpMsgCode {_150, _200, _215, _220, _221, _230, _226, _227, _250, _257, _331, _350, _451, _5_502, _504, _530, _550 };
|
||||
|
||||
FTPServer(unsigned int port = 21, SDCardManager *sdCardManager = NULL, const char *login = NULL, const char *password = NULL, uint8_t maxClient = MAX_CLIENT, uint16_t clientCommandDataBufferSize = 255) : TCPServer<T>(port, maxClient, clientCommandDataBufferSize),
|
||||
_login(NULL),
|
||||
@ -41,7 +42,6 @@ class FTPServer : public TCPServer<T>
|
||||
strcpy(_password, password);
|
||||
}
|
||||
}
|
||||
|
||||
_dataServer.begin(_dataPort);
|
||||
}
|
||||
|
||||
@ -68,17 +68,20 @@ class FTPServer : public TCPServer<T>
|
||||
client->_clientState = TCPClient::HANDLED;
|
||||
}
|
||||
|
||||
virtual void processClientData(T *client)
|
||||
ICACHE_RAM_ATTR virtual void processClientData(T *client)
|
||||
{
|
||||
if (client->_waitingForDataConnection)
|
||||
/*if (client->_waitingForDataConnection)
|
||||
{
|
||||
//#ifdef DEBUG_FTPS
|
||||
//Serial.println("Listening for new data client");
|
||||
//#endif
|
||||
WiFiClient dataClient = _dataServer.available();
|
||||
|
||||
if (dataClient)
|
||||
if(dataClient)
|
||||
{
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.println("Data client returns true");
|
||||
#endif
|
||||
if (dataClient.connected())
|
||||
{
|
||||
client->_waitingForDataConnection = false;
|
||||
@ -90,72 +93,68 @@ class FTPServer : public TCPServer<T>
|
||||
else
|
||||
dataClient.stop();
|
||||
}
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
switch(client->_dataTransferPending)
|
||||
{
|
||||
case LIST_DF: //We list the files of the current directory
|
||||
//We check if the dataConnection is established:
|
||||
if (client->_dataClient.connected())
|
||||
{
|
||||
client->_client.println("150 File status okay;");
|
||||
if(sendFSTree(client))
|
||||
case LIST_DF:
|
||||
if (client->_dataClient.connected())
|
||||
{
|
||||
client->_client.println("226 Closing data connection.");
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.println("Listing started");
|
||||
#endif
|
||||
|
||||
client->_client.println("150 File status okay.");
|
||||
if(sendFSTree(client))
|
||||
{
|
||||
client->_client.println("226 Closing data connection.");
|
||||
}
|
||||
else
|
||||
{
|
||||
client->_client.println("451 Requested action aborted.");
|
||||
}
|
||||
|
||||
client->closeDataConnection();
|
||||
client->_dataTransferPending = NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
client->_client.println("451 Requested action aborted.");
|
||||
}
|
||||
|
||||
client->_dataClient.stop();
|
||||
client->_dataTransferPending = NONE;
|
||||
}
|
||||
//A timeout should be added
|
||||
/*else
|
||||
{
|
||||
client->_client.println("425 Can't open data connection.");
|
||||
}*/
|
||||
break;
|
||||
case RETR_DF:
|
||||
if (client->_dataClient.connected())
|
||||
{
|
||||
if(client->_fileSentBytes == 0)
|
||||
client->_client.println("150 File status okay;");
|
||||
|
||||
client->_client.println("150 File status okay.");
|
||||
|
||||
FileTransferStatus fts;
|
||||
if(!sendFile(client,&fts))//File was sent or error occured
|
||||
{
|
||||
//we check the return code
|
||||
switch(fts)
|
||||
if(fts == OK)
|
||||
{
|
||||
case OK:
|
||||
client->_client.println("226 Closing data connection.");
|
||||
client->_dataClient.stop();
|
||||
client->_dataTransferPending = NONE;
|
||||
break;
|
||||
case NOT_FOUND:
|
||||
client->_client.println("451 File not found.");
|
||||
client->_dataClient.stop();
|
||||
client->_dataTransferPending = NONE;
|
||||
break;
|
||||
client->_client.println("226 Closing data connection.");
|
||||
client->closeDataConnection();
|
||||
client->_dataTransferPending = NONE;
|
||||
}
|
||||
else if(fts == NOT_FOUND)
|
||||
{
|
||||
client->_client.println("451 File not found.");
|
||||
client->closeDataConnection();
|
||||
client->_dataTransferPending = NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
//A timeout should be added
|
||||
/*else
|
||||
else if(client->_fileSentBytes != 0)
|
||||
{
|
||||
client->_client.println("426 Connection closed; transfer aborted.");
|
||||
client->closeDataConnection();
|
||||
client->_dataTransferPending = NONE;
|
||||
}
|
||||
break;
|
||||
case STOR_DF:
|
||||
if (client->_dataClient.connected() || client->_dataClient.available())//Here we need to check if client has some data available for reading. IMPORTANT
|
||||
{
|
||||
client->_client.println("425 Can't open data connection.");
|
||||
}*/
|
||||
break;
|
||||
case STOR_DF :
|
||||
if (client->_dataClient.connected() || client->_dataClient.available())
|
||||
{
|
||||
if(client->_dataClient.connected())
|
||||
client->_fileIsBeeingReceived = true;
|
||||
|
||||
if(client->_dataClient.available())
|
||||
{
|
||||
client->_fileIsBeeingReceived = true;
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.printf("receiving file %s\n", client->_currentFile);
|
||||
#endif
|
||||
@ -171,18 +170,19 @@ class FTPServer : public TCPServer<T>
|
||||
{
|
||||
client->_client.println("451 Requested action aborted: local error in processing.");
|
||||
}
|
||||
client->_dataClient.stop();
|
||||
client->closeDataConnection();
|
||||
client->_fileIsBeeingReceived = false;
|
||||
client->_dataTransferPending = NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(client->_fileIsBeeingReceived)
|
||||
//If no data connection exists and no error was raised during writting, then it could be just a file creation with no data connection opened
|
||||
else if(client->_fileIsBeeingReceived || (client->_dataClientConnected || millis() - client->_actionTimeout > 5000))
|
||||
{
|
||||
if(client->_fileRecvBytes == 0) //File was just created empty
|
||||
{
|
||||
if(_sdCardManager->exists(client->_currentFile))
|
||||
_sdCardManager->remove(client->_currentFile);
|
||||
_sdCardManager->remove(client->_currentFile);
|
||||
|
||||
File file2create = _sdCardManager->open(client->_currentFile, FILE_WRITE);
|
||||
|
||||
@ -201,13 +201,55 @@ class FTPServer : public TCPServer<T>
|
||||
client->_client.println("226 Closing data connection.");
|
||||
|
||||
client->_fileIsBeeingReceived = false;
|
||||
client->_dataClient.stop();
|
||||
client->closeDataConnection();
|
||||
client->_dataTransferPending = NONE;
|
||||
client->_fileRecvBytes = 0;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case APPE_DF:
|
||||
if (client->_dataClient.connected() || client->_dataClient.available())//Here we need to check if client has some data for reading. IMPORTANT
|
||||
{
|
||||
if(client->_dataClient.available())
|
||||
{
|
||||
client->_fileIsBeeingReceived = true;
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.printf("appending to file %s\n", client->_currentFile);
|
||||
#endif
|
||||
FileTransferStatus fts = OK;
|
||||
|
||||
if(!writeToSdCard(client, &fts, true)) //An error occured
|
||||
{
|
||||
if(fts == NO_FILE_NAME)
|
||||
{
|
||||
client->_client.println("501 No file name given.");
|
||||
}
|
||||
else
|
||||
{
|
||||
client->_client.println("451 Requested action aborted: local error in processing.");
|
||||
}
|
||||
client->closeDataConnection();
|
||||
client->_fileIsBeeingReceived = false;
|
||||
client->_dataTransferPending = NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
//If the connection is closed and data has been received, then we got the whole file
|
||||
else if(client->_fileIsBeeingReceived)
|
||||
{
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.println("Whole file received");
|
||||
#endif
|
||||
|
||||
client->_client.println("226 Closing data connection.");
|
||||
|
||||
client->_fileIsBeeingReceived = false;
|
||||
client->closeDataConnection();
|
||||
client->_dataTransferPending = NONE;
|
||||
client->_fileRecvBytes = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_FTPS
|
||||
if (client->_newDataAvailable)
|
||||
{
|
||||
@ -215,17 +257,17 @@ class FTPServer : public TCPServer<T>
|
||||
}
|
||||
#endif
|
||||
|
||||
if (client->_dataSize > 0)
|
||||
if(client->_dataSize > 0)
|
||||
{
|
||||
switch (client->_ftpClientState)
|
||||
{
|
||||
case WAITING_FOR_COMMANDS:
|
||||
processCommands(client);
|
||||
break;
|
||||
case INIT:
|
||||
client->setCurrentDirectory(FTP_DIR);
|
||||
client->_ftpClientState = WAITING_FOR_COMMANDS;
|
||||
break;
|
||||
case WAITING_FOR_COMMANDS:
|
||||
processCommands(client);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -259,7 +301,7 @@ class FTPServer : public TCPServer<T>
|
||||
client->setUsername(client->_cmdParameters->getAt(0)->getString());
|
||||
}
|
||||
else
|
||||
client->_client.println("530 Username required.");
|
||||
sendInfoResponse(_530, client);//client->_client.println("530 Username required.");
|
||||
}
|
||||
else //The ftp access is open
|
||||
{
|
||||
@ -279,35 +321,47 @@ class FTPServer : public TCPServer<T>
|
||||
}
|
||||
else
|
||||
{
|
||||
client->_client.println("530 Wrong username or password !.");
|
||||
sendInfoResponse(_530, client, "Wrong username or password !");//client->_client.println("530 Wrong username or password !.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
client->_client.println("530 Password required.");
|
||||
sendInfoResponse(_530, client,"");//client->_client.println("530 Password required.");
|
||||
}
|
||||
}
|
||||
else if (strcmp(client->_ftpCommand, "PWD") == 0) //We set the default directory
|
||||
{
|
||||
if(!client->_loggedIn)
|
||||
{
|
||||
sendInfoResponse(_530, client);
|
||||
return;
|
||||
}
|
||||
|
||||
client->_client.printf("257 \"%s\"\r\n", client->_currentDirectory);
|
||||
}
|
||||
else if (strcmp(client->_ftpCommand, "TYPE") == 0)
|
||||
{
|
||||
if(!client->_loggedIn)
|
||||
{
|
||||
sendInfoResponse(_530, client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
{
|
||||
switch (client->_cmdParameters->getAt(0)->getString()[0])
|
||||
{
|
||||
case 'I':
|
||||
client->_binaryFlag = ON;
|
||||
client->_client.println("200 Command okay.");
|
||||
sendInfoResponse(_200, client,"");//client->_client.println("200 Command okay.");
|
||||
break;
|
||||
case 'L':
|
||||
client->_binaryFlag = ON;
|
||||
client->_client.println("200 Command okay.");
|
||||
sendInfoResponse(_200, client,"");//client->_client.println("200 Command okay.");
|
||||
break;
|
||||
case 'A':
|
||||
client->_binaryFlag = OFF;
|
||||
client->_client.println("200 Command okay.");
|
||||
sendInfoResponse(_200, client,"");//client->_client.println("200 Command okay.");
|
||||
break;
|
||||
default:
|
||||
client->_client.println("504 Command not implemented for TYPE.");
|
||||
@ -320,19 +374,80 @@ class FTPServer : public TCPServer<T>
|
||||
}
|
||||
else if (strcmp(client->_ftpCommand, "PASV") == 0)
|
||||
{
|
||||
client->_client.printf("227 Entering Passive Mode (%u,%u,%u,%u,%d,%d).\r\n", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3], _dataPort / 256, _dataPort % 256);
|
||||
client->_waitingForDataConnection = true;
|
||||
if(!client->_loggedIn)
|
||||
{
|
||||
sendInfoResponse(_530, client);
|
||||
return;
|
||||
}
|
||||
|
||||
//We need to test if we are in softAP or STA to chose the right IP
|
||||
uint8_t addr[4] = {0};
|
||||
if(WiFi.status() == WL_CONNECTED)
|
||||
{
|
||||
addr[0] = WiFi.localIP()[0];
|
||||
addr[1] = WiFi.localIP()[1];
|
||||
addr[2] = WiFi.localIP()[2];
|
||||
addr[3] = WiFi.localIP()[3];
|
||||
}else
|
||||
{
|
||||
addr[0] = WiFi.softAPIP()[0];
|
||||
addr[1] = WiFi.softAPIP()[1];
|
||||
addr[2] = WiFi.softAPIP()[2];
|
||||
addr[3] = WiFi.softAPIP()[3];
|
||||
}
|
||||
|
||||
client->_client.printf("227 Entering Passive Mode (%u,%u,%u,%u,%d,%d).\r\n", addr[0], addr[1], addr[2], addr[3], _dataPort / 256, _dataPort % 256);
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.println("Opening data server for new data client");
|
||||
#endif
|
||||
//We listen for 100 ms directly to accept the client
|
||||
uint64_t timeOut(millis());
|
||||
while(true)
|
||||
{
|
||||
WiFiClient dataClient = _dataServer.available();
|
||||
//Serial.printf("Client state : %d\n", dataClient.status());
|
||||
if (dataClient)
|
||||
{
|
||||
//Serial.printf("Data client is true , available : %d\n", dataClient.available());
|
||||
if (dataClient.connected())//Connected returns true if the status() is ESTABLISHED or available() returns true
|
||||
{
|
||||
client->setDataClient(dataClient);
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.println("Data client accepted from loop");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
else
|
||||
dataClient.stop();
|
||||
}
|
||||
|
||||
if(millis() - timeOut > 100)
|
||||
{
|
||||
client->_waitingForDataConnection = true;
|
||||
break;
|
||||
}
|
||||
yield();
|
||||
}
|
||||
}
|
||||
else if (strcmp(client->_ftpCommand, "LIST") == 0)
|
||||
{
|
||||
if(!client->_loggedIn)
|
||||
{
|
||||
sendInfoResponse(_530, client);
|
||||
return;
|
||||
}
|
||||
|
||||
//We inform that a data transfer is pending
|
||||
client->_dataTransferPending = LIST_DF;
|
||||
}
|
||||
else if (strcmp(client->_ftpCommand, "CWD") == 0)
|
||||
{
|
||||
if(!client->_loggedIn)
|
||||
{
|
||||
sendInfoResponse(_530, client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
{
|
||||
//Go back one level
|
||||
@ -389,6 +504,12 @@ class FTPServer : public TCPServer<T>
|
||||
}
|
||||
else if(strcmp(client->_ftpCommand, "RETR") == 0)
|
||||
{
|
||||
if(!client->_loggedIn)
|
||||
{
|
||||
sendInfoResponse(_530, client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
{
|
||||
//We save the file path to be sent
|
||||
@ -408,6 +529,12 @@ class FTPServer : public TCPServer<T>
|
||||
}
|
||||
else if(strcmp(client->_ftpCommand, "MKD") == 0)
|
||||
{
|
||||
if(!client->_loggedIn)
|
||||
{
|
||||
sendInfoResponse(_530, client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
{
|
||||
char *dirNameWithPath = constructFileNameWithPath(client->_currentDirectory, client->_cmdParameters);
|
||||
@ -429,16 +556,22 @@ class FTPServer : public TCPServer<T>
|
||||
}
|
||||
else
|
||||
{
|
||||
client->_client.println("550 Requested action not taken.");
|
||||
sendInfoResponse(_550, client,"");//client->_client.println("550 Requested action not taken.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
client->_client.println("550 Requested action not taken.");
|
||||
sendInfoResponse(_550, client,"");//client->_client.println("550 Requested action not taken.");
|
||||
}
|
||||
}
|
||||
else if(strcmp(client->_ftpCommand, "RMD") == 0)
|
||||
{
|
||||
if(!client->_loggedIn)
|
||||
{
|
||||
sendInfoResponse(_530, client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
{
|
||||
//We have the dir name, we need to append the current directory...
|
||||
@ -454,27 +587,36 @@ class FTPServer : public TCPServer<T>
|
||||
}
|
||||
else
|
||||
{
|
||||
client->_client.println("550 Requested action not taken.");
|
||||
sendInfoResponse(_550, client,"");//client->_client.println("550 Requested action not taken.");
|
||||
}
|
||||
|
||||
free(dirNameWithPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
client->_client.println("550 Requested action not taken.");
|
||||
sendInfoResponse(_550, client,"");//client->_client.println("550 Requested action not taken.");
|
||||
}
|
||||
}
|
||||
else if(strcmp(client->_ftpCommand, "STOR") == 0)
|
||||
{
|
||||
if(!client->_loggedIn)
|
||||
{
|
||||
sendInfoResponse(_530, client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
{
|
||||
client->_client.printf_P(PSTR("150 File status okay; about to open data connection.\r\n"));
|
||||
//We save the file path to be sent
|
||||
char *fileNameWithPath = constructFileNameWithPath(client->_currentDirectory, client->_cmdParameters);
|
||||
char *fileNameWithPath(NULL);
|
||||
|
||||
client->_client.println("150 File status okay; about to open data connection.");
|
||||
if(client->_cmdParameters->getAt(0)->getString()[0] == '/')
|
||||
fileNameWithPath = constructFileNameWithPath("", client->_cmdParameters);
|
||||
else
|
||||
fileNameWithPath = constructFileNameWithPath(client->_currentDirectory, client->_cmdParameters);
|
||||
|
||||
client->setCurrentFile(fileNameWithPath);
|
||||
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.printf("File to store : #%s#\n", client->_currentFile);
|
||||
#endif
|
||||
@ -483,12 +625,39 @@ class FTPServer : public TCPServer<T>
|
||||
client->startTimeout();
|
||||
}
|
||||
}
|
||||
else if(strcmp(client->_ftpCommand, "APPE") == 0)
|
||||
{
|
||||
if(!client->_loggedIn)
|
||||
{
|
||||
sendInfoResponse(_530, client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
{
|
||||
client->_client.printf_P(PSTR("150 File status okay; about to open data connection.\r\n"));
|
||||
//We save the file path to be sent
|
||||
char *fileNameWithPath = constructFileNameWithPath(client->_currentDirectory, client->_cmdParameters);
|
||||
client->setCurrentFile(fileNameWithPath);
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.printf("File to append : #%s#\n", client->_currentFile);
|
||||
#endif
|
||||
free(fileNameWithPath);
|
||||
client->_dataTransferPending = APPE_DF;
|
||||
}
|
||||
}
|
||||
else if(strcmp(client->_ftpCommand, "SYST") == 0)
|
||||
{
|
||||
client->_client.println("215 UNIX Type: L8");
|
||||
}
|
||||
else if(strcmp(client->_ftpCommand, "DELE") == 0)
|
||||
{
|
||||
if(!client->_loggedIn)
|
||||
{
|
||||
sendInfoResponse(_530, client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
{
|
||||
//We have the file name, we need to append the current directory...
|
||||
@ -504,22 +673,33 @@ class FTPServer : public TCPServer<T>
|
||||
}
|
||||
else
|
||||
{
|
||||
client->_client.println("550 Requested action not taken.");
|
||||
sendInfoResponse(_550, client,"");//client->_client.println("550 Requested action not taken.");
|
||||
}
|
||||
|
||||
free(file2deleteNameWithPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
client->_client.println("550 Requested action not taken.");
|
||||
sendInfoResponse(_550, client,"");//client->_client.println("550 Requested action not taken.");
|
||||
}
|
||||
}
|
||||
else if(strcmp(client->_ftpCommand, "RNFR") == 0)
|
||||
{
|
||||
if(!client->_loggedIn)
|
||||
{
|
||||
sendInfoResponse(_530, client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
{
|
||||
//We have the file name, we need to append the current directory...
|
||||
char *fileNameWithPath = constructFileNameWithPath(client->_currentDirectory, client->_cmdParameters);
|
||||
char *fileNameWithPath(NULL);
|
||||
|
||||
if(client->_cmdParameters->getAt(0)->getString()[0] == '/')
|
||||
fileNameWithPath = constructFileNameWithPath("", client->_cmdParameters);
|
||||
else
|
||||
fileNameWithPath = constructFileNameWithPath(client->_currentDirectory, client->_cmdParameters);
|
||||
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.printf("file to rename : #%s#\n",fileNameWithPath);
|
||||
@ -532,15 +712,26 @@ class FTPServer : public TCPServer<T>
|
||||
}
|
||||
else
|
||||
{
|
||||
client->_client.println("550 Requested action not taken.");
|
||||
sendInfoResponse(_550, client,"");//client->_client.println("550 Requested action not taken.");
|
||||
}
|
||||
}
|
||||
else if(strcmp(client->_ftpCommand, "RNTO") == 0)
|
||||
{
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
if(!client->_loggedIn)
|
||||
{
|
||||
sendInfoResponse(_530, client);
|
||||
return;
|
||||
}
|
||||
|
||||
if (client->_cmdParameters->count() > 0) //If the name starts with a /, we do not need to prepend the directory
|
||||
{
|
||||
//Here we rename the file
|
||||
char *file2RenameNameWithPath = constructFileNameWithPath(client->_currentDirectory, client->_cmdParameters);
|
||||
char *file2RenameNameWithPath(NULL);
|
||||
if(client->_cmdParameters->getAt(0)->getString()[0] == '/')
|
||||
file2RenameNameWithPath = constructFileNameWithPath("", client->_cmdParameters);
|
||||
else
|
||||
file2RenameNameWithPath = constructFileNameWithPath(client->_currentDirectory, client->_cmdParameters);
|
||||
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.printf("file to rename to : #%s#\n",file2RenameNameWithPath);
|
||||
Serial.printf("Old name : %s --> %s\n",client->_currentFile,file2RenameNameWithPath);
|
||||
@ -550,21 +741,45 @@ class FTPServer : public TCPServer<T>
|
||||
{
|
||||
client->_client.println("250 Requested file action okay.");
|
||||
}else
|
||||
client->_client.println("550 Requested action not taken.");
|
||||
sendInfoResponse(_550, client,"");//client->_client.println("550 Requested action not taken.");
|
||||
|
||||
free(file2RenameNameWithPath);
|
||||
}
|
||||
}
|
||||
else if(strcmp(client->_ftpCommand, "QUIT") == 0)
|
||||
{
|
||||
if(client->_dataTransferPending == NONE)//If no transfers are in progress
|
||||
{
|
||||
sendInfoResponse(_221, client);
|
||||
|
||||
client->_client.stop();
|
||||
client->_clientState = TCPClient::ClientState::DISCARDED;
|
||||
}
|
||||
else
|
||||
sendInfoResponse(_221, client);
|
||||
}
|
||||
/*else if(strcmp(client->_ftpCommand, "SIZE") == 0)
|
||||
{
|
||||
if (client->_cmdParameters->count() > 0)
|
||||
{
|
||||
client->_client.println("213 15224");
|
||||
}
|
||||
}*/
|
||||
else
|
||||
{
|
||||
client->_client.println("502 Command not implemented.");
|
||||
#ifdef DEBUG_FTPS
|
||||
Serial.println("Command not implemented");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//Here we write the received file to the sd card
|
||||
boolean writeToSdCard(T *client, FileTransferStatus *fts)
|
||||
ICACHE_RAM_ATTR inline boolean writeToSdCard(T *client, FileTransferStatus *fts, boolean append = false)
|
||||
{
|
||||
if (client->_currentFile != NULL)
|
||||
{
|
||||
if(_sdCardManager->exists(client->_currentFile) && client->_fileRecvBytes == 0)
|
||||
if(_sdCardManager->exists(client->_currentFile) && client->_fileRecvBytes == 0 && !append)
|
||||
_sdCardManager->remove(client->_currentFile);
|
||||
|
||||
File fileBeeingReceived = _sdCardManager->open(client->_currentFile, FILE_WRITE);
|
||||
@ -598,7 +813,7 @@ class FTPServer : public TCPServer<T>
|
||||
}
|
||||
|
||||
//Here we send the fs tree to the ftp client
|
||||
boolean sendFSTree(T *client)
|
||||
ICACHE_RAM_ATTR inline boolean sendFSTree(T *client)
|
||||
{
|
||||
if (client->_currentDirectory != NULL)
|
||||
{
|
||||
@ -642,7 +857,7 @@ class FTPServer : public TCPServer<T>
|
||||
}
|
||||
|
||||
//The binary flag needs to be taken into consideration
|
||||
boolean sendFile(T *client, FileTransferStatus *fts)
|
||||
ICACHE_RAM_ATTR inline boolean sendFile(T *client, FileTransferStatus *fts)
|
||||
{
|
||||
if (client->_currentFile != NULL)
|
||||
{
|
||||
@ -690,39 +905,7 @@ class FTPServer : public TCPServer<T>
|
||||
*fts = NOT_FOUND;
|
||||
return false;
|
||||
}
|
||||
|
||||
static char *_83FileNameFormat(char *filename)
|
||||
{
|
||||
char *buffer = (char *)malloc((sizeof(char) * strlen(filename)) + 1);
|
||||
strcpy(buffer, filename);
|
||||
char *delimiter = strchr(buffer, '.');
|
||||
if(delimiter != NULL)
|
||||
{
|
||||
*delimiter = '\0';
|
||||
|
||||
if(strlen(buffer) > 8)
|
||||
buffer[8] = '\0';
|
||||
|
||||
strcpy(filename, buffer);
|
||||
|
||||
if(strlen(delimiter + 1) > 3)
|
||||
*(delimiter + 1 + 3) = '\0';
|
||||
|
||||
strcat(filename, ".");
|
||||
strcat(filename, delimiter + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(strlen(buffer) > 8)
|
||||
{
|
||||
buffer[8] = '\0';
|
||||
}
|
||||
strcpy(filename, buffer);
|
||||
}
|
||||
free(buffer);
|
||||
return filename;
|
||||
}
|
||||
|
||||
//This functions construct the full file path.
|
||||
//ie : if the current directory is : "/somedir/subdir" and the received file name is : "my file .txt"
|
||||
//then it will return : "/somedir/subdir/my file .txt"
|
||||
@ -763,10 +946,30 @@ class FTPServer : public TCPServer<T>
|
||||
return fileNameWithPath;
|
||||
}
|
||||
|
||||
//Error code functions
|
||||
void sendInfoResponse(FtpMsgCode code, T *client, const char *msg = "")
|
||||
{
|
||||
switch(code)
|
||||
{
|
||||
case _200:
|
||||
client->_client.printf_P(PSTR("200 Command okay. %s\r\n"), msg);
|
||||
break;
|
||||
case _221:
|
||||
client->_client.printf_P(PSTR("221 Service closing control connection. %s\r\n"));
|
||||
break;
|
||||
case _530:
|
||||
client->_client.printf_P(PSTR("530 Password required. %s\r\n"), msg);
|
||||
break;
|
||||
case _550:
|
||||
client->_client.printf_P(PSTR("550 Requested action not taken. %s\r\n"), msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char *_login;
|
||||
char *_password;
|
||||
unsigned int _dataPort;
|
||||
|
||||
|
||||
WiFiServer _dataServer; //In passive mode, the FTP server opens two different ports (one for the commands and the other for the data stream)
|
||||
SDCardManager *_sdCardManager;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user