www.pudn.com > FTPServerClient.zip > server.cpp
#include#include #include #include "server.h" using namespace std; const string Server::FTP_ROOT = "."; TcpFactory* Server::listenTcp = new Tcpfactory; map Server::users; Server::Server(Tcp* ctrl) { pi = ctrl; logon = false; passive = false; dataType = Tcp::ASCII; } Server::~Server() { delete pi; delete data; } Server* Server::listen(int port) { listenTcp->setLocalPort(port); return new Server(listenTcp->listen()); } void Server::addUser(const string& username, const string& password) { users.insert(make_pair(username, password)); } void Server::start() { delete listenTcp; pi->write("220 FTP Server ready."); while(true) { string command = pi->read(); try { if(command.substr(0, 5)=="USER ") { map ::iterator user = users.find(command.substr(5)); if(user==users.end()) { pi->write("530 Not logged in."); logon = false; continue; } if(user->second.length()) { pi->write("331 User name okay, need password."); if(pi->read()!="PASS "+user->second) { pi->write("530 Not logged in."); logon = false; continue; } } pi->write("230 User logged in, proceed."); logon = true; } else if(command.substr(0, 4)=="CWD ") { if(checkPermission()) if(access(dir.buildFullname(FTP_ROOT, command.substr(4)).c_str(), X_OK)) pi->write("550 No such file or directory."); else { dir.cd(command.substr(4)); pi->write("250 CWD command successful."); } } else if(command=="CDUP") { if(checkPermission()) { dir.cd(".."); pi->write("200 CDUP command successful."); } } else if(command=="QUIT") { pi->write("221 Goodbye."); logon = false; return; } else if(command.substr(0, 5)=="PORT ") { if(checkPermission()) { int addr = 0; int port; int i = 5; for(int j=0; j<5; j++) { int comma = command.find(',', i); if(j<4) addr = (addr<<8)+atoi(command.substr(i, comma-i).c_str()); else port = atoi(command.substr(i, comma-i).c_str()); i = comma+1; } port = (port<<8)+atoi(command.substr(i).c_str()); dtp.setDest(addr, port); passive = false; pi->write("200 PORT command successful."); } } else if(command=="PASV") { if(checkPermission()) { int addr = pi->getLocalAddr(); int port = rand(); stringstream ss; ss << "227 Entering Passive Mode (" << (addr>>24) << ','; ss << ((addr>>16)&0xff) << ',' << ((addr>>8)&0xff) << ','; ss << (addr&0xff) << ',' << ((port>>8)&0xff) << ','; ss << (port&0xff) << ")."; pi->write(ss.str()); passive = true; dtp.setLocalPort(port); data = dtp.listen(); } } else if(command.substr(0, 5)=="TYPE ") { if(checkPermission()) { switch(command[5]) { case 'A': dataType = Tcp::ASCII; break; case 'I': dataType = Tcp::IMAGE; break; default: pi->write("504 Command not implemented for that parameter."); continue; } pi->write(string("200 Type set to ") + command[5] + "."); } } else if(command.substr(0, 5)=="STOR " || command.substr(0, 5)=="APPE ") { if(checkPermission()) { string filename = dir.buildFullname(FTP_ROOT, command.substr(5)); ofstream os(filename.c_str(), command[0]=='S' ? (dataType==Tcp::ASCII ? ios::out : ios::binary) : (dataType==Tcp::ASCII ? ios::app : ios::app|ios::binary)); if(!os) { pi->write("553 Requested action not taken."); continue; } pi->write(string("150 Opening ") + (dataType==Tcp::ASCII ? "ASCII" : "Binary") + " mode data connection for " + command.substr(5) + "."); openDataConnection(); data->setDataType(dataType); data->readToStream(os); delete data; pi->write("226 Transfer complete."); } } else if(command.substr(0, 5)=="RETR " || command.substr(0, 4)=="LIST") { if(checkPermission()) { string filename; if(command[0]=='L') if(command.length()==4) { char tmp[] = "/tmp/ftpd.XXXXXX"; mkstemp(tmp); filename = tmp; system(string("ls -l " + dir.buildFullname(FTP_ROOT, "") + " > " + filename).c_str()); } else if(command.length()>5 && command[4]==' ') { char tmp[] = "/tmp/ftpd.XXXXXX"; mkstemp(tmp); filename = tmp; system(string("ls -l " + dir.buildFullname(FTP_ROOT, command[5]=='-' ? " "+command.substr(5) : command.substr(5)) + " > " + filename).c_str()); } else { pi->write("502 Command not implemented."); continue; } else filename = dir.buildFullname(FTP_ROOT, command.substr(5)); ifstream is(filename.c_str(), dataType==Tcp::ASCII?ios::in:ios::binary); if(!is) { pi->write("550 No such file or directory."); continue; } pi->write(string("150 Opening ") + (dataType==Tcp::ASCII ? "ASCII" : "Binary") + " mode data connection for " + (command[0]=='L' ? "file list" : command.substr(5)) + "."); openDataConnection(); if(command[0]!='L') data->setDataType(dataType); data->writeFromStream(is); delete data; pi->write("226 Transfer complete."); if(command[0]=='L') remove(filename.c_str()); } } else if(command=="PWD") { pi->write("257 \"" + string(dir) + "\" is current directory."); } else if(command=="ABOR") { pi->write("226 Closing data connection."); } else if(command=="SYST") { pi->write("215 UNIX Type: L8"); } else if(command.substr(0, 4)=="HELP") { if(command.length()==4) { pi->write("214-The following commands are recognized:"); pi->write(" CWD CDUP QUIT PORT PASV PWD SYST HELP"); pi->write(" NOOP TYPE MODE RETR STOR APPE ABOR USER"); pi->write(" PASS LIST"); pi->write("214 FTP daemon implemented by Meng Xiangliang"); } else if(command.length()>5 && command[4]==' ') pi->write("214 Help message."); else pi->write("502 Command not implemented."); } else if(command.substr(0, 5)=="MODE ") { pi->write("504 Command not implemented for that parameter."); } else if(command=="NOOP") { pi->write("200 Command okay."); } else pi->write("502 Command not implemented."); } catch(const char* message) { cerr << "ERROR: " << message << endl; } } } bool Server::checkPermission() { if(logon) return true; else { pi->write("530 Not logged in."); return false; } } void Server::openDataConnection() { if(passive) passive = false; else data = dtp.connect(); } int main(int argc, char* argv[]) { Server::addUser("anonymous", ""); Server::addUser("mxl", "mxl"); while(true) { Server* server = Server::listen(argc>1 ? atoi(argv[1]) : 2382); if(fork()>0) { server->start(); delete server; return 0; } else delete server; } }