www.pudn.com > FTPServerClient.zip > client.cpp


#include  
#include  
#include "client.h" 
using namespace std; 
 
Client::Client(const string& addr, int port) { 
	TcpFactory factory; 
	factory.setDest(addr, port); 
	pi = factory.connect(); 
 
	string text; 
	int reply = getReply(text); 
 
	if(reply==120) 
		reply = getReply(text); 
 
	if(reply!=220) throw "Connect to server failed"; 
 
	passive = false; 
	dataType = Tcp::ASCII; 
} 
 
Client::~Client() { 
	delete pi; 
} 
 
int Client::user(const string& username) { 
	string text = "USER " + username; 
	pi->write(text); 
	cout << "\t[C] " << text << endl; 
 
	return getReply(text); 
} 
 
int Client::pass(const string& password) { 
	string text = "PASS " + password; 
	pi->write(text); 
	cout << "\t[C] PASS (hidden)" << endl; 
 
	return getReply(text); 
} 
 
int Client::cwd(const string& path) { 
	string text = "CWD " + path; 
	pi->write(text); 
	cout << "\t[C] " << text << endl; 
 
	return getReply(text); 
} 
 
int Client::cdup() { 
	pi->write("CDUP"); 
	cout << "\t[C] CDUP" << endl; 
 
	string text; 
	return getReply(text); 
} 
 
int Client::quit() { 
	pi->write("QUIT"); 
	cout << "\t[C] QUIT" << endl; 
 
	string text; 
	return getReply(text); 
} 
 
int Client::port(int port) { 
	int addr = pi->getLocalAddr(); 
	stringstream ss; 
	ss << "PORT " << (addr>>24) << ',' << ((addr>>16)&0xff) << ','; 
	ss << ((addr>>8)&0xff) << ',' << (addr&0xff) << ','; 
	ss << ((port>>8)&0xff) << ',' << (port&0xff); 
	pi->write(ss.str()); 
	cout << "\t[C] " << ss.str() << endl; 
 
	string text; 
	int reply = getReply(text); 
 
	if(reply==200) { 
		dtp.setLocalPort(port); 
		passive = false; 
	} 
 
	return reply; 
} 
 
int Client::pasv() { 
	pi->write("PASV"); 
	cout << "\t[C] PASV" << endl; 
 
	string text; 
	int reply = getReply(text); 
 
	if(reply==227) { 
		int addr = 0; 
		int port; 
		int i = 27; 
		for(int j=0; j<5; j++) { 
			int comma = text.find(',', i); 
			if(j<4) 
				addr = (addr<<8)+atoi(text.substr(i, comma-i).c_str()); 
			else 
				port = atoi(text.substr(i, comma-i).c_str()); 
			i = comma+1; 
		} 
		port = (port<<8)+atoi(text.substr(i).c_str()); 
 
		passive = true; 
		dtp.setDest(addr, port); 
		data = dtp.connect(); 
	} 
 
	return reply; 
} 
 
int Client::type(Tcp::DataType type) { 
	string text = "TYPE "; 
	switch(type) { 
	case Tcp::ASCII: 
		text += 'A'; 
		break; 
	case Tcp::IMAGE: 
		text += 'I'; 
		break; 
	default: 
		throw "Unsupported data type"; 
	} 
 
	pi->write(text); 
	cout << "\t[C] " << text << endl; 
 
	int reply = getReply(text); 
 
	if(reply==200) 
		dataType = type; 
 
	return reply; 
} 
 
int Client::stor(const string& filename) { 
	ifstream is(filename.c_str(), dataType==Tcp::ASCII?ios::in:ios::binary); 
	if(!is) throw "File not exist"; 
 
	string text = "STOR " + filename; 
	pi->write(text); 
	cout << "\t[C] " << text << endl; 
 
	openDataConnection(); 
	int reply = getReply(text); 
 
	if(reply==125 || reply==150) { 
		data->setDataType(dataType); 
		data->writeFromStream(is); 
	} 
 
	delete data; 
	if(reply==125 || reply==150) reply = getReply(text); 
 
	return reply; 
} 
 
