ftp/Win32.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | // 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" #include <string_view> #include <memory> [[nodiscard]] ATL::CComSafeArray< byte > GetKey( const std::wstring_view password) { // TODO: Hash password (e.g. SHA1) and set data byte data[128 / 8]{}; ATL::CComSafeArray< byte > key; ATLENSURE_SUCCEEDED(key.Create( sizeof (data))); const auto begin{ reinterpret_cast< const byte *>(data) }; const 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; } // mode: 1 = Read, 2 = Write [[nodiscard]] ATL::CComPtr<sfFTPLib::IStreamFilter> CreateStreamFilter( const std::wstring_view password, int nBits, int mode) { ATL::CComPtr<sfFTPLib::IStreamFilter> stream; if (mode == 1) { ATL::CComPtr<sfFTPLib::IAES128CTRReadStream> readStream; ATLENSURE_SUCCEEDED(readStream.CoCreateInstance(__uuidof(sfFTPLib::AES128CTRReadStream))); ATLENSURE_SUCCEEDED(readStream->SetKey(const_cast< byte *>(reinterpret_cast< const byte *>(password.data())), password.size())); stream = readStream; } else if (mode == 2) { ATL::CComPtr<sfFTPLib::IAES128CTRWriteStream> writeStream; ATLENSURE_SUCCEEDED(writeStream.CoCreateInstance(__uuidof(sfFTPLib::AES128CTRWriteStream))); ATLENSURE_SUCCEEDED(writeStream->SetKey(const_cast< byte *>(reinterpret_cast< const byte *>(password.data())), password.size())); stream = writeStream; } return stream; } void DownloadUsingStream(_In_ sfFTPLib::IFTPConnection* connection) { // create a storage ATL::CComPtr<IStorage> storage; ATLENSURE_SUCCEEDED(::StgCreateDocfile(L "Storage" , STGM_NOSCRATCH | STGM_TRANSACTED | STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, &storage)); ATL::CComPtr<IStream> stream; ATLENSURE_SUCCEEDED(storage->CreateStream(L "CONTENTS" , STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stream)); ATLENSURE_SUCCEEDED(connection->DownloadFileEx(ATL::CComBSTR(L "This is a DEMO server.txt" ), ATL::CComVariant(stream.p), 0, MAXULONGLONG, nullptr)); ::wprintf(L "DownloadFileEx() successful.\n" ); stream->Commit(STGC_OVERWRITE | STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE); storage->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> directoryItems; ATLENSURE_SUCCEEDED(connection->ReadDirectory(&directoryItems)); long count; ATLENSURE_SUCCEEDED(directoryItems->get_Count(&count)); ::wprintf(L "Count = %d\n" , count); // Enum if (count > 0) { ATL::CComPtr<IUnknown> unkEnum; directoryItems->get__NewEnum(&unkEnum); ATL::CComQIPtr<IEnumVARIANT> pEnum(unkEnum); const auto pArrVariant{ std::make_unique<VARIANT[]>(count) }; ULONG fetched; if (SUCCEEDED(pEnum->Next(count, pArrVariant. get (), &fetched))) { for (ULONG i = 0; i < fetched; i++) { if (pArrVariant[i].vt == VT_DISPATCH) { ATL::CComQIPtr<sfFTPLib::IFTPItem> item{ pArrVariant[i].pdispVal }; sfFTPLib::ItemType itemType; ATLENSURE_SUCCEEDED(item->get_Type(&itemType)); ATL::CComBSTR itemName; ATLENSURE_SUCCEEDED(item->get_Name(&itemName)); ULONGLONG itemSize; ATLENSURE_SUCCEEDED(item->get_Size(&itemSize)); ::wprintf(L "Type=0x%x; Name=%s; Size=%I64u\n" , itemType, (PCWSTR) itemName, itemSize); if (itemType == sfFTPLib::ftpItemTypeSymbolicLink) { ATL::CComBSTR linkPoint; item->get_LinkPoint(&linkPoint); ::wprintf(L "LinkPoint=%s" , (PCWSTR) linkPoint); } } ::VariantClear(&pArrVariant[i]); } } } } int wmain( int argc, wchar_t* argv[], wchar_t* envp[]) { ATLENSURE_SUCCEEDED(::CoInitializeEx(nullptr, 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 //ATLENSURE_SUCCEEDED(global->LoadLicense(ATL::CComBSTR(L"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::ftpProtocolPreferTLS)); ATLENSURE_SUCCEEDED(ftp->put_Host(ATL::CComBSTR(L "smartftp.com" ))); ATLENSURE_SUCCEEDED(ftp->put_Port(21)); ATLENSURE_SUCCEEDED(ftp->put_Username(ATL::CComBSTR(L "anonymous" ))); ATLENSURE_SUCCEEDED(ftp->put_Password(ATL::CComBSTR(L "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(L"192.168.1.10"); //proxy->put_Port(1080; //proxy->put_Authentication(VARIANT_TRUE); //proxy->put_Username(ATL::CComBSTR(L"user"); //proxy->put_Password(ATL::CComBSTR(L"pass"); ATLENSURE_SUCCEEDED(ftp->Connect()); ReadDirectory(ftp, ATL::CComBSTR(L "/" )); // download file ATLENSURE_SUCCEEDED(ftp->DownloadFileEx(ATL::CComBSTR(L "This is a DEMO server.txt" ), ATL::CComVariant(L "This is a DEMO server.txt" ), 0, MAXULONGLONG, nullptr)); ::wprintf(L "DownloadFile() successful.\n" ); ULONGLONG lastTransferBytes; ATLENSURE_SUCCEEDED(ftp->get_LastTransferBytes(&lastTransferBytes)); ::wprintf(L "LastTransferBytes = %I64u B\n" , lastTransferBytes); long lastTransferTime; ATLENSURE_SUCCEEDED(ftp->get_LastTransferTime(&lastTransferTime)); ::wprintf(L "LastTransferTime = %d s\n" , lastTransferTime); long lastTransferSpeed; ATLENSURE_SUCCEEDED(ftp->get_LastTransferSpeed(&lastTransferSpeed)); ::wprintf(L "LastTransferSpeed = %d B/s\n" , lastTransferSpeed); // DownloadFileEx using IStream //DownloadUsingStream(ftp); // Upload file //ATLENSURE_SUCCEEDED(ftp->UploadFileEx(ATL::CComVariant(L"c:\\test.dat"), ATL::CComBSTR(L"test.dat"), 0, nullptr)); ::CoUninitialize(); return 0; } |