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.
#include "stdafx.h"
#include "Win32.h"
ATL::CComSafeArray<byte> GetKey(const ATL::CString& password)
{
// TODO: Hash strPassword (e.g. MD5) and set data
byte data[128 / 8];
ATL::CComSafeArray<byte> key;
ATLENSURE_SUCCEEDED(key.Create(sizeof(data)));
auto begin = reinterpret_cast<const byte*>(data);
auto end = reinterpret_cast<const byte*>(data) + sizeof(data);
auto it = begin;
for (long Index = 0; it != end; Index++, ++it)
{
key.SetAt(Index, *it);
}
return key;
}
// nMode: 1 = Read
// 2 = Write
ATL::CComPtr<sfFTPLib::IStreamFilter> CreateStreamFilter(const ATL::CString &password, int nBits, int nMode)
{
ATL::CComPtr<sfFTPLib::IStreamFilter> pStream;
if(nMode == 1)
{
ATL::CComPtr<sfFTPLib::IAES128CTRReadStream> pRead;
ATLENSURE_SUCCEEDED(pRead.CoCreateInstance(__uuidof(sfFTPLib::AES128CTRReadStream)));
ATLENSURE_SUCCEEDED(pRead->SetKey((byte*) password.GetString(), password.GetLength()));
pStream = pRead;
}
else if (nMode == 2)
{
ATL::CComPtr<sfFTPLib::IAES128CTRWriteStream> pWrite;
ATLENSURE_SUCCEEDED(pWrite.CoCreateInstance(__uuidof(sfFTPLib::AES128CTRWriteStream)));
ATLENSURE_SUCCEEDED(pWrite->SetKey((byte*)password.GetString(), password.GetLength()));
pStream = pWrite;
}
return pStream;
}
void DownloadUsingStream(_In_ sfFTPLib::IFTPConnection* connection)
{
// create a storage
ATL::CComPtr<IStorage> pStorage;
ATLENSURE_SUCCEEDED(::StgCreateDocfile(_T("Storage"), STGM_NOSCRATCH | STGM_TRANSACTED | STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage));
ATL::CComPtr<IStream> pStream;
ATLENSURE_SUCCEEDED(pStorage->CreateStream(L"CONTENTS", STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream));
connection->DownloadFileEx(ATL::CComBSTR(_T("History.txt")), ATL::CComVariant(pStream.p), 0, 0, nullptr);
_tprintf(_T("DownloadFileEx() successful.\n"));
pStream->Commit(STGC_OVERWRITE | STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE);
pStorage->Commit(STGC_OVERWRITE | STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE);
}
void ReadDirectory(_In_ sfFTPLib::IFTPConnection* connection, _In_z_ PCWSTR directory)
{
ATLENSURE_SUCCEEDED(connection->ChangeDirectory(ATL::CComBSTR(directory)));
// read listing
ATL::CComPtr<sfFTPLib::IFTPItems> pDirectory;
ATLENSURE_SUCCEEDED(connection->ReadDirectory(&pDirectory));
long count;
pDirectory->get_Count(&count);
_tprintf(_T("Count = %d\n"), count);
// Enum
if (count > 0)
{
ATL::CComPtr<IUnknown> unkEnum;
pDirectory->get__NewEnum(&unkEnum);
ATL::CComQIPtr<IEnumVARIANT> pEnum(unkEnum);
auto pArrVariant = new VARIANT[count];
ULONG CeltFetched;
if (SUCCEEDED(pEnum->Next(count, pArrVariant, &CeltFetched)))
{
for (ULONG i = 0; i < CeltFetched; i++)
{
if (pArrVariant[i].vt == VT_DISPATCH)
{
ATL::CComQIPtr<sfFTPLib::IFTPItem> pFTPItem{ pArrVariant[i].pdispVal };
sfFTPLib::ItemType itemType;
ATLENSURE_SUCCEEDED(pFTPItem->get_Type(&itemType));
ATL::CComBSTR itemName;
ATLENSURE_SUCCEEDED(pFTPItem->get_Name(&itemName));
ULONGLONG itemSize;
ATLENSURE_SUCCEEDED(pFTPItem->get_Size(&itemSize));
_tprintf(_T("Type=0x%x; Name=%s; Size=%I64u\n"), itemType, (LPCTSTR) itemName, itemSize);
if (itemType == sfFTPLib::ftpItemTypeSymbolicLink)
{
ATL::CComBSTR linkPoint;
pFTPItem->get_LinkPoint(&linkPoint);
_tprintf(_T("LinkPoint=%s"), (LPCTSTR) linkPoint);
}
}
::VariantClear(&pArrVariant[i]);
}
}
delete [] pArrVariant;
}
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// init COM
ATLENSURE_SUCCEEDED(::CoInitializeEx(NULL, COINIT_MULTITHREADED));
ATL::CComPtr<sfFTPLib::IGlobal> global;
ATLENSURE_SUCCEEDED(global.CoCreateInstance(__uuidof(sfFTPLib::Global)));
// If LoadLicense is not called a trial license is automatically obtained from the activation server. The FTP Library uses WinHTTP to access
// the activation server at www.smartftp.com (TLS, port 443). Ensure that your application is not blocked by any firewall.
// TODO: insert the provided serial after the purchase of a license
//global->LoadLicense(_T("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"));
ATL::CComPtr<sfFTPLib::IFTPConnection> ftp;
ATLENSURE_SUCCEEDED(ftp.CoCreateInstance(__uuidof(sfFTPLib::FTPConnectionMTA)));
ATL::CComPtr<sfFTPLib::IFileLogger> fileLogger;
ATLENSURE_SUCCEEDED(fileLogger.CoCreateInstance(__uuidof(sfFTPLib::FileLogger)));
ATLENSURE_SUCCEEDED(fileLogger->put_File(ATL::CComBSTR(L"Win32Demo.log")));
ATL::CComQIPtr<sfFTPLib::ILogger> logger(fileLogger);
ATLENSURE_SUCCEEDED(ftp->put_Logger(logger));
// AUTH TLS
ATLENSURE_SUCCEEDED(ftp->put_Protocol(sfFTPLib::ftpProtocolSSLExplicit));
ATLENSURE_SUCCEEDED(ftp->put_Host(ATL::CComBSTR(_T("smartftp.com"))));
ATLENSURE_SUCCEEDED(ftp->put_Port(21));
ATLENSURE_SUCCEEDED(ftp->put_Username(ATL::CComBSTR(_T("anonymous"))));
ATLENSURE_SUCCEEDED(ftp->put_Password(ATL::CComBSTR(_T("bla@bla.com"))));
ATLENSURE_SUCCEEDED(ftp->put_Passive(VARIANT_TRUE));
// No Proxy
// ATL::CComPtr<IProxy> proxy;
// ATLENSURE_SUCCEEDED(ftp->get_Proxy(&proxy));
//proxy->put_Type(sfFTPLib::ftpProxyTypeNone);
//proxy->put_Host(ATL::CComBSTR(_T("192.168.1.10"));
//proxy->put_Port(1080;
//proxy->put_Authentication(VARIANT_TRUE);
//proxy->put_Username(ATL::CComBSTR(_T("user"));
//proxy->put_Password(ATL::CComBSTR(_T("pass"));
ATLENSURE_SUCCEEDED(ftp->Connect());
ReadDirectory(ftp, ATL::CComBSTR(L"/"));
// download file
ATLENSURE_SUCCEEDED(ftp->DownloadFile(ATL::CComBSTR(L"History.txt"), ATL::CComBSTR(L"History.txt"), 0, 0));
_tprintf(_T("DownloadFile() successful.\n"));
ULONGLONG lastTransferBytes;
ATLENSURE_SUCCEEDED(ftp->get_LastTransferBytes(&lastTransferBytes));
_tprintf(_T("LastTransferBytes = %I64u B\n"), lastTransferBytes);
long lastTransferTime;
ATLENSURE_SUCCEEDED(ftp->get_LastTransferTime(&lastTransferTime));
_tprintf(_T("LastTransferTime = %d s\n"), lastTransferTime);
long lastTransferSpeed;
ATLENSURE_SUCCEEDED(ftp->get_LastTransferSpeed(&lastTransferSpeed));
_tprintf(_T("LastTransferSpeed = %d B/s\n"), lastTransferSpeed);
// DownloadFileEx using IStream
//DownloadUsingStream(ftp);
::CoUninitialize();
return nRetCode;
}