diff --git a/Net/include/Poco/Net/FTPClientSession.h b/Net/include/Poco/Net/FTPClientSession.h index 8247ba885..1e817a784 100644 --- a/Net/include/Poco/Net/FTPClientSession.h +++ b/Net/include/Poco/Net/FTPClientSession.h @@ -51,40 +51,37 @@ public: { FTP_PORT = 21 }; - + enum FileType { - TYPE_TEXT, // TYPE A (ASCII) - TYPE_BINARY // TYPE I (Image) + TYPE_TEXT, /// TYPE A (ASCII) + TYPE_BINARY /// TYPE I (Image/binary data) }; - + FTPClientSession(); /// Creates an FTPClientSession. /// /// Passive mode will be used for data transfers. - explicit FTPClientSession(const StreamSocket& socket, bool readWelcomeMessage = true); + FTPClientSession(const StreamSocket& socket, bool readWelcomeMessage = true); /// Creates an FTPClientSession using the given /// connected socket for the control connection. /// /// Passive mode will be used for data transfers. - - FTPClientSession(const std::string& host, - Poco::UInt16 port = FTP_PORT, - const std::string& username = "", - const std::string& password = ""); + + FTPClientSession(const std::string& host, Poco::UInt16 port = FTP_PORT, const std::string& username = "", const std::string& password = ""); /// Creates an FTPClientSession using a socket connected /// to the given host and port. If username is supplied, /// login is attempted. /// /// Passive mode will be used for data transfers. - + virtual ~FTPClientSession(); /// Destroys the FTPClientSession. - + void setTimeout(const Poco::Timespan& timeout); /// Sets the timeout for socket operations. - + Poco::Timespan getTimeout() const; /// Returns the timeout for socket operations. @@ -95,14 +92,11 @@ public: /// EPSV command is used (with a fallback to PASV if EPSV fails) /// for switching to passive mode. The same applies to /// EPRT and PORT for active connections. - + bool getPassive() const; /// Returns true iff passive mode is enabled for this connection. - - virtual void open(const std::string& host, - Poco::UInt16 port, - const std::string& username = "", - const std::string& password = ""); + + virtual void open(const std::string& host, Poco::UInt16 port, const std::string& username = "", const std::string& password = ""); /// Opens the FTP connection to the given host and port. /// If username is supplied, login is attempted. @@ -117,18 +111,21 @@ public: /// NetException in case of a general network communication failure. void logout(); + /// Logs out from the server by sending a QUIT command. Any transfer + /// that's in progress is ended. The control connection is kept + /// open. void close(); /// Sends a QUIT command and closes the connection to the server. /// /// Throws a FTPException in case of a FTP-specific error, or a /// NetException in case of a general network communication failure. - + std::string systemType(); /// Returns the system type of the FTP server. /// /// Sends a SYST command to the server and returns the result. - + void setFileType(FileType type); /// Sets the file type for transferring files. /// @@ -144,7 +141,7 @@ public: void setWorkingDirectory(const std::string& path); /// Changes the current working directory on the server. /// - /// Sends a CWD command with the given path as argument to the + /// Sends a CWD command with the given path as argument to the /// server. /// /// Throws a FTPException in case of a FTP-specific error, or a @@ -155,7 +152,7 @@ public: /// /// Throws a FTPException in case of a FTP-specific error, or a /// NetException in case of a general network communication failure. - + void cdup(); /// Moves one directory up from the current working directory /// on the server. @@ -164,7 +161,7 @@ public: /// /// Throws a FTPException in case of a FTP-specific error, or a /// NetException in case of a general network communication failure. - + void rename(const std::string& oldName, const std::string& newName); /// Renames the file on the server given by oldName to newName. /// @@ -172,7 +169,7 @@ public: /// /// Throws a FTPException in case of a FTP-specific error, or a /// NetException in case of a general network communication failure. - + void remove(const std::string& path); /// Deletes the file specified by path on the server. /// @@ -217,11 +214,11 @@ public: /// the native text file format. /// The InputLineEndingConverter class from the Foundation /// library can be used for that purpose. - + void endDownload(); /// Must be called to complete a download initiated with /// beginDownload(). - + std::ostream& beginUpload(const std::string& path); /// Starts uploading the file with the given name. /// After all data has been written to the returned stream, @@ -274,9 +271,9 @@ public: /// client waits for a connection request from the server. /// After establishing the data connection, a SocketStream /// for transferring the data is created. - + void endList(); - /// Must be called to complete a directory listing download + /// Must be called to complete a directory listing download /// initiated with beginList(). void abort(); @@ -287,7 +284,7 @@ public: /// /// A separate call to endDownload() or endUpload() is /// not necessary. - + int sendCommand(const std::string& command, std::string& response); /// Sends the given command verbatim to the server /// and waits for a response. @@ -304,13 +301,12 @@ public: bool isSecure() const; /// Returns true if the session is FTPS. - + const std::string& welcomeMessage(); - /// Returns welcome message. - + /// Returns the welcome message. + protected: virtual void receiveServerReadyReply(); - /// Function that read server welcome message after connetion enum StatusClass { @@ -320,9 +316,10 @@ protected: FTP_TRANSIENT_NEGATIVE = 4, FTP_PERMANENT_NEGATIVE = 5 }; + enum { - DEFAULT_TIMEOUT = 30000000 // 30 seconds default timeout for socket operations + DEFAULT_TIMEOUT = 30000000 // 30 seconds default timeout for socket operations }; static bool isPositivePreliminary(int status); @@ -343,16 +340,16 @@ protected: void parseAddress(const std::string& str, SocketAddress& addr); void parseExtAddress(const std::string& str, SocketAddress& addr); void endTransfer(); - + DialogSocket* _pControlSocket = nullptr; SocketStream* _pDataStream = nullptr; private: FTPClientSession(const FTPClientSession&); FTPClientSession& operator = (const FTPClientSession&); - + std::string _host; - Poco::UInt16 _port = 0; + Poco::UInt16 _port = FTP_PORT; bool _passiveMode = true; FileType _fileType = TYPE_BINARY; bool _supports1738 = true; @@ -360,7 +357,7 @@ private: bool _isLoggedIn = false; Poco::Timespan _timeout = DEFAULT_TIMEOUT; std::string _welcomeMessage; - Poco::FastMutex _wmMutex; + Poco::FastMutex _wmMutex; }; diff --git a/Net/include/Poco/Net/FTPStreamFactory.h b/Net/include/Poco/Net/FTPStreamFactory.h index 4f33f19c1..992cc4f51 100644 --- a/Net/include/Poco/Net/FTPStreamFactory.h +++ b/Net/include/Poco/Net/FTPStreamFactory.h @@ -30,8 +30,8 @@ namespace Net { class Net_API FTPPasswordProvider /// The base class for all password providers. /// An instance of a subclass of this class can be - /// registered with the FTPStreamFactory to - /// provide a password + /// registered with the FTPStreamFactory to + /// provide a password. { public: virtual std::string password(const std::string& username, const std::string& host) = 0; @@ -56,7 +56,7 @@ class Net_API FTPStreamFactory: public Poco::URIStreamFactory /// the FTP URL format specified in RFC 1738. /// /// If the URI does not contain a username and password, the - /// username "anonymous" and the password " + /// username "anonymous" and the password "poco@localhost". { public: FTPStreamFactory(); @@ -64,13 +64,13 @@ public: ~FTPStreamFactory(); /// Destroys the FTPStreamFactory. - + std::istream* open(const Poco::URI& uri); /// Creates and opens a HTTP stream for the given URI. /// The URI must be a ftp://... URI. /// /// Throws a NetException if anything goes wrong. - + static void setAnonymousPassword(const std::string& password); /// Sets the password used for anonymous FTP. /// @@ -78,10 +78,10 @@ public: /// thread-safe, so it's best to call this method /// during application initialization, before the /// FTPStreamFactory is used for the first time. - + static const std::string& getAnonymousPassword(); /// Returns the password used for anonymous FTP. - + static void setPasswordProvider(FTPPasswordProvider* pProvider); /// Sets the FTPPasswordProvider. If NULL is given, /// no password provider is used. @@ -90,7 +90,7 @@ public: /// thread-safe, so it's best to call this method /// during application initialization, before the /// FTPStreamFactory is used for the first time. - + static FTPPasswordProvider* getPasswordProvider(); /// Returns the FTPPasswordProvider currently in use, /// or NULL if no one has been set. @@ -107,7 +107,7 @@ protected: static void splitUserInfo(const std::string& userInfo, std::string& username, std::string& password); static void getUserInfo(const Poco::URI& uri, std::string& username, std::string& password); static void getPathAndType(const Poco::URI& uri, std::string& path, char& type); - + private: static std::string _anonymousPassword; static FTPPasswordProvider* _pPasswordProvider; diff --git a/Net/src/FTPClientSession.cpp b/Net/src/FTPClientSession.cpp index 41a5eee80..edc3c4daa 100644 --- a/Net/src/FTPClientSession.cpp +++ b/Net/src/FTPClientSession.cpp @@ -31,7 +31,7 @@ namespace Net { FTPClientSession::FTPClientSession(): _pControlSocket(0), _pDataStream(0), - _port(0), + _port(FTP_PORT), _passiveMode(true), _fileType(TYPE_BINARY), _supports1738(true), @@ -41,7 +41,7 @@ FTPClientSession::FTPClientSession(): { } - + FTPClientSession::FTPClientSession(const StreamSocket& socket, bool readWelcomeMessage): _pControlSocket(new DialogSocket(socket)), _pDataStream(0), @@ -55,14 +55,14 @@ FTPClientSession::FTPClientSession(const StreamSocket& socket, bool readWelcomeM _timeout(DEFAULT_TIMEOUT) { _pControlSocket->setReceiveTimeout(_timeout); - if (readWelcomeMessage) + if (readWelcomeMessage) { receiveServerReadyReply(); } - else + else { _serverReady = true; - } + } } @@ -93,7 +93,7 @@ FTPClientSession::~FTPClientSession() { close(); } - catch (...) + catch (...) { } } @@ -108,7 +108,7 @@ void FTPClientSession::setTimeout(const Poco::Timespan& timeout) _pControlSocket->setReceiveTimeout(timeout); } - + Poco::Timespan FTPClientSession::getTimeout() const { return _timeout; @@ -121,7 +121,7 @@ void FTPClientSession::setPassive(bool flag, bool useRFC1738) _supports1738 = useRFC1738; } - + bool FTPClientSession::getPassive() const { return _passiveMode; @@ -183,7 +183,7 @@ void FTPClientSession::login(const std::string& username, const std::string& pas status = sendCommand("USER", username, response); if (isPositiveIntermediate(status)) status = sendCommand("PASS", password, response); - if (!isPositiveCompletion(status)) + if (!isPositiveCompletion(status)) throw FTPException("Login denied", response, status); setFileType(_fileType); @@ -198,12 +198,12 @@ void FTPClientSession::logout() if (_isLoggedIn) { - try - { - endTransfer(); + try + { + endTransfer(); } - catch (...) - { + catch (...) + { } _isLoggedIn = false; std::string response; @@ -214,11 +214,11 @@ void FTPClientSession::logout() void FTPClientSession::close() { - try - { - logout(); + try + { + logout(); } - catch (...) + catch (...) { } _serverReady = false; @@ -285,24 +285,24 @@ void FTPClientSession::cdup() throw FTPException("Cannot change directory", response, status); } - + void FTPClientSession::rename(const std::string& oldName, const std::string& newName) { std::string response; int status = sendCommand("RNFR", oldName, response); - if (!isPositiveIntermediate(status)) + if (!isPositiveIntermediate(status)) throw FTPException(std::string("Cannot rename ") + oldName, response, status); status = sendCommand("RNTO", newName, response); - if (!isPositiveCompletion(status)) + if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot rename to ") + newName, response, status); } - + void FTPClientSession::remove(const std::string& path) { std::string response; int status = sendCommand("DELE", path, response); - if (!isPositiveCompletion(status)) + if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot remove " + path), response, status); } @@ -311,7 +311,7 @@ void FTPClientSession::createDirectory(const std::string& path) { std::string response; int status = sendCommand("MKD", path, response); - if (!isPositiveCompletion(status)) + if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot create directory ") + path, response, status); } @@ -320,7 +320,7 @@ void FTPClientSession::removeDirectory(const std::string& path) { std::string response; int status = sendCommand("RMD", path, response); - if (!isPositiveCompletion(status)) + if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot remove directory ") + path, response, status); } @@ -336,13 +336,13 @@ std::istream& FTPClientSession::beginDownload(const std::string& path) return *_pDataStream; } - + void FTPClientSession::endDownload() { endTransfer(); } - + std::ostream& FTPClientSession::beginUpload(const std::string& path) { if (!isOpen()) @@ -378,7 +378,7 @@ void FTPClientSession::endList() endTransfer(); } - + void FTPClientSession::abort() { if (!isOpen()) @@ -390,7 +390,7 @@ void FTPClientSession::abort() int status = sendCommand("ABOR", response); if (status == 426) status = _pControlSocket->receiveStatusMessage(response); - if (status != 226) + if (status != 226) throw FTPException("Cannot abort transfer", response, status); } @@ -456,7 +456,7 @@ StreamSocket FTPClientSession::activeDataConnection(const std::string& command, sendPortCommand(server.address()); std::string response; int status = sendCommand(command, arg, response); - if (!isPositivePreliminary(status)) + if (!isPositivePreliminary(status)) throw FTPException(command + " command failed", response, status); if (server.poll(_timeout, Socket::SELECT_READ)) return server.acceptConnection(); @@ -474,7 +474,7 @@ StreamSocket FTPClientSession::passiveDataConnection(const std::string& command, sock.setSendTimeout(_timeout); std::string response; int status = sendCommand(command, arg, response); - if (!isPositivePreliminary(status)) + if (!isPositivePreliminary(status)) throw FTPException(command + " command failed", response, status); return sock; } @@ -542,7 +542,7 @@ void FTPClientSession::sendPORT(const SocketAddress& addr) arg += NumberFormatter::format(port % 256); std::string response; int status = sendCommand("PORT", arg, response); - if (!isPositiveCompletion(status)) + if (!isPositiveCompletion(status)) throw FTPException("PORT command failed", response, status); } @@ -568,7 +568,7 @@ void FTPClientSession::sendPASV(SocketAddress& addr) { std::string response; int status = sendCommand("PASV", response); - if (!isPositiveCompletion(status)) + if (!isPositiveCompletion(status)) throw FTPException("PASV command failed", response, status); parseAddress(response, addr); } @@ -609,8 +609,8 @@ void FTPClientSession::parseExtAddress(const std::string& str, SocketAddress& ad if (it != end && *it == delim) ++it; if (it != end && *it == delim) ++it; Poco::UInt16 port = 0; - while (it != end && Poco::Ascii::isDigit(*it)) { port *= 10; port += *it++ - '0'; } - addr = SocketAddress(_pControlSocket->peerAddress().host(), port); + while (it != end && Poco::Ascii::isDigit(*it)) { port *= 10; port += *it++ - '0'; } + addr = SocketAddress(_pControlSocket->peerAddress().host(), port); } @@ -622,7 +622,7 @@ void FTPClientSession::endTransfer() _pDataStream = 0; std::string response; int status = _pControlSocket->receiveStatusMessage(response); - if (!isPositiveCompletion(status)) + if (!isPositiveCompletion(status)) throw FTPException("Data transfer failed", response, status); } } diff --git a/NetSSL_OpenSSL/Makefile b/NetSSL_OpenSSL/Makefile index 137e7926a..8fd4537ba 100644 --- a/NetSSL_OpenSSL/Makefile +++ b/NetSSL_OpenSSL/Makefile @@ -17,7 +17,7 @@ objects = AcceptCertificateHandler RejectCertificateHandler ConsoleCertificateHa SecureSocketImpl SecureStreamSocket SecureStreamSocketImpl \ SSLException SSLManager Utility VerificationErrorArgs \ X509Certificate Session SecureSMTPClientSession \ - FTPSClientSession + FTPSClientSession FTPSStreamFactory target = PocoNetSSL target_version = $(LIBVERSION) diff --git a/NetSSL_OpenSSL/include/Poco/Net/FTPSClientSession.h b/NetSSL_OpenSSL/include/Poco/Net/FTPSClientSession.h index f725dacf4..14650d9a6 100644 --- a/NetSSL_OpenSSL/include/Poco/Net/FTPSClientSession.h +++ b/NetSSL_OpenSSL/include/Poco/Net/FTPSClientSession.h @@ -28,6 +28,9 @@ namespace Net { class NetSSL_API FTPSClientSession: public Poco::Net::FTPClientSession + /// This is an extension of FTPClientSession that supports + /// FTP over SSL/TLS using the AUTH SSL/AUTH TLS and PBSZ/PROT + /// commands according to RFC 4217. { public: FTPSClientSession(); @@ -40,7 +43,7 @@ public: /// /// Passive mode will be used for data transfers. - explicit FTPSClientSession(const StreamSocket& socket, bool readWelcomeMessage = true, bool tryUseFTPS = true, Context::Ptr pContext = nullptr); + FTPSClientSession(const StreamSocket& socket, bool readWelcomeMessage = true, bool enableFTPS = true, Context::Ptr pContext = nullptr); /// Creates an FTPSClientSession using the given /// connected socket for the control connection. /// @@ -55,8 +58,8 @@ public: virtual ~FTPSClientSession(); - void tryFTPSmode(bool tryFTPS); - /// avoid or require TLS mode + void enableFTPS(bool enable = true); + /// Enable or disable FTPS (FTP over SSL/TLS). bool isSecure() const; /// Returns true if the session is FTPS. @@ -75,7 +78,7 @@ private: void afterCreateControlSocket(); ///Send commands to make SSL negotiating of control channel - bool _tryFTPS = true; + bool _enableFTPS = true; bool _secureDataConnection = false; Context::Ptr _pContext; }; diff --git a/NetSSL_OpenSSL/include/Poco/Net/FTPSStreamFactory.h b/NetSSL_OpenSSL/include/Poco/Net/FTPSStreamFactory.h new file mode 100644 index 000000000..d67c1571c --- /dev/null +++ b/NetSSL_OpenSSL/include/Poco/Net/FTPSStreamFactory.h @@ -0,0 +1,74 @@ +// +// FTPSStreamFactory.h +// +// Library: Net +// Package: FTP +// Module: FTPSStreamFactory +// +// Definition of the FTPSStreamFactory class. +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Net_FTPSStreamFactory_INCLUDED +#define Net_FTPSStreamFactory_INCLUDED + + +#include "Poco/Net/Net.h" +#include "Poco/Net/HTTPSession.h" +#include "Poco/Net/FTPStreamFactory.h" + + +namespace Poco { +namespace Net { + + +class Net_API FTPSStreamFactory: public Poco::Net::FTPStreamFactory + /// An implementation of the URIStreamFactory interface + /// that handles secure File Transfer Protocol (ftps) URIs + /// according to RFC 4217, based on the FTPSClientSession class. + /// + /// The URI's path may end with an optional type specification + /// in the form (;type=), where is + /// one of a, i or d. If type=a, the file identified by the path + /// is transferred in ASCII (text) mode. If type=i, the file + /// is transferred in Image (binary) mode. If type=d, a directory + /// listing (in NLST format) is returned. This corresponds with + /// the FTP URL format specified in RFC 1738. + /// + /// If the URI does not contain a username and password, the + /// username "anonymous" and the password "poco@localhost". + /// + /// Note that ftps is a non-standard URI scheme. +{ +public: + FTPSStreamFactory(); + /// Creates the FTPSStreamFactory. + + ~FTPSStreamFactory(); + /// Destroys the FTPSStreamFactory. + + std::istream* open(const Poco::URI& uri); + /// Creates and opens a HTTP stream for the given URI. + /// The URI must be a ftps://... URI. + /// + /// Throws a NetException if anything goes wrong. + + static void registerFactory(); + /// Registers the FTPSStreamFactory with the + /// default URIStreamOpener instance. + + static void unregisterFactory(); + /// Unregisters the FTPSStreamFactory with the + /// default URIStreamOpener instance. +}; + + +} } // namespace Poco::Net + + +#endif // Net_FTPSStreamFactory_INCLUDED diff --git a/NetSSL_OpenSSL/samples/download/src/download.cpp b/NetSSL_OpenSSL/samples/download/src/download.cpp index 99911c9bd..9f7b64075 100644 --- a/NetSSL_OpenSSL/samples/download/src/download.cpp +++ b/NetSSL_OpenSSL/samples/download/src/download.cpp @@ -19,6 +19,7 @@ #include "Poco/Net/HTTPStreamFactory.h" #include "Poco/Net/HTTPSStreamFactory.h" #include "Poco/Net/FTPStreamFactory.h" +#include "Poco/Net/FTPSStreamFactory.h" #include "Poco/Net/SSLManager.h" #include "Poco/Net/KeyConsoleHandler.h" #include "Poco/Net/ConsoleCertificateHandler.h" @@ -35,6 +36,7 @@ using Poco::Exception; using Poco::Net::HTTPStreamFactory; using Poco::Net::HTTPSStreamFactory; using Poco::Net::FTPStreamFactory; +using Poco::Net::FTPSStreamFactory; using Poco::Net::SSLManager; using Poco::Net::Context; using Poco::Net::KeyConsoleHandler; @@ -64,6 +66,7 @@ int main(int argc, char** argv) HTTPStreamFactory::registerFactory(); HTTPSStreamFactory::registerFactory(); FTPStreamFactory::registerFactory(); + FTPSStreamFactory::registerFactory(); if (argc != 2) { diff --git a/NetSSL_OpenSSL/src/FTPSClientSession.cpp b/NetSSL_OpenSSL/src/FTPSClientSession.cpp index 7e23eeab4..b2b895ecc 100644 --- a/NetSSL_OpenSSL/src/FTPSClientSession.cpp +++ b/NetSSL_OpenSSL/src/FTPSClientSession.cpp @@ -35,9 +35,9 @@ FTPSClientSession::FTPSClientSession(Context::Ptr pContext): { } -FTPSClientSession::FTPSClientSession(const StreamSocket& socket, bool readWelcomeMessage, bool tryUseFTPS, Context::Ptr pContext): - FTPClientSession(socket, readWelcomeMessage), - _tryFTPS(tryUseFTPS), +FTPSClientSession::FTPSClientSession(const StreamSocket& socket, bool readWelcomeMessage, bool enableFTPS, Context::Ptr pContext): + FTPClientSession(socket, readWelcomeMessage), + _enableFTPS(enableFTPS), _pContext(pContext) { } @@ -55,9 +55,9 @@ FTPSClientSession::~FTPSClientSession() } -void FTPSClientSession::tryFTPSmode(bool tryFTPS) +void FTPSClientSession::enableFTPS(bool enable) { - _tryFTPS = tryFTPS; + _enableFTPS = enable; } @@ -81,7 +81,7 @@ void FTPSClientSession::beforeCreateDataSocket() void FTPSClientSession::afterCreateControlSocket() { - if (!_tryFTPS) return; + if (!_enableFTPS) return; _pControlSocket->setNoDelay(true); if (_pControlSocket->secure()) return; @@ -106,7 +106,7 @@ void FTPSClientSession::afterCreateControlSocket() } else { - _tryFTPS = false; + _enableFTPS = false; } } diff --git a/NetSSL_OpenSSL/src/FTPSStreamFactory.cpp b/NetSSL_OpenSSL/src/FTPSStreamFactory.cpp new file mode 100644 index 000000000..b21af445c --- /dev/null +++ b/NetSSL_OpenSSL/src/FTPSStreamFactory.cpp @@ -0,0 +1,161 @@ +// +// FTPSStreamFactory.cpp +// +// Library: Net +// Package: FTP +// Module: FTPSStreamFactory +// +// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/Net/FTPSStreamFactory.h" +#include "Poco/Net/FTPSClientSession.h" +#include "Poco/Net/NetException.h" +#include "Poco/URI.h" +#include "Poco/URIStreamOpener.h" +#include "Poco/UnbufferedStreamBuf.h" +#include "Poco/Path.h" + + +using Poco::URIStreamFactory; +using Poco::URI; +using Poco::URIStreamOpener; +using Poco::UnbufferedStreamBuf; +using Poco::Path; + + +namespace Poco { +namespace Net { + + +class FTPSStreamBuf: public UnbufferedStreamBuf +{ +public: + FTPSStreamBuf(std::istream& istr): + _istr(istr) + { + // make sure exceptions from underlying string propagate + _istr.exceptions(std::ios::badbit); + } + + ~FTPSStreamBuf() + { + } + +private: + int readFromDevice() + { + return _istr.get(); + } + + std::istream& _istr; +}; + + +class FTPSIOS: public virtual std::ios +{ +public: + FTPSIOS(std::istream& istr): + _buf(istr) + { + poco_ios_init(&_buf); + } + + ~FTPSIOS() + { + } + + FTPSStreamBuf* rdbuf() + { + return &_buf; + } + +protected: + FTPSStreamBuf _buf; +}; + + +class FTPSStream: public FTPSIOS, public std::istream +{ +public: + FTPSStream(std::istream& istr, FTPSClientSession* pSession): + FTPSIOS(istr), + std::istream(&_buf), + _pSession(pSession) + { + } + + ~FTPSStream() + { + delete _pSession; + } + +private: + FTPSClientSession* _pSession; +}; + + +FTPSStreamFactory::FTPSStreamFactory() +{ +} + + +FTPSStreamFactory::~FTPSStreamFactory() +{ +} + + +std::istream* FTPSStreamFactory::open(const URI& uri) +{ + poco_assert (uri.getScheme() == "ftps"); + + Poco::UInt16 port = uri.getPort(); + if (port == 0) port = FTPClientSession::FTP_PORT; + FTPSClientSession* pSession = new FTPSClientSession(uri.getHost(), port); + try + { + std::string username; + std::string password; + getUserInfo(uri, username, password); + + std::string path; + char type; + getPathAndType(uri, path, type); + + pSession->login(username, password); + if (type == 'a') + pSession->setFileType(FTPClientSession::TYPE_TEXT); + + Path p(path, Path::PATH_UNIX); + p.makeFile(); + for (int i = 0; i < p.depth(); ++i) + pSession->setWorkingDirectory(p[i]); + std::string file(p.getFileName()); + std::istream& istr = (type == 'd' ? pSession->beginList(file) : pSession->beginDownload(file)); + return new FTPSStream(istr, pSession); + } + catch (...) + { + delete pSession; + throw; + } +} + + +void FTPSStreamFactory::registerFactory() +{ + URIStreamOpener::defaultOpener().registerStreamFactory("ftps", new FTPSStreamFactory); +} + + +void FTPSStreamFactory::unregisterFactory() +{ + URIStreamOpener::defaultOpener().unregisterStreamFactory("ftps"); +} + + +} } // namespace Poco::Net diff --git a/NetSSL_OpenSSL/testsuite/src/FTPSClientSessionTest.cpp b/NetSSL_OpenSSL/testsuite/src/FTPSClientSessionTest.cpp index 92c133afb..51f40ae5b 100644 --- a/NetSSL_OpenSSL/testsuite/src/FTPSClientSessionTest.cpp +++ b/NetSSL_OpenSSL/testsuite/src/FTPSClientSessionTest.cpp @@ -108,7 +108,7 @@ void FTPSClientSessionTest::testLogin1() server.clearCommands(); server.clearResponses(); - session.tryFTPSmode(true); + session.enableFTPS(true); login(server, session); assertTrue (session.isOpen()); assertTrue (session.isLoggedIn()); @@ -143,7 +143,7 @@ void FTPSClientSessionTest::testLogin2() server.addResponse("331 Password required"); server.addResponse("230 Welcome"); server.addResponse("200 Type set to I"); - session.tryFTPSmode(true); + session.enableFTPS(true); session.open("127.0.0.1", serverPort, "user", "password"); assertTrue (session.isOpen()); assertTrue (session.isLoggedIn());