diff --git a/src/app/FTPClient.cpp b/src/app/FTPClient.cpp index 4ff90a0..a7df6e4 100644 --- a/src/app/FTPClient.cpp +++ b/src/app/FTPClient.cpp @@ -8,6 +8,7 @@ _username(NULL), _currentDirectory(NULL), _currentFile(NULL), _fileSentBytes(0), +_fileRecvBytes(0), _waitingForDataConnection(false), _fileIsBeeingReceived(false), _ftpClientState(FTPServer::FTPClientState::INIT), diff --git a/src/app/FTPClient.h b/src/app/FTPClient.h index 38aac89..9385012 100644 --- a/src/app/FTPClient.h +++ b/src/app/FTPClient.h @@ -28,6 +28,7 @@ class FTPClient : public TCPClient char *_currentDirectory; char *_currentFile; uint64_t _fileSentBytes; + uint64_t _fileRecvBytes; boolean _waitingForDataConnection; boolean _fileIsBeeingReceived; diff --git a/src/app/FTPServer.h b/src/app/FTPServer.h index 038bc8a..ceaa440 100644 --- a/src/app/FTPServer.h +++ b/src/app/FTPServer.h @@ -13,7 +13,7 @@ class FTPServer : public TCPServer public: enum FTPClientState {INIT, WAITING_FOR_COMMANDS}; enum FTPClientDataTransfer {NONE, LIST_DF, NLST_DF, RETR_DF, STOR_DF}; - enum FileTransferStatus {OK, NOT_FOUND}; + enum FileTransferStatus {OK, NOT_FOUND, NO_FILE_NAME}; enum BinaryFlag {OFF = 0, ON}; 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(port, maxClient, clientCommandDataBufferSize), @@ -40,6 +40,8 @@ class FTPServer : public TCPServer strcpy(_password, password); } } + + _dataServer.begin(_dataPort); } void setCustomDataPort(unsigned int port) @@ -69,9 +71,9 @@ class FTPServer : public TCPServer { if (client->_waitingForDataConnection) { - /*#ifdef DEBUG_FTPS - Serial.println("Listening for new data client"); - #endif*/ + //#ifdef DEBUG_FTPS + //Serial.println("Listening for new data client"); + //#endif WiFiClient dataClient = _dataServer.available(); if (dataClient) @@ -140,19 +142,32 @@ class FTPServer : public TCPServer }*/ break; case STOR_DF : - if (client->_dataClient.connected()) - { - char recvBuffer[READ_WRITE_BUFFER_SIZE]; + if (client->_dataClient.connected() || client->_dataClient.available()) + { if(client->_dataClient.available()) { - uint16_t size = client->_dataClient.read((uint8_t *)recvBuffer, READ_WRITE_BUFFER_SIZE-1); - recvBuffer[size] = '\0'; - Serial.printf("Data : %s\n", recvBuffer); + #ifdef DEBUG_FTPS + Serial.printf("receiving file %s\n", client->_currentFile); + #endif + FileTransferStatus fts = OK; + + if(!writeToSdCard(client, &fts)) //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->_dataClient.stop(); + client->_fileIsBeeingReceived = false; + client->_dataTransferPending = NONE; + } + else + client->_fileIsBeeingReceived = true; } - - /*client->_dataClient.stop(); - client->_dataTransferPending = NONE;*/ - client->_fileIsBeeingReceived = true; } else if(client->_fileIsBeeingReceived) { @@ -160,9 +175,12 @@ class FTPServer : public TCPServer Serial.println("Whole file received"); #endif + client->_client.println("226 Closing data connection."); + client->_fileIsBeeingReceived = false; client->_dataClient.stop(); client->_dataTransferPending = NONE; + client->_fileRecvBytes = 0; } break; } @@ -278,9 +296,11 @@ class FTPServer : public TCPServer } else if (strcmp(client->_ftpCommand, "PASV") == 0) { - _dataServer.begin(_dataPort); 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; + #ifdef DEBUG_FTPS + Serial.println("Opening data server for new data client"); + #endif } else if (strcmp(client->_ftpCommand, "LIST") == 0) { @@ -457,14 +477,16 @@ class FTPServer : public TCPServer if (client->_cmdParameters->count() > 0) { //We save the file path to be sent - char *temp = (char *)malloc((sizeof(char) * strlen(client->_currentDirectory)) + (sizeof(char) * strlen(client->_cmdParameters->getAt(0)->getString())) + (strcmp(client->_currentDirectory,"/") == 0 ? 0 : 1) + 1); + client->_client.println("150 File status okay; about to open data connection."); + + char *temp = (char *)malloc((sizeof(char) * strlen(client->_currentDirectory)) + (sizeof(char) * strlen(_83FileNameFormat(client->_cmdParameters->getAt(0)->getString()))) + (strcmp(client->_currentDirectory,"/") == 0 ? 0 : 1) + 1); strcpy(temp, client->_currentDirectory); if(strcmp(client->_currentDirectory,"/") != 0 )strcat(temp, "/"); strcat(temp, client->_cmdParameters->getAt(0)->getString()); client->setCurrentFile(temp); #ifdef DEBUG_FTPS - Serial.printf("File to store : %s\n", temp); + Serial.printf("File to store : %s\n", client->_currentFile); #endif free(temp); client->_dataTransferPending = STOR_DF; @@ -474,12 +496,79 @@ class FTPServer : public TCPServer { client->_client.println("215 UNIX Type: L8"); } + else if(strcmp(client->_ftpCommand, "DELE") == 0) + { + if (client->_cmdParameters->count() > 0) + { + //We have the dir name, we need to append the current directory... + uint16_t pathDirNameLength = strlen(client->_cmdParameters->getAt(0)->getString()) + strlen(client->_currentDirectory) + /*If we need to add a /*/ (strcmp(client->_currentDirectory,"/") == 0 ? 0 : 1) + 1; //for \0 + char *pathWithDirName = (char *)malloc(sizeof(char) * pathDirNameLength); + sprintf(pathWithDirName,"%s%s%s",client->_currentDirectory, strcmp(client->_currentDirectory,"/") == 0 ? "" : "/", client->_cmdParameters->getAt(0)->getString()); + + #ifdef DEBUG_FTPS + Serial.printf("file to delete : #%s#\n",pathWithDirName); + #endif + + if(_sdCardManager->remove(pathWithDirName)) + { + client->_client.println("250 Requested file action okay."); + } + else + { + client->_client.println("550 Requested action not taken."); + } + + free(pathWithDirName); + } + else + { + client->_client.println("550 Requested action not taken."); + } + } else client->_client.println("502 Command not implemented."); } + //Here we write the received file to the sd card + boolean writeToSdCard(T *client, FileTransferStatus *fts) + { + if (client->_currentFile != NULL) + { + if(_sdCardManager->exists(client->_currentFile) && client->_fileRecvBytes == 0) + _sdCardManager->remove(client->_currentFile); + + File fileBeeingReceived = _sdCardManager->open(client->_currentFile, FILE_WRITE); + + if(fileBeeingReceived) + { + char recvBuffer[1024]; + + /*fileBeeingReceived.seek(client->_fileRecvBytes);*/ + uint16_t size = client->_dataClient.read((uint8_t *)recvBuffer, 1024); + + fileBeeingReceived.write(recvBuffer, size); + + client->_fileRecvBytes += size; + fileBeeingReceived.close(); + #ifdef DEBUG_FTPS + Serial.println("File beeing written"); + #endif + } + else + { + return false; + } + } + else + { + *fts = NO_FILE_NAME; + return false; + } + return true; + } + //Here we send the fs tree to the ftp client - void sendFSTree(T *client) + boolean sendFSTree(T *client) { if (client->_currentDirectory != NULL) { @@ -513,8 +602,13 @@ class FTPServer : public TCPServer #ifdef DEBUG_FTPS Serial.println("Failed to open directory"); #endif + return false; } + + return true; } + + return false; } //The binary flag needs to be taken into consideration @@ -567,6 +661,38 @@ class FTPServer : public TCPServer return false; } + 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; + } + char *_login; char *_password; unsigned int _dataPort;