int Client::retr(const string& filename) { 
	string text = "RETR " + filename; 
	pi->write(text); 
	cout << "\t[C] " << text << endl; 
 
	openDataConnection(); 
	int reply = getReply(text); 
 
	if(reply==125 || reply==150) { 
		ofstream os(filename.c_str(), dataType==Tcp::ASCII?ios::out:ios::binary); 
		data->setDataType(dataType); 
		data->readToStream(os); 
	} 
 
	delete data; 
	if(reply==125 || reply==150) reply = getReply(text); 
 
	return reply; 
} 
 
int Client::appe(const string& filename) { 
	ifstream is(filename.c_str(), dataType==Tcp::ASCII?ios::in:ios::binary); 
	if(!is) throw "File not exist"; 
 
	string text = "APPE " + filename; 
	pi->write(text); 
	cout << "\t[C] " << text << endl; 
 
	openDataConnection(); 
	int reply = getReply(text); 
 
	if(reply==125 || reply==150) { 
		data->setDataType(dataType); 
		data->writeFromStream(is); 
	} 
 
	delete data; 
	if(reply==125 || reply==150) reply = getReply(text); 
 
	return reply; 
} 
 
int Client::list(const string& path) { 
	string text = path.length() ? "LIST " + path : "LIST"; 
	pi->write(text); 
	cout << "\t[C] " << text << endl; 
 
	openDataConnection(); 
	int reply = getReply(text); 
 
	if(reply==125 || reply==150) data->readToStream(cout); 
 
	delete data; 
	if(reply==125 || reply==150) reply = getReply(text); 
 
	return reply; 
} 
 
int Client::pwd(Directory& dir) { 
	pi->write("PWD"); 
	cout << "\t[C] PWD" << endl; 
 
	string text; 
	int reply = getReply(text); 
 
	if(reply==257) 
		dir.cd(text.substr(5, text.find('"', 5)-5)); 
 
	return reply; 
} 
 
int Client::abor() { 
	pi->write("ABOR"); 
	cout << "\t[C] ABOR" << endl; 
 
	string text; 
	return getReply(text); 
} 
 
int Client::syst() { 
	pi->write("SYST"); 
	cout << "\t[C] SYST" << endl; 
 
	string text; 
	return getReply(text); 
} 
 
int Client::help(const string& command) { 
	string text = command.length() ? "HELP " + command : "HELP"; 
	pi->write(text); 
	cout << "\t[C] " << text << endl; 
 
	return getReply(text); 
} 
 
bool Client::connect(Client* host) { 
	pi->write("PASV"); 
	cout << "\t[C] PASV" << endl; 
 
	string text; 
	if(getReply(text)!=227) return false; 
 
	text.replace(0, 27, "PORT "); 
	text.resize(text.find(')')); 
	host->pi->write(text); 
	cout << "\t[C] " << text << endl; 
 
	return host->getReply(text)==200; 
} 
 
bool Client::transfer(Client* host, const string& filename) { 
	string text = "RETR " + filename; 
	host->pi->write(text); 
	cout << "\t[C] " << text << endl; 
 
	int reply = host->getReply(text); 
	if(reply!=125 && reply!=150) return false; 
 
	text = "STOR " + filename.substr(filename.rfind('/')+1); 
	pi->write(text); 
	cout << "\t[C] " << text << endl; 
 
	reply = getReply(text); 
	if(reply!=125 && reply!=150) return false; 
 
	host->getReply(text); 
	getReply(text); 
	return true; 
} 
 
int Client::getReply(string& reply) { 
	reply = pi->read() + '\n'; 
	string num = reply.substr(0, 3) + ' '; 
 
	if(reply[3]=='-') { 
		string temp; 
		do { 
			temp = pi->read(); 
			reply += "\t[R] " + temp + '\n'; 
		} while(temp.substr(0, 4)!=num); 
	} 
 
	cout << "\t[R] " << reply; 
	return atoi(num.c_str()); 
} 
 
void Client::openDataConnection() { 
	if(passive) 
		passive = false; 
	else 
		data = dtp.listen(); 
}