Pregunta
¿Alguien puede recomendar una biblioteca SFTP decente para su uso con aplicaciones de Windows C ++? Si una multiplataforma uno está disponible, entonces todo el mejor, pero no es esencial. Es para su uso con una aplicación comercial, por lo que pagar por algo que no es un problema.
Estoy utilizando el excelente última biblioteca TCP / IP que soporta FTP- S pero no SFTP (Yeh, lo sé, confundiendo no lo es!).
Me he encontrado con la biblioteca Chilkat , que se ve muy bien, pero se pregunta si hay otros que la gente ha utilizado.
Solución
libcurl .
libcurl es una biblioteca de transferencia de URL del lado del cliente libre y fácil de usar que da soporte FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, Telnet, DICT, LDAP, LDAPS y el archivo. libcurl compatible con los certificados SSL, HTTP POST, PUT HTTP, carga FTP, cargar basada formulario HTTP, servidores proxy, cookies de usuario + autenticación de contraseña (básica, implícita, NTLM, negociar, Kerberos4), transferencia de archivos hoja de vida, haciendo un túnel proxy http y más!
libcurl es altamente portátil, se construye y funciona de forma idéntica en numerosas plataformas, incluyendo Solaris, NetBSD, FreeBSD, OpenBSD, Darwin, HP-UX, IRIX, AIX, Tru64, Linux, UnixWare, Hurdes, Windows, Amiga, OS / 2, BeOs, Mac OS X, Ultrix, QNX, OpenVMS, RISC OS, Novell NetWare, DOS y más ...
Otros consejos
OpenSSH sería una buena opción. Es multiplataforma y viene con una licencia BSD, para que pueda utilizarlo en su aplicación comercial sin tener que revelar su código fuente.
se puede utilizar para SFTP libssh debajo de las ventanas. debe tener ssh.lib al compilar y ssh.dll durante la ejecución de su programa. Se está trabajando bastante bueno para mí. Este código de ejemplo es un cliente utilizando ssh1 y yo también estoy apoyando archivos de gran tamaño (4 GB y más) y pausa / reanudar. El cliente funciona con cualquier ssh (y / o SFTP) del servidor. No puedo copiar el código completo para usted debido a la limitación en la longitud de los mensajes en stackoverflow.
main()
{
pSFTPConnector sshc = new SFTPConnector(L".\\", L"127.0.0.1", 22, L"sftpuser",L"sftppassword"); // change the hostname , port , username, password to your sftp server, your credentials
FILE *nullfile = fopen("null", "w");
sshc->setLogFile(nullfile);
sshc->setVerbosity(SSH_LOG_DEBUG); // you can change the verbosity as appropriate for you
int i= sshc->InitSession();
if (i != E_OK) wprintf(L"%s",sshc->errstring.c_str() );
i=sshc->ConnectSession();
if (i != E_OK) wprintf(L"%s", sshc->errstring.c_str());
i = sshc->InitSFTP();
if (i != E_OK) wprintf(L"%s", sshc->errstring.c_str());
i = sshc->SFTPrename("renamed_myfile.txt", "myfile.txt"); //change these file names
i = sshc->Makedir("sftpdir");
i = sshc->testUploadFile("myfile2.txt", "1234567890testfile");
// change these file names to whatever appropriate
i = sshc->SFTPreget("c:\\testdir\\reget_downloaded_CAR_HIRE_FINAL.jpg", "CAR_HIRE_FINAL.jpg", 64 * 1024);
sshc->setBlockTransferDelay(1);
i = sshc->GetSessionStatus();
i = sshc->SFTPreput("c:\\testdir\\CentOS-6.5-x86_64-bin-DVD1.iso", "reput_CentOS-6.5-x86_64-bin-DVD1.iso", 64 * 1024);
i = sshc->SFTPreput("c:\\testdir\\Reget_CentOS-6.5-x86_64-bin-DVD1.iso", "reput2_CentOS-6.5-x86_64-bin-DVD1.iso", 64 * 1024);
if (i != E_OK) wprintf(L"%s", sshc->errstring.c_str());
delete sshc;
getchar();
return 0;
}
Este es el archivo de clase:
// filename ssh.h
// SFTP Connection class with Pause/Resume largfiles capability
// uses libssh for sftp functionality.
// Author Desphilboy
// Written 21 Sep 2014
// needed include files on a windows system
// for linux, native file open and read/write functions must be changed.
#include <libssh\libssh.h>
#include <libssh\sftp.h>
#include <Windows.h>
#include <string>
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <time.h>
#include <fstream>
#include <iostream>
#include <process.h>
using namespace std;
// constant to limit length of character strings
#define SHORT_BUFF_LEN 1024
#define INITIALBLOCKTRANSDELAY 10 // mili seconds, this is the delay that we put after each block transfer to make it posssible for network to absorb the data.
// these values will be returned by functions to report error or success
typedef enum sshconerr{
E_OK = 1, E_SESSION_ALOC = -1, E_SSH_CONNECT_ERR = -2, E_SFTP_ALLOC = -3, E_INIT_SFTP = -4, E_CREATE_DIR = -5, E_FILEOPEN_WRITE = -6, E_WRITE_ERR = -7
, E_FILE_CLOSE = -8, E_FILE_OPEN_READ = -9, E_INVALID_PARAMS = -10, E_SFTP_ERR = -11, E_SFTP_READ_ERR = -12, E_SFTP_READBYTES_ERR = -13, E_GET_FILEINF = -14
, E_LOCAL_FILE_NOTFOUND = -15, E_RENAME_ERR = -16, E_MEM_ALLOC = -17, E_LOCAL_FILE_READ = -18, E_LOCAL_FILE_RDWR = -19, E_REMOTEFILE_SEEK = -20
, E_REMOTE_FILE_OPEN = -21, E_DELETE_ERR = -22, E_RENAME_LOCAL_FILE = -23, E_LOCAL_DELETE_FILE = -24, E_FILEOPEN_RDONLY = -25, E_SFTP_READ_EOF=-26
,E_AUTHENTICATE=-27 ,E_UNKNOWN=-999 } ESSHERR;
// status of transfers;
typedef enum sftpstat{ ES_DONE=0 , ES_INPROGRESS , ES_FAILED, ES_STARTING, ES_PAUSED, ES_RESUMING, ES_CANCELLED, ES_NONE } ESFTPSTAT;
using namespace std;
// statistics about the transfer;
typedef struct transferstatstruct {
string remote_file_name;
string local_file_name;
__int64 initially_transferred;
__int64 total_size;
__int64 transferred;
__int64 averagebps;
__int64 seconds_elapsed;
__int64 seconds_remained;
int percent;
ESFTPSTAT transferstate;
} TTransStat;
#define E_SESSION_NEW -1
// these libraries are required
#pragma comment(lib, "ssh.lib") // for ex4ecution in windows, ssh.dll is needed
// this is the main class that does the majority of the work
typedef class CSFTPConnector{
private:
ssh_session session; // ssh session
sftp_session sftp; // sftp session
sftp_file file; // structure for a remote file
FILE *localfile; // not used in windows but could be local file pointer in UNIX
FILE *logfile; // the file for writing logs, default is set to stderr
string filename; // file name of the transfer;
string localfilename; // file name of local file;
string tempfilename; // a temporaty file name will be used during the transfer which is renamed when transfer is completed.
ESFTPSTAT transferstatus; // state of the transfer which has one of the above values (ESFTPSTAT)
__int64 transferstarttime; // time of start of the transfer
wchar_t username[SHORT_BUFF_LEN];
wchar_t password[SHORT_BUFF_LEN];
wchar_t hostname[SHORT_BUFF_LEN]; // hostname of the sftp server
wchar_t basedir[SHORT_BUFF_LEN]; // this base dir is the directory of public and private key structur ( NOT USED IN THIS VERSION)
int port; // port of the server;
int verbosity; // degree of verbosity of libssh
__int64 filesize; // total number of bytes to be transfered;
DWORD local_file_size_hiDWORD; // Bill Gates cannot accept the file size without twisting the programmers, so he accepts them in 2 separate words like this
DWORD local_file_size_lowDWORD; // these 2 DWORDs when connected together comprise a 64 bit file size.
__int64 lfilesize; // local file size
__int64 rfilesize; // remote file size
__int64 transfered; // number of bytes already transfered
__int64 initially_was_transferred; // this is the number of bytes which was transferred before pause or interrupt of a transfer and used when resuming a transfer.
bool pause; // pause flag
TTransStat stats; // statistics of the transfer
HANDLE localfilehandle; // windows uses handles to manipulate files. this is the handle to local file.
int blocktransferdelay;
ESSHERR CSFTPConnector::rwopen_existing_SFTPfile(char *fn); // open a file on remote ( server ) read/write for upload
ESSHERR CSFTPConnector::rdopen_existing_SFTPfile(char *fn); // open a file on remote ( server ) read only for download
ESSHERR createSFTPfile(char *fn); // create a file on server;
ESSHERR writeSFTPfile(char *block, size_t blocksize); // write a block of data to the open remote file
ESSHERR readSFTPfile(char *block, size_t len, size_t *bytesread); // read a block of data from the open remote file
ESSHERR readSFTPfile(char *block, __int64 len, DWORD *bytesread);
ESSHERR closeSFTPfile(); // closes the remote file;
ESSHERR openSFTPfile(char *fn); // opens the remote file
ESSHERR getSFTPfileinfo(); // gets information about the remote file
public:
wstring errstring; // the string describing last error
ESSHERR Err; // error code of last error
CSFTPConnector(); // default constructor;
CSFTPConnector(wchar_t *dir, wchar_t *hn, int hostport, wchar_t *un, wchar_t *pass); // constructor
void setVerbosity(int v);
int getVerbosity();
ESSHERR InitSession(); // must be called befor doing any transfer
ESSHERR ConnectSession(); // connnects to the ssh server
ESSHERR InitSFTP(); // must be called befor doing any transfer
ESSHERR Makedir(char *newdir);
ESSHERR testUploadFile(char *fn, char *block); // do not use this , only for test purposes for myself
ESSHERR SFTPput(char *lfn, char *rfn, size_t blocksize); // Upload a file from start
ESSHERR SFTPreput(char *lfn, char *rfn, size_t blocksize); // checks for previouse interrupted transfer, then either continues the previouse transfer ( if there was any) or starts a new one (UPLOAD)
ESSHERR SFTPrename(char *newname, char *oldname); // renames a remote file( must be closed)
ESSHERR CSFTPConnector::SFTPdelete(char *remfile); // deletes a remote file
TTransStat *getStatus(); // gets statistics of the transfer
ESSHERR CSFTPConnector::SFTPget(char *lfn, char *rfn, size_t blocksize); // Downloads a file from sftp server
ESSHERR CSFTPConnector::SFTPreget(char *lfn, char *rfn, size_t blocksize); // checks for previouse interrupted transfer, then either continues the previouse transfer ( if there was any) or starts a new one (DOWNLOAD)
void CancelTransfer();
void PauseTransfer();
void setLogFile(FILE *logf); // sets the log file, if not set stderr will be used. by default.
void CloseLocalFile();
void CloseRemoteFile();
int GetSessionStatus();
bool IsConnected();
void setBlockTransferDelay(int miliseconds);
ESFTPSTAT getTransferStatus();
~CSFTPConnector();
} SFTPConnector, *pSFTPConnector ;
sftpstat CSFTPConnector::getTransferStatus()
{
return transferstatus;
}
void CSFTPConnector::setBlockTransferDelay(int miliseconds)
{
blocktransferdelay = miliseconds;
}
bool CSFTPConnector::IsConnected()
{
if (ssh_is_connected(session) == 1) return true;
return false;
}
int CSFTPConnector::GetSessionStatus()
{
return ssh_get_status(session);
}
void CSFTPConnector::CloseLocalFile()
{
CloseHandle(localfilehandle);
}
void CSFTPConnector::CloseRemoteFile()
{
sftp_close(file);
}
void CSFTPConnector::setLogFile(FILE *logf)
{
logfile = logf;
}
void CSFTPConnector::CancelTransfer()
{
transferstatus = ES_CANCELLED;
}
void CSFTPConnector::PauseTransfer()
{
transferstatus = ES_PAUSED;
pause = true;
}
//----------------------------------------
// SFTPreger starts or resumes a download.
ESSHERR CSFTPConnector::SFTPreget(char *lfn, char *rfn, size_t blocksize)
{
ESSHERR result;
int rc;
BOOL bresult;
DWORD bytesread;
DWORD byteswritten;
filesize = 0;
transfered = 0;
initially_was_transferred = 0;
lfilesize = rfilesize = 0;
pause = false;
transferstatus = ES_NONE;
char *block;
struct stat st;
wchar_t temp[SHORT_BUFF_LEN];
size_t tempsize;
wstring wlfn;
int loopcounter = 0;
localfilename = lfn;
filename = rfn;
tempfilename = string(lfn) + ".sftp_temp";
mbstowcs_s(&tempsize, temp, tempfilename.c_str(), SHORT_BUFF_LEN);
localfilehandle = CreateFile(temp, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (localfilehandle == INVALID_HANDLE_VALUE)
{
transferstatus = ES_FAILED;
errstring = L"Could not open local file:" + wstring(temp) +L" for read and write";
Err = E_LOCAL_FILE_RDWR;
return E_LOCAL_FILE_RDWR;
}
local_file_size_lowDWORD = GetFileSize(localfilehandle, &local_file_size_hiDWORD);
lfilesize = (local_file_size_hiDWORD * 0x100000000) + local_file_size_lowDWORD;
if (lfilesize < 0) {
transferstatus = ES_FAILED;
Err = E_LOCAL_FILE_NOTFOUND;
errstring = L"Could not get size info for file:" + wstring(temp);
CloseLocalFile();
return E_LOCAL_FILE_NOTFOUND;
}
transfered = lfilesize;
initially_was_transferred = lfilesize;
__int64 tempi64 = transfered & 0x00000000FFFFFFFF;
DWORD dwlow = tempi64;
tempi64 = (transfered & 0x7FFFFFFF00000000);
tempi64 = tempi64 >> 32;
long dwhi = tempi64;
DWORD dwResult = SetFilePointer(localfilehandle, dwlow, &dwhi, FILE_BEGIN);
if (dwResult == INVALID_SET_FILE_POINTER)
{
errstring = L"could not set file pointer for localfile" + wstring(temp);
transferstatus = ES_FAILED; Err = result;
CloseLocalFile();
return result;
}
block = (char*)malloc(blocksize + 1);
if (block == NULL) {
Err = E_MEM_ALLOC;
transferstatus = ES_FAILED;
errstring = L"Could not allocate memory for file block size";
CloseLocalFile();
return E_MEM_ALLOC;
}
result = rdopen_existing_SFTPfile((char *)rfn);
if (result == E_OK){
getSFTPfileinfo();
filesize = rfilesize;
}
else
{
Err = E_REMOTE_FILE_OPEN;
transferstatus = ES_FAILED;
errstring = L"Could not open remote file";
CloseLocalFile();
delete block;
return E_REMOTE_FILE_OPEN;
}
rc=sftp_seek64(file, transfered);
if (rc != SSH_OK)
{
Err = E_REMOTEFILE_SEEK;
transferstatus = ES_FAILED;
errstring = L"Could not set pointer for remote file";
CloseRemoteFile();
CloseLocalFile();
delete block;
return E_REMOTEFILE_SEEK;
}
transferstatus = ES_RESUMING;
sftp_file_set_blocking(file);
transferstarttime = time(NULL);
transferstatus = ES_INPROGRESS;
while (transferstatus != ES_FAILED && transferstatus != ES_PAUSED && transferstatus!=ES_CANCELLED &&transferstatus != ES_DONE)
{
loopcounter++;
result = readSFTPfile(block,blocksize, (size_t *) &bytesread);
if (result != E_OK && result != E_SFTP_READ_EOF)
{
errstring = L"Error reading from remote sftp server file.";
Err = result;
transferstatus = ES_FAILED;
CloseRemoteFile();
CloseLocalFile();
delete block;
return result;
}
if (result == E_SFTP_READ_EOF) transferstatus = ES_DONE;
fprintf(logfile, "Read %d bytes from input file. Number of packets: %d , %llu from %llu bytes\n", bytesread, loopcounter, transfered, filesize);
bresult = WriteFile(localfilehandle, (LPVOID)block, bytesread, &byteswritten, NULL);
if (byteswritten < bytesread)
{
if (bresult == FALSE)
{
errstring = L"Error writing to local file.";
Err = E_LOCAL_FILE_RDWR;
transferstatus = ES_FAILED;
CloseRemoteFile();
CloseLocalFile();
delete block;
return E_LOCAL_FILE_RDWR;
}
else if (bytesread == 0)
{
errstring = L"Transfer done.";
Err = E_OK;
transferstatus = ES_DONE;
continue;
}
}
Err = E_OK;
if (pause == true) transferstatus = ES_PAUSED;
if (bresult == TRUE && bytesread == 0)
{
// at the end of the file
transferstatus = ES_DONE;
}
Sleep(blocktransferdelay);
if (loopcounter % 71 == 0)Sleep(7 * blocktransferdelay);
if (loopcounter % 331 == 0)Sleep(77 * blocktransferdelay);
if (loopcounter % 3331 == 0)Sleep(777 * blocktransferdelay);
}
result = closeSFTPfile();
CloseHandle(localfilehandle);
Sleep(1000);
if (transferstatus == ES_DONE)
{
wchar_t temp2[SHORT_BUFF_LEN];
mbstowcs_s(&tempsize, temp2, lfn, SHORT_BUFF_LEN);
bresult = MoveFile(temp, temp2);
if (bresult != TRUE)
{
Err = E_RENAME_LOCAL_FILE;
errstring = L"Could not rename local file: " + wstring(temp);
transferstatus = ES_FAILED;
delete block;
return E_RENAME_LOCAL_FILE;
}
}
if (transferstatus == ES_CANCELLED)
{
wchar_t temp2[SHORT_BUFF_LEN];
mbstowcs_s(&tempsize, temp2, lfn, SHORT_BUFF_LEN);
bresult = DeleteFile(temp);
if (bresult != TRUE)
{
Err = E_LOCAL_DELETE_FILE;
errstring = L"Could not rename local file: " + wstring(temp);
transferstatus = ES_FAILED;
delete block;
return E_LOCAL_DELETE_FILE;
}
}
delete block;
return result;
}
//---------------------------------------
TTransStat * CSFTPConnector::getStatus()
{
stats.seconds_elapsed = time(NULL);
stats.seconds_elapsed -= transferstarttime;
stats.averagebps = ((transfered- initially_was_transferred) * 8) / stats.seconds_elapsed;
if (filesize > 0) {
stats.percent = (transfered *100)/ filesize;
stats.seconds_remained = ((filesize - transfered) * 8) / stats.averagebps;
}
else
{
stats.percent = -1;
stats.seconds_remained = -1;
}
stats.total_size = filesize;
stats.transferstate = transferstatus;
stats.remote_file_name = filename;
stats.local_file_name = localfilename;
stats.transferred = transfered;
stats.initially_transferred = initially_was_transferred;
return &stats;
}
ESSHERR CSFTPConnector::SFTPrename(char *newname, char *oldname)
{
int rc=sftp_rename(sftp, oldname, newname);
if (rc !=SSH_OK){
return E_RENAME_ERR;
}
return E_OK;
}
ESSHERR CSFTPConnector::SFTPdelete(char *remfile)
{
int rc = sftp_unlink(sftp,remfile);
if (rc != SSH_OK){
return E_DELETE_ERR;
}
return E_OK;
}
// SFTPreput
ESSHERR CSFTPConnector::SFTPreput(char *lfn, char *rfn, size_t blocksize)
{
ESSHERR result;
BOOL bresult;
DWORD bytesread;
filesize = 0;
transfered = 0;
pause = false;
transferstatus = ES_NONE;
char *block;
struct stat st;
wchar_t temp[SHORT_BUFF_LEN];
size_t tempsize;
wstring wlfn;
int loopcounter = 0;
localfilename = lfn;
//wlfn = wstring(lfn);
//localfile = fopen(lfn, L"r");
filename = rfn;
mbstowcs_s(&tempsize, temp, lfn, SHORT_BUFF_LEN);
//filesize = getFileSize(localfilename);
/*if(filesize < 0) {
transferstatus = ES_FAILED;
Err = E_LOCAL_FILE_NOTFOUND;
return E_LOCAL_FILE_NOTFOUND;
}*/
localfilehandle = CreateFile(temp, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (localfilehandle == INVALID_HANDLE_VALUE)
{
transferstatus = ES_FAILED;
Err = E_LOCAL_FILE_NOTFOUND;
return E_LOCAL_FILE_NOTFOUND;
}
local_file_size_lowDWORD = GetFileSize(localfilehandle, &local_file_size_hiDWORD);
filesize = (local_file_size_hiDWORD * 0x100000000) + local_file_size_lowDWORD;
if (filesize < 0) {
transferstatus = ES_FAILED;
Err = E_LOCAL_FILE_NOTFOUND;
CloseLocalFile();
return E_LOCAL_FILE_NOTFOUND;
}
block = (char*)malloc(blocksize + 1);
if (block == NULL) {
Err = E_MEM_ALLOC;
transferstatus = ES_FAILED;
errstring = L"Could not allocate memory for file block size";
CloseLocalFile();
return E_MEM_ALLOC;
}
tempfilename = string(rfn) + ".sftp_temp";
result = rwopen_existing_SFTPfile((char *)tempfilename.c_str());
if (result == E_OK){
getSFTPfileinfo();
sftp_seek64(file, rfilesize);
__int64 tempi64 = rfilesize & 0x00000000FFFFFFFF;
DWORD dwlow = tempi64;
tempi64 = (rfilesize & 0x7FFFFFFF00000000);
tempi64 = tempi64 >> 32;
long dwhi = tempi64;
DWORD dwResult=SetFilePointer(localfilehandle, dwlow,&dwhi , FILE_BEGIN);
if (dwResult == INVALID_SET_FILE_POINTER)
{
transferstatus = ES_FAILED; Err = result; return result;
}
transferstatus = ES_RESUMING;
transfered = rfilesize;
initially_was_transferred = rfilesize;
}
else{
result = createSFTPfile((char *)tempfilename.c_str());
transferstatus = ES_STARTING;
rfilesize = 0;
initially_was_transferred = 0;
if (result != E_OK) {
transferstatus = ES_FAILED;
Err = result;
CloseLocalFile();
return result;
}
}
sftp_file_set_blocking(file);
transferstarttime = time(NULL);
transferstatus = ES_INPROGRESS;
while (transferstatus != ES_FAILED && transferstatus != ES_PAUSED && transferstatus != ES_DONE)
{
loopcounter++;
bresult = ReadFile(localfilehandle, (LPVOID)block, blocksize, &bytesread, NULL);
fprintf(logfile, "Read %d bytes from input file. Number of packets: %d , %llu from %llu bytes\n", bytesread, loopcounter, transfered, filesize);
if (bytesread < blocksize)
{
if (bresult == FALSE)
{
errstring = L"Error reading from local file.";
Err = E_LOCAL_FILE_READ;
transferstatus = ES_FAILED;
CloseRemoteFile();
CloseLocalFile();
return E_LOCAL_FILE_READ;
}
else if (bytesread == 0)
{
errstring = L"Transfer done.";
Err = E_OK;
transferstatus = ES_DONE;
continue;
}
}
result = writeSFTPfile(block, bytesread);
if (result != E_OK && bytesread>0 )
{
errstring = L"Error transmitting to remote sftp server file.";
Err = result;
transferstatus = ES_FAILED;
CloseRemoteFile();
CloseLocalFile();
return result;
}
Err = E_OK;
//transfered = transfered + bytesread;
if (pause == true) transferstatus = ES_PAUSED;
if (bresult == TRUE && bytesread == 0)
{
// at the end of the file
transferstatus = ES_DONE;
}
Sleep(blocktransferdelay);
if (loopcounter % 71 == 0)Sleep(7 * blocktransferdelay);
if (loopcounter % 331 == 0)Sleep(77 * blocktransferdelay);
if (loopcounter % 3331 == 0)Sleep(777 * blocktransferdelay);
}
CloseRemoteFile();
CloseLocalFile();
Sleep(1000);
if (transferstatus == ES_CANCELLED)
{
result = SFTPdelete((char *)tempfilename.c_str());
if (bresult != E_OK)
{
Err = E_DELETE_ERR;
errstring = L"Could not delete remote file.";
transferstatus = ES_FAILED;
return E_DELETE_ERR;
}
}
if (transferstatus == ES_DONE) result = SFTPrename(rfn, (char *)tempfilename.c_str());
delete block;
return result;
}
ESSHERR CSFTPConnector::getSFTPfileinfo()
{
sftp_attributes fileinf = sftp_fstat(file);
if (fileinf == NULL){
return E_GET_FILEINF;
}
rfilesize = fileinf->size;
sftp_attributes_free(fileinf);
return E_OK;
}
ESSHERR CSFTPConnector::closeSFTPfile()
{
int rc = sftp_close(file);
if (rc != SSH_OK)
{
fprintf(logfile, "Can't close the written file: %s\n",
ssh_get_error(session));
return E_FILE_CLOSE;
}
return E_OK;
}
ESSHERR CSFTPConnector::writeSFTPfile(char *block, size_t blocksize)
{
size_t nwritten = sftp_write(file, block, blocksize);
if (nwritten != blocksize)
{
fprintf(logfile, "Can't write data to file: %s\n",
ssh_get_error(session));
//sftp_close(file);
transfered = transfered + nwritten;
return E_WRITE_ERR;
}
transfered = transfered + nwritten;
return E_OK;
}
ESSHERR CSFTPConnector::readSFTPfile(char *block, __int64 len, DWORD *bytesread)
{
DWORD readbytes;
*bytesread = 0;
if (len <= 0) return E_INVALID_PARAMS;
if (bytesread == NULL || block == NULL) return E_INVALID_PARAMS;
readbytes = sftp_read(file, block, len);
if (readbytes < 0)
{
fprintf(logfile, "Can't read from remote file: %s %s\n", filename.c_str(), ssh_get_error(session));
*bytesread = 0;
return E_SFTP_READ_ERR;
}
if (readbytes < len)
{
*bytesread = readbytes;
return E_SFTP_READ_EOF;
}
*bytesread = readbytes;
transfered = transfered + readbytes;
return E_OK;
}
ESSHERR CSFTPConnector::createSFTPfile(char *fn)
{
int access_type = O_CREAT | O_RDWR | O_APPEND;
int rc, nwritten;
filename = string(fn);
file = sftp_open(sftp, fn,access_type, S_IREAD | S_IWRITE);
if (file == NULL)
{
fprintf(logfile, "Can't open file for writing: %s\n",
ssh_get_error(session));
return E_FILEOPEN_WRITE;
}
return E_OK;
}
ESSHERR CSFTPConnector::openSFTPfile(char *fn)
{
int access_type = O_RDONLY;
int rc, nwritten;
filename = string(fn);
file = sftp_open(sftp, fn,
access_type, S_IWRITE);
if (file == NULL)
{
fprintf(logfile, "Can't open file for writing: %s\n",
ssh_get_error(session));
return E_FILE_OPEN_READ;
}
return E_OK;
}
ESSHERR CSFTPConnector::Makedir(char *newdir)
{
int rc;
rc = sftp_mkdir(sftp, newdir, S_IFDIR);
if (rc != SSH_OK)
{
if (sftp_get_error(sftp) != SSH_FX_FILE_ALREADY_EXISTS)
{
fprintf(logfile, "Can't create directory: %s\n",
ssh_get_error(session));
return E_CREATE_DIR;
}
}
return E_OK;
}
SFTPConnector::CSFTPConnector()
{
//libssh2_init(0);
session = ssh_new();
if (session == NULL)
{
Err = E_SESSION_ALOC;
errstring = L"Could not allocate a session.";
}
wcscpy(hostname, L"localhost" );
wcscpy(username, L"User");
wcscpy(password, L"Password");
wcscpy(basedir, L".\\");
port = 22;
verbosity = SSH_LOG_RARE;
filesize = 0;
transfered = 0;
pause = false;
transferstatus = ES_NONE;
logfile = stderr;
blocktransferdelay = INITIALBLOCKTRANSDELAY;
}
CSFTPConnector::CSFTPConnector(wchar_t *dir, wchar_t *hn, int hostport, wchar_t *un, wchar_t *pass)
{
//libssh2_init(0);
session = ssh_new();
if (session == NULL)
{
Err = E_SESSION_ALOC;
errstring = L"Could not allocate a session.";
}
wcscpy(hostname, hn);
wcscpy(username, un);
wcscpy(password, pass);
wcscpy(basedir, dir);
port = hostport;
verbosity = SSH_LOG_RARE;
filesize=0;
transfered=0;
pause=false;
transferstatus = ES_NONE;
logfile = stderr;
blocktransferdelay = INITIALBLOCKTRANSDELAY;
}
ESSHERR CSFTPConnector::InitSFTP()
{
int rc;
sftp= sftp_new(session);
if (session == NULL)
{
Err = E_SFTP_ALLOC;
errstring = L"Could not allocate a sftp session.";
}
rc = sftp_init(sftp);
if (rc != SSH_OK)
{
fprintf(logfile, "Error initializing SFTP session: %s.\n",
sftp_get_error(sftp));
sftp_free(sftp);
return E_INIT_SFTP;
}
return E_OK;
}
ESSHERR CSFTPConnector::ConnectSession()
{
char temp[SHORT_BUFF_LEN];
size_t n_of_chars;
wcstombs_s(&n_of_chars, temp, SHORT_BUFF_LEN, (const wchar_t *)password, SHORT_BUFF_LEN);
int ir;
ir=ssh_connect(session);
if (ir != SSH_OK){
errstring = L"Could not connect the ssh session.";
return E_SSH_CONNECT_ERR;
}
ir=ssh_userauth_password(session, NULL, temp);
if (ir != SSH_OK){
errstring = L"Could not authenticate with the ssh server.\r\n";
return E_AUTHENTICATE;
}
return E_OK;
}
ESSHERR CSFTPConnector::InitSession()
{
char temp[SHORT_BUFF_LEN];
size_t n_of_chars;
wcstombs_s(&n_of_chars, temp,SHORT_BUFF_LEN, (const wchar_t *) hostname, SHORT_BUFF_LEN);
ssh_options_set(session, SSH_OPTIONS_HOST,temp);
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
ssh_options_set(session, SSH_OPTIONS_PORT, &port);
wcstombs_s(&n_of_chars, temp, SHORT_BUFF_LEN, (const wchar_t *)username, SHORT_BUFF_LEN);
ssh_options_set(session, SSH_OPTIONS_USER,temp);
wcstombs_s(&n_of_chars, temp, SHORT_BUFF_LEN, (const wchar_t *)basedir, SHORT_BUFF_LEN);
ssh_options_set(session, SSH_OPTIONS_SSH_DIR, temp);
return E_OK;
}
void CSFTPConnector::setVerbosity(int v)
{
verbosity = v;
}
int CSFTPConnector::getVerbosity()
{
return verbosity;
}