#include "ftp.h" FTP::User::User(Socket::Connection NewConnection, std::map Credentials) { Conn = NewConnection; MyPassivePort = 0; USER = ""; PASS = ""; MODE = MODE_STREAM; STRU = STRU_FILE; TYPE = TYPE_ASCII_NONPRINT; PORT = 20; RNFR = ""; AllCredentials = Credentials; MyDir = Filesystem::Directory("", FTPBasePath); MyDir.SetPermissions("", Filesystem::P_LIST); MyDir.SetPermissions("Unconverted", Filesystem::P_LIST | Filesystem::P_DELE | Filesystem::P_RNFT | Filesystem::P_STOR | Filesystem::P_RETR); MyDir.SetPermissions("Converted", Filesystem::P_LIST | Filesystem::P_DELE | Filesystem::P_RNFT | Filesystem::P_RETR); MyDir.SetPermissions("OnDemand", Filesystem::P_LIST | Filesystem::P_RETR); MyDir.SetPermissions("Live", Filesystem::P_LIST); MyDir.SetVisibility("Converted", Filesystem::S_INACTIVE); MyDir.SetVisibility("OnDemand", Filesystem::S_ACTIVE); } FTP::User::~User() { } int FTP::User::ParseCommand(std::string Command) { Commands ThisCmd = CMD_NOCMD; if (Command.substr(0, 4) == "NOOP") { ThisCmd = CMD_NOOP; Command.erase(0, 5); } if (Command.substr(0, 4) == "USER") { ThisCmd = CMD_USER; Command.erase(0, 5); } if (Command.substr(0, 4) == "PASS") { ThisCmd = CMD_PASS; Command.erase(0, 5); } if (Command.substr(0, 4) == "QUIT") { ThisCmd = CMD_QUIT; Command.erase(0, 5); } if (Command.substr(0, 4) == "PORT") { ThisCmd = CMD_PORT; Command.erase(0, 5); } if (Command.substr(0, 4) == "RETR") { ThisCmd = CMD_RETR; Command.erase(0, 5); } if (Command.substr(0, 4) == "STOR") { ThisCmd = CMD_STOR; Command.erase(0, 5); } if (Command.substr(0, 4) == "TYPE") { ThisCmd = CMD_TYPE; Command.erase(0, 5); } if (Command.substr(0, 4) == "MODE") { ThisCmd = CMD_MODE; Command.erase(0, 5); } if (Command.substr(0, 4) == "STRU") { ThisCmd = CMD_STRU; Command.erase(0, 5); } if (Command.substr(0, 4) == "EPSV") { ThisCmd = CMD_EPSV; Command.erase(0, 5); } if (Command.substr(0, 4) == "PASV") { ThisCmd = CMD_PASV; Command.erase(0, 5); } if (Command.substr(0, 4) == "LIST") { ThisCmd = CMD_LIST; Command.erase(0, 5); } if (Command.substr(0, 4) == "CDUP") { ThisCmd = CMD_CDUP; Command.erase(0, 5); } if (Command.substr(0, 4) == "DELE") { ThisCmd = CMD_DELE; Command.erase(0, 5); } if (Command.substr(0, 4) == "RNFR") { ThisCmd = CMD_RNFR; Command.erase(0, 5); } if (Command.substr(0, 4) == "RNTO") { ThisCmd = CMD_RNTO; Command.erase(0, 5); } if (Command.substr(0, 3) == "PWD") { ThisCmd = CMD_PWD; Command.erase(0, 4); } if (Command.substr(0, 3) == "CWD") { ThisCmd = CMD_CWD; Command.erase(0, 4); } if (Command.substr(0, 3) == "RMD") { ThisCmd = CMD_RMD; Command.erase(0, 4); } if (Command.substr(0, 3) == "MKD") { ThisCmd = CMD_MKD; Command.erase(0, 4); } if (ThisCmd != CMD_RNTO) { RNFR = ""; } switch (ThisCmd) { case CMD_NOOP: { return 200; //Command okay. break; } case CMD_USER: { USER = ""; PASS = ""; if (Command == "") { return 501; } //Syntax error in parameters or arguments. USER = Command; return 331; //User name okay, need password. break; } case CMD_PASS: { if (USER == "") { return 503; } //Bad sequence of commands if (Command == "") { return 501; } //Syntax error in parameters or arguments. PASS = Command; if (!LoggedIn()) { USER = ""; PASS = ""; return 530; //Not logged in. } return 230; break; } case CMD_LIST: { Socket::Connection Connected = Passive.accept(); if (Connected.connected()) { Conn.SendNow("125 Data connection already open; transfer starting.\n"); } else { Conn.SendNow("150 File status okay; about to open data connection.\n"); } while (!Connected.connected()) { Connected = Passive.accept(); } std::string tmpstr = MyDir.LIST(ActiveStreams); Connected.SendNow(tmpstr); Connected.close(); return 226; break; } case CMD_QUIT: { return 221; //Service closing control connection. Logged out if appropriate. break; } case CMD_PORT: { if (!LoggedIn()) { return 530; } //Not logged in. if (Command == "") { return 501; } //Syntax error in parameters or arguments. PORT = atoi(Command.c_str()); return 200; //Command okay. break; } case CMD_EPSV: { if (!LoggedIn()) { return 530; } //Not logged in. MyPassivePort = (rand() % 9999); Passive = Socket::Server(MyPassivePort, "0.0.0.0", true); return 229; break; } case CMD_PASV: { if (!LoggedIn()) { return 530; } //Not logged in. MyPassivePort = (rand() % 9999) + 49152; Passive = Socket::Server(MyPassivePort, "0.0.0.0", true); return 227; break; } case CMD_RETR: { if (!LoggedIn()) { return 530; } //Not logged in. if (Command == "") { return 501; } //Syntax error in parameters or arguments. if (!MyDir.HasPermission(Filesystem::P_RETR)) { return 550; } //Access denied. Socket::Connection Connected = Passive.accept(); if (Connected.connected()) { Conn.SendNow("125 Data connection already open; transfer starting.\n"); } else { Conn.SendNow("150 File status okay; about to open data connection.\n"); } while (!Connected.connected()) { Connected = Passive.accept(); } std::string tmpstr = MyDir.RETR(Command); Connected.SendNow(tmpstr); Connected.close(); return 226; break; } case CMD_STOR: { if (!LoggedIn()) { return 530; } //Not logged in. if (Command == "") { return 501; } //Syntax error in parameters or arguments. if (!MyDir.HasPermission(Filesystem::P_STOR)) { return 550; } //Access denied. Socket::Connection Connected = Passive.accept(); if (Connected.connected()) { Conn.SendNow("125 Data connection already open; transfer starting.\n"); } else { Conn.SendNow("150 File status okay; about to open data connection.\n"); } while (!Connected.connected()) { Connected = Passive.accept(); } std::string Buffer; while (Connected.spool()) { } /// \todo Comment me back in. ^_^ //Buffer = Connected.Received(); MyDir.STOR(Command, Buffer); return 250; break; } case CMD_TYPE: { if (!LoggedIn()) { return 530; } //Not logged in. if (Command == "") { return 501; } //Syntax error in parameters or arguments. if (Command.size() != 1 && Command.size() != 3) { return 501; } //Syntax error in parameters or arguments. switch (Command[0]) { case 'A': { if (Command.size() > 1) { if (Command[1] != ' ') { return 501; } //Syntax error in parameters or arguments. if (Command[2] != 'N') { return 504; } //Command not implemented for that parameter. } TYPE = TYPE_ASCII_NONPRINT; break; } case 'I': { if (Command.size() > 1) { if (Command[1] != ' ') { return 501; } //Syntax error in parameters or arguments. if (Command[2] != 'N') { return 504; } //Command not implemented for that parameter. } TYPE = TYPE_IMAGE_NONPRINT; break; } default: { return 504; //Command not implemented for that parameter. break; } } return 200; //Command okay. break; } case CMD_MODE: { if (!LoggedIn()) { return 530; } //Not logged in. if (Command == "") { return 501; } //Syntax error in parameters or arguments. if (Command.size() != 1) { return 501; } //Syntax error in parameters or arguments. if (Command[0] != 'S') { return 504; } //Command not implemented for that parameter. MODE = MODE_STREAM; return 200; //Command okay. break; } case CMD_STRU: { if (!LoggedIn()) { return 530; } //Not logged in. if (Command == "") { return 501; } //Syntax error in parameters or arguments. if (Command.size() != 1) { return 501; } //Syntax error in parameters or arguments. switch (Command[0]) { case 'F': { STRU = STRU_FILE; break; } case 'R': { STRU = STRU_RECORD; break; } default: { return 504; //Command not implemented for that parameter. break; } } return 200; //Command okay. break; } case CMD_PWD: { if (!LoggedIn()) { return 550; } //Not logged in. if (Command != "") { return 501; } //Syntax error in parameters or arguments. return 2570; //257 -- 0 to indicate PWD over MKD break; } case CMD_CWD: { if (!LoggedIn()) { return 530; } //Not logged in. Filesystem::Directory TmpDir = MyDir; if (TmpDir.CWD(Command)) { if (TmpDir.IsDir()) { MyDir = TmpDir; return 250; } } return 550; break; } case CMD_CDUP: { if (!LoggedIn()) { return 530; } //Not logged in. if (Command != "") { return 501; } //Syntax error in parameters or arguments. Filesystem::Directory TmpDir = MyDir; if (TmpDir.CDUP()) { if (TmpDir.IsDir()) { MyDir = TmpDir; return 250; } } return 550; break; } case CMD_DELE: { if (!LoggedIn()) { return 530; } //Not logged in. if (Command == "") { return 501; } //Syntax error in parameters or arguments. if (!MyDir.DELE(Command)) { return 550; } return 250; break; } case CMD_RMD: { if (!LoggedIn()) { return 530; } //Not logged in. if (Command == "") { return 501; } //Syntax error in parameters or arguments. if (!MyDir.HasPermission(Filesystem::P_RMD)) { return 550; } if (!MyDir.DELE(Command)) { return 550; } return 250; break; } case CMD_MKD: { if (!LoggedIn()) { return 530; } //Not logged in. if (Command == "") { return 501; } //Syntax error in parameters or arguments. if (!MyDir.HasPermission(Filesystem::P_MKD)) { return 550; } if (!MyDir.MKD(Command)) { return 550; } return 2571; break; } case CMD_RNFR: { if (!LoggedIn()) { return 530; } //Not logged in. if (Command == "") { return 501; } //Syntax error in parameters or arguments. RNFR = Command; return 350; //Awaiting further information } case CMD_RNTO: { if (!LoggedIn()) { return 530; } //Not logged in. if (Command == "") { return 501; } //Syntax error in parameters or arguments. if (RNFR == "") { return 503; } //Bad sequence of commands if (!MyDir.Rename(RNFR, Command)) { return 550; } return 250; } default: { return 502; //Command not implemented. break; } } } bool FTP::User::LoggedIn() { if (USER == "" || PASS == "") { return false; } if (!AllCredentials.size()) { return true; } if ((AllCredentials.find(USER) != AllCredentials.end()) && AllCredentials[USER] == PASS) { return true; } return false; } std::string FTP::User::NumToMsg(int MsgNum) { std::string Result; switch (MsgNum) { case 200: { Result = "200 Message okay.\n"; break; } case 221: { Result = "221 Service closing control connection. Logged out if appropriate.\n"; break; } case 226: { Result = "226 Closing data connection.\n"; break; } case 227: { std::stringstream sstr; sstr << "227 Entering passive mode (0,0,0,0,"; sstr << (MyPassivePort >> 8) % 256; sstr << ","; sstr << MyPassivePort % 256; sstr << ").\n"; Result = sstr.str(); break; } case 229: { std::stringstream sstr; sstr << "229 Entering extended passive mode (|||"; sstr << MyPassivePort; sstr << "|).\n"; Result = sstr.str(); break; } case 230: { Result = "230 User logged in, proceed.\n"; break; } case 250: { Result = "250 Requested file action okay, completed.\n"; break; } case 2570: { //PWD Result = "257 \"" + MyDir.PWD() + "\" selected as PWD\n"; break; } case 2571: { //MKD Result = "257 \"" + MyDir.PWD() + "\" created\n"; break; } case 331: { Result = "331 User name okay, need password.\n"; break; } case 350: { Result = "350 Requested file action pending further information\n"; break; } case 501: { Result = "501 Syntax error in parameters or arguments.\n"; break; } case 502: { Result = "502 Command not implemented.\n"; break; } case 503: { Result = "503 Bad sequence of commands.\n"; break; } case 504: { Result = "504 Command not implemented for that parameter.\n"; break; } case 530: { Result = "530 Not logged in.\n"; break; } case 550: { Result = "550 Requested action not taken.\n"; break; } default: { Result = "Error msg not implemented?\n"; break; } } return Result; }