#include "ftp.h" FTP::User::User( Socket::Connection NewConnection, std::map Credentials ) { Conn = NewConnection; 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 ); JSON::Value MyConfig = JSON::fromFile( "/tmp/mist/streamlist" ); fprintf( stderr, "Streamamount: %d\n", MyConfig["streams"].size() ); for( JSON::ObjIter it = MyConfig["streams"].ObjBegin(); it != MyConfig["streams"].ObjEnd(); it++ ) { std::string ThisStream = (*it).second["channel"]["URL"].toString(); ThisStream.erase( ThisStream.begin() ); ThisStream.erase( ThisStream.end() - 1 ); while( ThisStream.find( '/' ) != std::string::npos ) { ThisStream.erase(0,ThisStream.find('/')+1); } ActiveStreams.push_back( ThisStream ); fprintf( stderr, "\t%s\n", ThisStream.c_str() ); } } 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: { std::cout << "Listening on :" << MyPassivePort << "\n"; Socket::Connection Connected = Passive.accept(); if( Connected.connected() ) { Conn.Send( "125 Data connection already open; transfer starting.\n" ); } else { Conn.Send( "150 File status okay; about to open data connection.\n" ); } while( !Connected.connected() ) { Connected = Passive.accept(); } fprintf( stderr, "Sending LIST information\n" ); std::string tmpstr = MyDir.LIST( ActiveStreams ); Connected.Send( 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); std::cout << ":" << MyPassivePort << "\n"; 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; std::cout << ":" << MyPassivePort << "\n"; 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. std::cout << "Listening on :" << MyPassivePort << "\n"; Socket::Connection Connected = Passive.accept(); if( Connected.connected() ) { Conn.Send( "125 Data connection already open; transfer starting.\n" ); } else { Conn.Send( "150 File status okay; about to open data connection.\n" ); } while( !Connected.connected() ) { Connected = Passive.accept(); } fprintf( stderr, "Sending RETR information\n" ); std::string tmpstr = MyDir.RETR( Command ); Connected.Send( 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. std::cout << "Listening on :" << MyPassivePort << "\n"; Socket::Connection Connected = Passive.accept(); if( Connected.connected() ) { Conn.Send( "125 Data connection already open; transfer starting.\n" ); } else { Conn.Send( "150 File status okay; about to open data connection.\n" ); } while( !Connected.connected() ) { Connected = Passive.accept(); } fprintf( stderr, "Reading STOR information\n" ); std::string Buffer; while( Connected.spool() ) { } 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; }