mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-20 14:02:38 +02:00
fixes and improvements to FTP(S)ClientSession
This commit is contained in:
@@ -54,8 +54,8 @@ public:
|
||||
|
||||
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();
|
||||
@@ -63,16 +63,13 @@ public:
|
||||
///
|
||||
/// 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.
|
||||
@@ -99,10 +96,7 @@ public:
|
||||
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,6 +111,9 @@ 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.
|
||||
@@ -306,11 +303,10 @@ public:
|
||||
/// 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,6 +316,7 @@ protected:
|
||||
FTP_TRANSIENT_NEGATIVE = 4,
|
||||
FTP_PERMANENT_NEGATIVE = 5
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
DEFAULT_TIMEOUT = 30000000 // 30 seconds default timeout for socket operations
|
||||
@@ -352,7 +349,7 @@ private:
|
||||
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;
|
||||
|
@@ -31,7 +31,7 @@ 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
|
||||
/// 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();
|
||||
|
@@ -31,7 +31,7 @@ namespace Net {
|
||||
FTPClientSession::FTPClientSession():
|
||||
_pControlSocket(0),
|
||||
_pDataStream(0),
|
||||
_port(0),
|
||||
_port(FTP_PORT),
|
||||
_passiveMode(true),
|
||||
_fileType(TYPE_BINARY),
|
||||
_supports1738(true),
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
};
|
||||
|
74
NetSSL_OpenSSL/include/Poco/Net/FTPSStreamFactory.h
Normal file
74
NetSSL_OpenSSL/include/Poco/Net/FTPSStreamFactory.h
Normal file
@@ -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=<typecode>), where <typecode> 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
|
@@ -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)
|
||||
{
|
||||
|
@@ -35,9 +35,9 @@ FTPSClientSession::FTPSClientSession(Context::Ptr pContext):
|
||||
{
|
||||
}
|
||||
|
||||
FTPSClientSession::FTPSClientSession(const StreamSocket& socket, bool readWelcomeMessage, bool tryUseFTPS, Context::Ptr pContext):
|
||||
FTPSClientSession::FTPSClientSession(const StreamSocket& socket, bool readWelcomeMessage, bool enableFTPS, Context::Ptr pContext):
|
||||
FTPClientSession(socket, readWelcomeMessage),
|
||||
_tryFTPS(tryUseFTPS),
|
||||
_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;
|
||||
}
|
||||
}
|
||||
|
||||
|
161
NetSSL_OpenSSL/src/FTPSStreamFactory.cpp
Normal file
161
NetSSL_OpenSSL/src/FTPSStreamFactory.cpp
Normal file
@@ -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
|
@@ -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());
|
||||
|
Reference in New Issue
Block a user