ftp/Win32.cpp
// Win32.cpp : Defines the entry point for the console application.
//
// Summary: sfFTPLib c++ demonstration
//
// Technical support: support@smartftp.com
//
// Copyright (c) SmartSoft Ltd.
// Note for Non-Unicode Build:
// If you get one of the following errors add comsuppw.lib (Release) or comsuppwd.lib (Debug) to the linker's "Additional Dependencies".
// Win32.obj : error LNK2019: unresolved external symbol "wchar_t * __stdcall _com_util::ConvertStringToBSTR(char const *)"
// Win32.obj : error LNK2019: unresolved external symbol "char * __stdcall _com_util::ConvertBSTRToString(wchar_t *)"
#include "stdafx.h"
#include "Win32.h"
using namespace std;
CComBSTR GetKey(const CString& strPassword)
{
// TODO: Hash strPassword (e.g. MD5) and set data
byte data[128/8];
CComBSTR bstrKey;
bstrKey.AppendBytes(reinterpret_cast<char*>(data), sizeof(data));
return bstrKey;
}
// nMode: 1 = Read
// 2 = Write
sfFTPLib::IStreamFilterPtr CreateStreamFilter(const CString &strPassword, int nBits, int nMode)
{
sfFTPLib::IStreamFilterPtr pStream;
if(nMode == 1)
{
sfFTPLib::IAES128CTRReadStreamPtr pRead;
ATLENSURE_SUCCEEDED(pRead.CreateInstance(__uuidof(sfFTPLib::AES128CTRReadStream)));
ATLENSURE_SUCCEEDED(pRead->raw_SetKey(GetKey(strPassword)));
pStream = pRead;
}
else if(nMode == 2)
{
sfFTPLib::IAES128CTRWriteStreamPtr pWrite;
ATLENSURE_SUCCEEDED(pWrite.CreateInstance(__uuidof(sfFTPLib::AES128CTRWriteStream)));
ATLENSURE_SUCCEEDED(pWrite->raw_SetKey(GetKey(strPassword)));
pStream = pWrite;
}
return pStream;
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// init COM
ATLVERIFY(SUCCEEDED(::CoInitializeEx(NULL, COINIT_MULTITHREADED)));
try
{
sfFTPLib::IGlobalPtr pGlobal;
HRESULT hr = pGlobal.CreateInstance(__uuidof(sfFTPLib::Global));
if(SUCCEEDED(hr))
{
// TODO: uncomment to load serial from string
//pGlobal->LoadLicense(_T("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"));
// UPnP
sfFTPLib::IUPnPNATManagerPtr pUPnPNATManager;
hr = pUPnPNATManager.CreateInstance(__uuidof(sfFTPLib::UPnPNATManager));
if(SUCCEEDED(hr))
{
pUPnPNATManager->Initialize();
}
sfFTPLib::IFTPConnectionPtr ftp;
hr = ftp.CreateInstance(__uuidof(sfFTPLib::FTPConnectionMTA));
if(SUCCEEDED(hr))
{
ftp->LogFile->File = L"Win32Demo.log";
// AUTH TLS
ftp->_Protocol = sfFTPLib::ftpProtocolSSLExplicit;
ftp->Host = _T("smartftp.com");
ftp->Port = 21;
ftp->Username = _T("anonymous");
ftp->Password = _T("bla@bla.com");
ftp->Passive = VARIANT_TRUE;
// No Proxy
//ftp->Proxy->Type = sfFTPLib::ftpProxyTypeNone;
//ftp->Proxy->Host =_T("192.168.1.10");
//ftp->Proxy->Port = 1080;
//ftp->Proxy->Authentication = VARIANT_TRUE;
//ftp->Proxy->Username = _T("user");
//ftp->Proxy->Password = _T("pass");
// Connect
ftp->Connect();
ftp->ChangeDirectory(_T("/SmartFTP"));
// read listing
sfFTPLib::IFTPItemsPtr pDirectory = ftp->ReadDirectory();
if(pDirectory)
{
int nCount = pDirectory->Count;
_tprintf(_T("Count = %d\n"), nCount);
// Enum
if(nCount > 0)
{
IEnumVARIANTPtr pEnum = pDirectory->_NewEnum;
ATLENSURE(pEnum);
VARIANT *pArrVariant = new VARIANT[nCount];
ULONG CeltFetched;
if(SUCCEEDED(pEnum->Next(nCount, pArrVariant, &CeltFetched)))
{
for(ULONG i=0; i<CeltFetched; i++)
{
if(pArrVariant[i].vt == VT_DISPATCH)
{
sfFTPLib::IFTPItemPtr pFTPItem = pArrVariant[i].pdispVal;
if(pFTPItem)
{
_tprintf(_T("Type=0x%x; Name=%s; Size=%d\n"), pFTPItem->Type, (LPCTSTR)pFTPItem->Name, pFTPItem->Size);
if(pFTPItem->Type == sfFTPLib::ftpItemTypeSymLink)
{
_tprintf(_T("LinkPoint=%s"), (LPCTSTR)pFTPItem->LinkPoint);
}
}
}
::VariantClear(&pArrVariant[i]);
}
}
delete [] pArrVariant;
}
}
// download file
ftp->DownloadFile(_T("History.txt"), _T("History.txt"), 0, 0);
_tprintf(_T("DownloadFile() successful.\n"));
_tprintf(_T("LastTransferBytes = %I64u B\n"), ftp->LastTransferBytes);
_tprintf(_T("LastTransferTime = %d s\n"), ftp->LastTransferTime);
_tprintf(_T("LastTransferSpeed = %d B/s\n"), ftp->LastTransferSpeed);
// DownloadFileEx using IStream
// create a storage
IStoragePtr pStorage;
if(SUCCEEDED(::StgCreateDocfile(_T("Storage"), STGM_NOSCRATCH | STGM_TRANSACTED | STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage)))
{
IStreamPtr pStream;
if(SUCCEEDED(pStorage->CreateStream(L"CONTENTS", STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream)))
{
ftp->DownloadFileEx(_T("History.txt"), CComVariant(pStream.GetInterfacePtr()), 0, 0);
_tprintf(_T("DownloadFileEx() successful.\n"));
}
pStream->Commit(STGC_OVERWRITE | STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE);
pStorage->Commit(STGC_OVERWRITE | STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE);
}
// Uncomment this to test encryption. You need a server with upload permissions.
/*
// Upload with encryption
sfFTPLib::IStreamFilterPtr pEncryption = CreateStreamFilter(_T("Password"), 128, 1);
ftp->StreamFilter = pEncryption;
err = ftp->UploadFile(_T("History.txt"), _T("History.txt.encrypted"), 0, 0);
// Download with decryption
sfFTPLib::IStreamFilterPtr pDecryption = CreateStreamFilter(_T("Password"), 128, 2);
ftp->StreamFilter = pDecryption;
ftp->DownloadFile(_T("History.txt.encrypted"), _T("History.txt.decrypted"), 0, 0);
*/
}
else
{
_tprintf(_T("Failed to create CFTPConnection instance.\n"));
}
// UPnP
if(pUPnPNATManager)
{
pUPnPNATManager->Uninitialize();
}
}
}
catch(_com_error &e)
{
_tprintf(_T("Com Error:\n"));
_tprintf(_T("Code = %08lx\n"), e.Error());
_tprintf(_T("Code meaning = %s\n"), (LPCTSTR) e.ErrorMessage());
_tprintf(_T("Source = %s\n"), (LPCTSTR) e.Source());
_tprintf(_T("Error Description = %s\n"), (LPCTSTR) e.Description());
}
catch(...)
{
_tprintf(_T("Unknown Error\n"));
}
::CoUninitialize();
return nRetCode;
}