2013-05-12 77 views
3

在我的項目中,我需要在服務器和多個客戶端之間傳輸文件。 客戶端和服務器之間的通信應該加密, 應該有一個用戶名和密碼認證 和協議應該是一個普通的,所以我想到了SFTP。libssh是否支持sftp服務器功能?

有兩個用於ssh:libssh和libssh2的c/C++庫, ,其中只有第一個也提供了服務器功能。

有一個libssh的API文檔,其中涉及子模塊sftp的客戶端模塊 已有詳細記錄。 但是對於server API,我只能找到基本的ssh函數。

libssh是否提供服務器端sftp支持?

+0

還有我們的SecureBlackbox有SSH和SFTP服務器組件和C++版,其中可用於構建SFTP服務器。見http://www.eldos.com/sbb/lib-sftp.php – 2013-05-13 07:16:25

+0

這就是我正在尋找的。但我需要一個開源庫。 – user2369952 2013-05-13 09:47:13

回答

0

是的,你可以使用libssh來實現一個sftp服務器。它只是沒有被分開。

見的功能在sftp.h文件的末尾:

http://git.libssh.org/projects/libssh.git/tree/include/libssh/sftp.h

http://git.libssh.org/projects/libssh.git/tree/src/sftpserver.c

我們很快會發布libssh的新版本,提高服務器支持。

+0

謝謝,這聽起來很成功。 在sftpserver.c中實現的功能是否已經可用,在構建庫時是否需要特殊的編譯選項? – user2369952 2013-05-16 20:01:28

0

你可以使用libssh作爲sftp。我可以在這裏給你一些代碼,它支持暫停/恢復並在Windows上工作。我無法複製整個班級,因爲它會超過此網站的限制。更改用戶名和密碼,主機名到您的SFTP服務器的正確當量:

int main(array<System::String ^> ^args) 
    { 

     //Console::WriteLine(L"Hello World"); 


     pSFTPConnector sshc = new SFTPConnector(L".\\", L"127.0.0.1", 22, L"iman", L"iman"); // change the hostname , port , username, password to your sftp server, your credentials 

     //FILE *nullfile = fopen("null", "w"); 
     //sshc->setLogFile(nullfile); 
     sshc->setVerbosity(SSH_LOG_RARE);  // you can change the verbosity as appropriate for you 

     int i= sshc->InitSession(); 
     i=sshc->ConnectSession(); 
     i = sshc->InitSFTP(); 


     //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->SFTPget("c:\\testdir\\Got_CAR_HIRE_FINAL_test.jpg", "CAR_HIRE_FINAL_test.jpg", 64*1024); 
     i = sshc->SFTPget("c:\\testdir\\get_downloaded_CAR_HIRE_FINAL.jpg", "CAR_HIRE_FINAL.jpg", 64 *1024); 
     i = sshc->SFTPreget("c:\\testdir\\reget_downloaded_CAR_HIRE_FINAL.jpg", "CAR_HIRE_FINAL.jpg", 64 * 1024); 
     i = sshc->SFTPput("c:\\testdir\\CAR_HIRE_FINAL.jpg", "put_CAR_HIRE_FINAL.jpg", 64 * 1024); 
     i = sshc->SFTPreput("c:\\testdir\\CAR_HIRE_FINAL.jpg", "reput_CAR_HIRE_FINAL.jpg", 64 * 1024); 

     delete sshc; 
     return 0; 
    } 


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_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 total_size; 
    __int64 transferred; 
    __int64 averagebps; 
    long long seconds_elapsed; 
    long long  seconds_remained; 
    int percent; 
    ESFTPSTAT transferstate; 
} TTransStat; 


#define E_SESSION_NEW -1 



// these libraries are required 
#pragma comment(lib, "ssh.lib") 





// 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) 
    time_t 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 
    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. 

    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(); 

    ~CSFTPConnector(); 




} SFTPConnector, *pSFTPConnector ; 





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; 
} 

//---------------------------------------- 


ESSHERR CSFTPConnector::SFTPget(char *lfn, char *rfn, size_t blocksize) 
{ 
    DWORD  result; 
    int rc; 
    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; 

    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; 
    } 

    lfilesize =0; 
    transfered =0; 

    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_REMOTEFILE_SEEK; 
    } 


    transferstatus = ES_STARTING; 

    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 = (ESSHERR)result; 
      transferstatus = ES_FAILED; 
      CloseRemoteFile(); 
      CloseLocalFile(); 
      delete block; 
      return (ESSHERR)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, &bytesread, NULL); 
     if (bytesread < blocksize) 
     { 
      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(BLOCKTRANSDELAY); 
     if (loopcounter % 331 == 0)Sleep(77 * BLOCKTRANSDELAY); 
     if (loopcounter % 3331 == 0)Sleep(777 * BLOCKTRANSDELAY); 

    } 

    // closing files 
    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 (ESSHERR) result; 
} 


TTransStat CSFTPConnector::getStatus() 
{ 
    stats.seconds_elapsed = time(NULL) - transferstarttime; 
    stats.averagebps = (transfered * 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; 

    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; 
} 



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; 

    } 
    else{ 
     result = createSFTPfile((char *)tempfilename.c_str()); 
     transferstatus = ES_STARTING; 
     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(BLOCKTRANSDELAY); 
     if (loopcounter % 331 == 0)Sleep(77 * BLOCKTRANSDELAY); 
     if (loopcounter % 3331 == 0)Sleep(777 * BLOCKTRANSDELAY); 

    } 

    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, size_t len, size_t *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; 
     transfered = transfered + readbytes; 
     return E_SFTP_READ_EOF; 
    } 


    *bytesread = readbytes; 
    transfered = transfered + readbytes; 

    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; 
    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_FILEOPEN_WRITE; 
    } 
    return E_OK; 
} 


ESSHERR CSFTPConnector::rdopen_existing_SFTPfile(char *fn) 
{ 

    int access_type = O_RDONLY ; 
    int rc, nwritten; 

    filename = string(fn); 
    file = sftp_open(sftp, fn, 
     access_type, S_IREAD); 
    if (file == NULL) 
    { 
     fprintf(logfile, "Can't open file for writing: %s\n", 
      ssh_get_error(session)); 
     return E_FILEOPEN_RDONLY; 
    } 
    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; 
} 


CSFTPConnector::CSFTPConnector(wchar_t *dir, wchar_t *hn, int hostport, wchar_t *un, wchar_t *pass) 
{ 

    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; 

} 


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 connect the ssh session."; 
     return E_SSH_CONNECT_ERR; 
    } 
    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; 
} 


CSFTPConnector::~CSFTPConnector() 
{ 


    sftp_free(sftp); 
    ssh_disconnect(session); 
    ssh_free(session); 

    return; 
} 
相關問題