任何人都可以推荐一个体面的 SFTP 库来与 Windows C++ 应用程序一起使用吗?如果可以使用跨平台的,那就更好了,但这不是必需的。它用于商业应用程序,因此付费不是问题。
我正在使用支持 FTP-S 但不支持 SFTP 的出色的Ultimate TCP/IP库(是的,我知道,不是很混乱!)。
我遇到过Chilkat图书馆,它看起来很不错,但想知道是否还有其他人用过。
任何人都可以推荐一个体面的 SFTP 库来与 Windows C++ 应用程序一起使用吗?如果可以使用跨平台的,那就更好了,但这不是必需的。它用于商业应用程序,因此付费不是问题。
我正在使用支持 FTP-S 但不支持 SFTP 的出色的Ultimate TCP/IP库(是的,我知道,不是很混乱!)。
我遇到过Chilkat图书馆,它看起来很不错,但想知道是否还有其他人用过。
查看libcurl。
libcurl 是一个免费且易于使用的客户端 URL 传输库,支持 FTP、FTPS、HTTP、HTTPS、SCP、SFTP、TFTP、TELNET、DICT、LDAP、LDAPS 和 FILE。libcurl 支持 SSL 证书、HTTP POST、HTTP PUT、FTP 上传、基于 HTTP 表单的上传、代理、cookie、用户+密码身份验证(Basic、Digest、NTLM、Negotiate、Kerberos4)、文件传输恢复、http 代理隧道等等!
libcurl 是高度可移植的,它可以在多种平台上构建和工作,包括 Solaris、NetBSD、FreeBSD、OpenBSD、Darwin、HPUX、IRIX、AIX、Tru64、Linux、UnixWare、HURD、Windows、Amiga、OS/2、BeOs、Mac OS X、Ultrix、QNX、OpenVMS、RISC OS、Novell NetWare、DOS 等...
OpenSSH将是一个不错的选择。它是跨平台的,并附带 BSD 许可证,因此您可以在商业应用程序中使用它,而无需透露您的源代码。
您可以在 windows 下使用 libssh 进行 SFTP。编译时必须有 ssh.lib,执行程序时必须有 ssh.dll。它对我来说很好。此示例代码是使用 ssh1 的客户端,我还支持大文件(4GB 及更多)和暂停/恢复。客户端将与任何 ssh(和/或 SFTP)服务器一起使用。由于 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;
}
这是类文件:
// 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;
}