I've the following C++ code that is a FTP class test.
Code:
#if defined(_WIN32)
#include <windows.h>
#include <winsock.h>
#define socket_receive(Socket,buffer,len, flags) recv(Socket, (char*)buffer, len , flags)
#define socket_send(Socket,buffer,len, flags) send(Socket, (char*)buffer, len , flags)
#define socket_close closesocket
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#define socket_receive(Socket,buffer,len, flags) recv(Socket, (char*)buffer, len , flags)
#define socket_send(Socket,buffer,len, flags) send(Socket, (char*)buffer, len , flags)
#define socket_close close
#endif
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
using namespace std;
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
using namespace boost;
class FTPUploader
{
public:
string Host, Username, Password, Path;
bool Logined, Initialized;
SOCKET wSOCKET;
int bytes, retValue;
string mes, reply;
const static int BLOCK_SIZE = 512;
char buffer[BLOCK_SIZE];
public:
FTPUploader(string _Host, string _Username, string _Password, string _Path)
{
this->Host = _Host;
this->Username = _Username;
this->Password = _Password;
this->Path = _Path;
this->Initialized = false;
this->Logined = false;
}
/* methods for gettings and setting properties */
public:
void set_Host(string _Host)
{
this->Host = _Host;
}
string get_Host(void)
{
return this->Host;
}
void set_Username(string _Username)
{
this->Username = _Username;
}
string get_Username(void)
{
return this->Username;
}
void set_Password(string _Password)
{
this->Password = _Password;
}
string get_Password(void)
{
return this->Password;
}
void set_Path(string _Path)
{
this->Path = _Path;
}
string get_Path(void)
{
return this->Path;
}
/* Connection handlig methods */
private:
bool Initialize(void)
{
if(this->Initialized)
return true;
#if defined(_WIN32)
WSADATA wsa;
if(WSAStartup(MAKEWORD(1, 1), &wsa))
{
WSACleanup();
return false;
}
#endif
this->Initialized = true;
return true;
}
public:
bool Login(void)
{
if(this->Logined)
return true;
if(!this->Initialized)
this->Initialize();
this->wSOCKET = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if( this->wSOCKET == INVALID_SOCKET )
{
#if defined (_WIN32)
WSACleanup();
#endif
return false;
}
hostent *he;
if( (he = gethostbyname( this->Host.c_str() )) == NULL )
return false;
sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr( inet_ntoa( (**(in_addr**)he->h_addr_list ) ) );
clientService.sin_port = htons( 21 );
if( connect( this->wSOCKET, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR )
{
WSACleanup();
return false;
}
this->readReply();
if(this->retValue != 220)
{
this->Close();
return false;
}
this->sendCommand("USER " + this->Username);
if( !(this->retValue == 331 || this->retValue == 230) )
{
this->Cleanup();
return false;
}
if(this->retValue != 230)
{
this->sendCommand("PASS " + this->Password);
if( !(this->retValue == 230 || this->retValue == 202) )
{
this->Cleanup();
return false;
}
}
this->Logined = true;
this->changeDirectory(this->Path);
return true;
}
void Close(void)
{
if( this->wSOCKET != 0 )
{
this->sendCommand("QUIT");
}
this->Cleanup();
#if defined(_WIN32)
WSACleanup();
#endif
}
void Cleanup(void)
{
if(this->wSOCKET != 0)
{
socket_close(this->wSOCKET);
this->wSOCKET = 0;
}
this->Initialized = false;
this->Logined = false;
}
/* End Connection handler methods */
public:
long getFileSize(string fileName)
{
if(!this->Logined)
this->Login();
this->sendCommand("SIZE " + fileName);
long size = 0;
if(this->retValue == 213)
{
size = atol(this->reply.substr(4).c_str());
}
else return 0;
return size;
}
public:
bool setBinaryMode(bool _mode)
{
if(_mode)
this->sendCommand("TYPE I");
else
this->sendCommand("TYPE A");
if(this->retValue != 200)
return false;
return true;
}
bool changeDirectory(string _Path)
{
if(_Path == ".")
return false;
if(!this->Logined)
this->Login();
this->sendCommand("CWD " + _Path);
if(this->retValue != 250)
return false;
this->Path = _Path;
return true;
}
bool makeDirectory(string _DirName)
{
if(!this->Logined)
this->Login();
this->sendCommand("MKD " + _DirName);
if(this->retValue != 250)
return false;
return true;
}
public:
bool upload(string fileName)
{
return this->upload(fileName,false);
}
public:
bool upload(string fileName,bool resume)
{
if(!this->Logined)
this->Login();
SOCKET cSocket = this->createDataSocket();
long offset = 0;
if(resume)
{
try
{
this->setBinaryMode(true);
offset = this->getFileSize(fileName);
}
catch(bool)
{
offset = 0;
}
}
if(offset > 0)
{
this->sendCommand("REST " + offset);
if(this->retValue != 350)
offset = 0;
}
this->sendCommand("STOR " + fileName);
if( !(this->retValue == 125 || this->retValue == 150) )
return false;
/* SECTION = get and send the file */
ifstream input;
input.open( fileName.c_str() , ios::binary );
// get length of file:
int length;
input.seekg (0, ios::end);
length = input.tellg();
input.seekg (0, ios::beg);
// allocate memory:
char *filebuf;
filebuf = new char [length];
// read data as a block:
input.read(filebuf,length);
input.close();
socket_send(cSocket,filebuf, length ,0);
/* end SECTION */
if(getpeername(cSocket,0,0))
socket_close(cSocket);
this->readReply();
if( !(this->retValue == 226 || this->retValue == 250) )
{
return false;
}
return true;
}
/* Actor Helpers */
void readReply(void)
{
this->mes = "";
this->reply = this->readLine();
this->retValue = lexical_cast<int>( this->reply.substr(0,3) );
}
string readLine(void)
{
while(true)
{
this->bytes = socket_receive(this->wSOCKET,this->buffer, BLOCK_SIZE ,0);
cout << "bytes recived : " << this->bytes << endl;
cout << "strlen buffer : " <<(int)strlen(this->buffer) << endl;
cout << "Buffer :\n" << this->buffer << endl;
this->mes += this->buffer;
cout << "Buffer2 :\n" << this->mes << endl;
this->mes = this->mes.substr(0,this->bytes);
cout << "Buffer3 :\n" << this->mes << endl;
if(this->bytes < (int)strlen(this->buffer) )
break;
}
vector<string> mess;
split(mess,this->mes,is_any_of("\n"));
if(this->mes.length() > 2)
{
this->mes = mess[mess.size() - 2];
}
else
{
this->mes = mess[0];
}
if(!(this->mes.substr(3,1) == " "))
{
return this->readLine();
}
return this->mes;
}
private:
void sendCommand(string command)
{
command += "\r\n";
const char *cmdBytes = command.c_str();
socket_send(this->wSOCKET,cmdBytes, (int)strlen(cmdBytes),0);
this->readReply();
}
private:
SOCKET createDataSocket(void)
{
this->sendCommand("PASV");
if(this->retValue != 227)
return NULL;
int index1 = (int)( this->reply.find_first_of('(', 0) );
int index2 = (int)( this->reply.find_first_of(')', 0) );
string ipData = this->reply.substr(index1 + 1,index2 - index1 - 1);
int parts[6];
int len = (int)ipData.length();
int partCount = 0;
string buf = "";
for(int i = 0; i < len && partCount <= 6; i++)
{
string ch = ipData.substr(i,1);
if( isdigit( lexical_cast<char>(ch) ) ) buf += ch;
else if(ch != ",")
{
return NULL;
}
if(ch == "," || i + 1 == len)
{
try
{
parts[partCount++] = lexical_cast<int>(buf);
buf = "";
}
catch(bad_lexical_cast &)
{
return NULL;
}
}
}
string ipAddress = lexical_cast<string>( parts[0] ) + "." + lexical_cast<string>( parts[1] ) + "." + lexical_cast<string>( parts[2] ) + "." + lexical_cast<string>( parts[3] );
int port = (parts[4] << 8) + parts[5];
SOCKET s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if( s == INVALID_SOCKET )
return NULL;
sockaddr_in clientService;
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr( ipAddress.c_str() );
clientService.sin_port = htons( port );
if( connect( s, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR )
return NULL;
return s;
}
/* End Actor helpers */
};
int main()
{
FTPUploader ftp("ftp.magicasoft.net","usr","pass",".");
ftp.Login();
ftp.changeDirectory("httpdocs");
cin.get();
return 0;
}
it gives the output:
Code:
bytes recived : 59
strlen buffer : 519
Buffer :
220 ProFTPD 1.2.9 Server (ProFTPD) [galapagos.globat.com]
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠░ ↕
Buffer2 :
220 ProFTPD 1.2.9 Server (ProFTPD) [galapagos.globat.com]
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠░ ↕
Buffer3 :
220 ProFTPD 1.2.9 Server (ProFTPD) [galapagos.globat.com]
bytes recived : 35
strlen buffer : 519
Buffer :
331 Password required for mazdak.
[galapagos.globat.com]
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠░ ↕
Buffer2 :
331 Password required for mazdak.
[galapagos.globat.com]
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠░ ↕
Buffer3 :
331 Password required for mazdak.
bytes recived : 28
strlen buffer : 519
Buffer :
230 User mazdak logged in.
zdak.
[galapagos.globat.com]
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠░ ↕
Buffer2 :
230 User mazdak logged in.
zdak.
[galapagos.globat.com]
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠░ ↕
Buffer3 :
230 User mazdak logged in.
bytes recived : 29
strlen buffer : 519
Buffer :
250 CWD command successful.
dak.
[galapagos.globat.com]
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠░ ↕
Buffer2 :
250 CWD command successful.
dak.
[galapagos.globat.com]
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠░ ↕
Buffer3 :
250 CWD command successful.
I've tried to port it so that it uses a socket class I've made.
socket.hpp:
Code:
#if defined(_WIN32)
#include <windows.h>
#include <winsock.h>
#define socket_connect ::connect
#define socket_close ::closesocket
#define socket_ioctl ::ioctlsocket
#define socket_recive(Socket,buffer,len, flags) recv(Socket, (char*)buffer, len , flags)
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/ioctl>
typedef SOCKET int
#define INVALID_SOCKET -1
#define socket_close ::close
#define socket_ioctl ::ioctl
#define socket_connect(SOCKET s, sockaddr_in* name, namelen) ::connect(s, (const sockaddr*) name, sizeof(sockaddr) )
#endif
#include <string>
class Socket
{
public:
SOCKET m_socket;
bool m_isOpen;
private:
void setSocket(SOCKET s)
{
this->m_socket = s;
}
SOCKET getSocket(void)
{
return this->m_socket;
}
void setIsOpen(bool bVal)
{
this->m_isOpen = bVal;
}
public:
bool isOpen(void)
{
return this->m_isOpen;
}
Socket(void)
{
this->setIsOpen(false);
}
virtual ~Socket(void)
{
this->close();
}
bool open(int af, int type, int protocol)
{
if(this->isOpen())
return true;
SOCKET tempSocket = ::socket(af, type, protocol);
if(tempSocket == INVALID_SOCKET)
return false;
else
{
this->setIsOpen(true);
this->setSocket(tempSocket);
return true;
}
}
bool open(SOCKET tempSocket)
{
if(this->isOpen())
return true;
if(tempSocket == INVALID_SOCKET)
return false;
else
{
this->setIsOpen(true);
this->setSocket(tempSocket);
return true;
}
}
bool close(void)
{
this->shutdown(0x02);
if( socket_close(this->getSocket()) == 0 ? true : false )
{
this->setSocket(0);
this->setIsOpen(false);
return true;
}
else return false;
}
bool bind(const sockaddr* name, int namelen)
{
return ::bind(this->getSocket(), name, namelen) == 0 ? true : false;
}
bool connect(const sockaddr* name, int namelen)
{
return socket_connect(this->getSocket(), name, namelen) == 0 ? true : false;
}
bool connect(const char* host, int port, int af)
{
hostent* he;
if( (he = ::gethostbyname(host)) == 0 )
return false;
sockaddr_in clientService;
clientService.sin_family = af;
clientService.sin_addr.s_addr = ::inet_addr( ::inet_ntoa( (**(in_addr**)he->h_addr_list ) ) );
clientService.sin_port = htons(port);
return socket_connect(this->getSocket(), (SOCKADDR*) &clientService, sizeof(clientService) ) == 0 ? true : false;
}
bool connect(std::string host, int port, int af)
{
return this->connect(host.c_str(), port, af);
}
bool shutdown(int how)
{
return ::shutdown(this->getSocket(), how) == 0 ? true : false;
}
int receive(char* buffer, int length, int flags)
{
return ::socket_recive(this->getSocket(), (char*)buffer, length, flags);
}
int send(char* buffer, int length, int flags)
{
return ::send(this->getSocket(), (char*)buffer, length, flags);
}
int send(std::string buffer, int length, int flags)
{
char* cBuffer = (char*)buffer.c_str();
return ::send(this->getSocket(), cBuffer, length, flags);
}
bool listen(int backlog)
{
return ::listen(this->getSocket(), backlog) == 0 ? true : false;
}
Socket* accept(sockaddr* addr, int* addrlen)
{
Socket* tempSocket = new Socket();
tempSocket->open( ::accept(this->getSocket(), addr, addrlen) );
return tempSocket;
}
bool getPeerName(sockaddr* name, int* namelen)
{
return ::getpeername(this->getSocket(), name, namelen) == 0 ? true : false;
}
bool getName(sockaddr* name, int* namelen)
{
return ::getsockname(this->getSocket(), name, namelen) == 0 ? true : false;
}
bool getOption(int level, int optionName, char* optionValue)
{
return ::getsockopt(this->getSocket(), level, optionName, optionValue, (int*)::strlen(optionValue) ) == 0 ? true : false;
}
bool setOption(int level, int optionName, const char* optionValue)
{
return ::setsockopt(this->getSocket(), level, optionName, optionValue, (int)::strlen(optionValue) ) == 0 ? true : false;
}
bool ioctl(long cmd, unsigned long* argp)
{
socket_ioctl(this->getSocket(), cmd, argp);
}
};
main.cpp:
Code:
#include <string>
#include <vector>
#include <fstream>
#include <iostream>
using namespace std;
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
using namespace boost;
#include "Socket.hpp"
class FTPUploader
{
public:
string Host, Username, Password, Path;
bool Logined, Initialized;
Socket* socket;
int bytes, retValue;
string mes, reply;
const static int BLOCK_SIZE = 512;
char buffer[BLOCK_SIZE];
/* methods for gettings and setting properties */
public:
void set_Host(string _Host)
{
this->Host = _Host;
}
string get_Host(void)
{
return this->Host;
}
void set_Username(string _Username)
{
this->Username = _Username;
}
string get_Username(void)
{
return this->Username;
}
void set_Password(string _Password)
{
this->Password = _Password;
}
string get_Password(void)
{
return this->Password;
}
void set_Path(string _Path)
{
this->Path = _Path;
}
string get_Path(void)
{
return this->Path;
}
public:
FTPUploader(string _Host, string _Username, string _Password, string _Path)
{
this->socket = new Socket();
this->Host = _Host;
this->Username = _Username;
this->Password = _Password;
this->Path = _Path;
this->Initialized = false;
this->Logined = false;
}
/* Connection handlig methods */
private:
bool Initialize(void)
{
if(this->Initialized)
return true;
#if defined(_WIN32)
WSADATA wsa;
if(WSAStartup(MAKEWORD(1, 1), &wsa))
{
WSACleanup();
return false;
}
#endif
this->Initialized = true;
return true;
}
public:
bool Login(void)
{
if(this->Logined)
return true;
if(!this->Initialized)
this->Initialize();
if( !this->socket->open(AF_INET, SOCK_STREAM, IPPROTO_TCP) )
{
#if defined (_WIN32)
WSACleanup();
#endif
return false;
}
if( !this->socket->connect(this->Host, 21, AF_INET) )
{
WSACleanup();
return false;
}
this->readReply();
if(this->retValue != 220)
{
this->Close();
return false;
}
this->sendCommand("USER " + this->Username);
if( !(this->retValue == 331 || this->retValue == 230) )
{
this->Cleanup();
return false;
}
if(this->retValue != 230)
{
this->sendCommand("PASS " + this->Password);
if( !(this->retValue == 230 || this->retValue == 202) )
{
this->Cleanup();
return false;
}
}
this->Logined = true;
this->changeDirectory(this->Path);
return true;
}
void Close(void)
{
if( !this->socket->isOpen() )
{
this->sendCommand("QUIT");
}
this->Cleanup();
#if defined(_WIN32)
WSACleanup();
#endif
}
void Cleanup(void)
{
if( !this->socket->isOpen() )
{
this->socket->close();
}
this->Initialized = false;
this->Logined = false;
}
/* End Connection handler methods */
public:
long getFileSize(string fileName)
{
if(!this->Logined)
this->Login();
this->sendCommand("SIZE " + fileName);
long size = 0;
if(this->retValue == 213)
{
size = atol(this->reply.substr(4).c_str());
}
else return 0;
return size;
}
public:
bool setBinaryMode(bool _mode)
{
if(_mode)
this->sendCommand("TYPE I");
else
this->sendCommand("TYPE A");
if(this->retValue != 200)
return false;
return true;
}
bool changeDirectory(string _Path)
{
if(_Path == ".")
return false;
if(!this->Logined)
this->Login();
this->sendCommand("CWD " + _Path);
if(this->retValue != 250)
return false;
this->Path = _Path;
return true;
}
bool makeDirectory(string _DirName)
{
if(!this->Logined)
this->Login();
this->sendCommand("MKD " + _DirName);
if(this->retValue != 250)
return false;
return true;
}
public:
bool upload(string fileName)
{
return this->upload(fileName,false);
}
public:
bool upload(string fileName,bool resume)
{
if(!this->Logined)
this->Login();
Socket* cSocket = this->createDataSocket();
long offset = 0;
if(resume)
{
try
{
this->setBinaryMode(true);
offset = this->getFileSize(fileName);
}
catch(bool)
{
offset = 0;
}
}
if(offset > 0)
{
this->sendCommand("REST " + offset);
if(this->retValue != 350)
offset = 0;
}
this->sendCommand("STOR " + fileName);
if( !(this->retValue == 125 || this->retValue == 150) )
return false;
/* SECTION = get and send the file */
ifstream input;
input.open( fileName.c_str() , ios::binary );
// get length of file:
int length;
input.seekg (0, ios::end);
length = input.tellg();
input.seekg (0, ios::beg);
// allocate memory:
char *filebuf;
filebuf = new char [length];
// read data as a block:
input.read(filebuf,length);
input.close();
cSocket->send(filebuf, length, 0);
/* end SECTION */
if(cSocket->getPeerName(0,0))
cSocket->close();
this->readReply();
if( !(this->retValue == 226 || this->retValue == 250) )
{
return false;
}
return true;
}
/* Actor Helpers */
void readReply(void)
{
this->mes = "";
this->reply = this->readLine();
this->retValue = lexical_cast<int>( this->reply.substr(0,3) );
}
string readLine(void)
{
while(true)
{
this->bytes = this->socket->receive(this->buffer, BLOCK_SIZE, 0);
cout << "bytes recived : " << this->bytes << endl;
cout << "strlen buffer : " <<(int)strlen(this->buffer) << endl;
cout << "Buffer :\n" << this->buffer << endl;
this->mes += this->buffer;
cout << "Buffer2 :\n" << this->mes << endl;
this->mes = this->mes.substr(0,this->bytes);
cout << "Buffer3 :\n" << this->mes << endl;
if(this->bytes < (int)strlen(this->buffer) )
break;
}
vector<string> mess;
split(mess,this->mes,is_any_of("\n"));
if(this->mes.length() > 2)
{
this->mes = mess[mess.size() - 2];
}
else
{
this->mes = mess[0];
}
if(!(this->mes.substr(3,1) == " "))
{
return this->readLine();
}
return this->mes;
}
private:
void sendCommand(string command)
{
command += "\r\n";
this->socket->send(command, (int)command.length(), 0);
this->readReply();
}
private:
Socket* createDataSocket(void)
{
this->sendCommand("PASV");
if(this->retValue != 227)
return NULL;
int index1 = (int)( this->reply.find_first_of('(', 0) );
int index2 = (int)( this->reply.find_first_of(')', 0) );
string ipData = this->reply.substr(index1 + 1,index2 - index1 - 1);
int parts[6];
int len = (int)ipData.length();
int partCount = 0;
string buf = "";
for(int i = 0; i < len && partCount <= 6; i++)
{
string ch = ipData.substr(i,1);
if( isdigit( lexical_cast<char>(ch) ) ) buf += ch;
else if(ch != ",")
{
return NULL;
}
if(ch == "," || i + 1 == len)
{
try
{
parts[partCount++] = lexical_cast<int>(buf);
buf = "";
}
catch(bad_lexical_cast &)
{
return NULL;
}
}
}
string ipAddress = lexical_cast<string>( parts[0] ) + "." + lexical_cast<string>( parts[1] ) + "." + lexical_cast<string>( parts[2] ) + "." + lexical_cast<string>( parts[3] );
int port = (parts[4] << 8) + parts[5];
Socket* s = new Socket();
if( !s->open(AF_INET,SOCK_STREAM,IPPROTO_TCP) )
return NULL;
if( !s->connect(ipAddress, port, AF_INET) )
return NULL;
return s;
}
/* End Actor helpers */
};
int main()
{
FTPUploader ftp("ftp.magicasoft.net","usr","pass",".");
ftp.Login();
ftp.changeDirectory("httpdocs");
cin.get();
return 0;
}
but this gives... output:
Code:
bytes recived : 59
strlen buffer : 59
Buffer :
220 ProFTPD 1.2.9 Server (ProFTPD) [galapagos.globat.com]
Buffer2 :
220 ProFTPD 1.2.9 Server (ProFTPD) [galapagos.globat.com]
Buffer3 :
220 ProFTPD 1.2.9 Server (ProFTPD) [galapagos.globat.com]
I've checked the most of it but I can't see a difference for the first receive ( readline() )
And I can't see why the exact same strlens give different length :
strlen buffer : 59
strlen buffer : 519