FTPClientSession read welcome message with external socket (#2335)

* FTPClientSession read welcome message with external socket

Add method to configure if the FTPClientSession should read welcome message from FTP server when you use external socket. Otherwise you could end up in a desyncronization of FTP commands

* FTPSClientSession constructor FTPS behavior

Add variable in constructor to let you enable or disable FTPS connection

* Get FTPSClientSession back from master

* Support UTF8 filename

Using UTF8 filename cause image loading funtion fail without a transcoding function

* FTP Add function to get welcome message

Add a function to get at application level the FTP Server welcome message

* removed FTPPasswordProvider from FTPSStreamFactory

Removed duplicate FTPPasswordProvider  class from FTPSStreamFactory

* Code Style corrections

No hungarian style
no indent nested namespace
rename mutex
This commit is contained in:
micheleselea
2018-07-10 15:58:16 +02:00
committed by Aleksandar Fabijanic
parent 3f1f6fa8e6
commit 9887e78b5e
9 changed files with 152 additions and 123 deletions

View File

@@ -63,7 +63,7 @@ public:
///
/// Passive mode will be used for data transfers.
explicit FTPClientSession(const StreamSocket& socket);
explicit FTPClientSession(const StreamSocket& socket, bool readWelcomeMessage = true);
/// Creates an FTPClientSession using the given
/// connected socket for the control connection.
///
@@ -305,6 +305,9 @@ public:
bool isSecure() const;
/// Returns true if the session is FTPS.
const std::string& welcomeMessage();
/// Returns welcome message.
protected:
virtual void receiveServerReadyReply();
/// Function that read server welcome message after connetion
@@ -355,6 +358,8 @@ private:
bool _serverReady = false;
bool _isLoggedIn = false;
Poco::Timespan _timeout = DEFAULT_TIMEOUT;
std::string _welcomeMessage;
Poco::FastMutex _wmMutex;
};
@@ -407,6 +412,12 @@ inline bool FTPClientSession::isSecure() const
return false;
}
inline const std::string& FTPClientSession::welcomeMessage()
{
Poco::FastMutex::ScopedLock lock(_wmMutex);
return _welcomeMessage;
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,46 @@
//
// FTPPasswordProvider.h
//
// Library: Net
// Package: FTP
// Module: FTPPasswordProvider
//
// Definition of the FTPPasswordProvider class.
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Net_FTPPasswordProvider_INCLUDED
#define Net_FTPPasswordProvider_INCLUDED
#include <string>
namespace Poco {
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 FTPPasswordProvider to
/// provide a password
{
public:
virtual std::string password(const std::string& username, const std::string& host) = 0;
/// Provide the password for the given user on the given host.
protected:
FTPPasswordProvider();
virtual ~FTPPasswordProvider();
};
} } // namespace Poco::Net
#endif // Net_FTPPasswordProvider_INCLUDED

View File

@@ -21,28 +21,12 @@
#include "Poco/Net/Net.h"
#include "Poco/Net/HTTPSession.h"
#include "Poco/URIStreamFactory.h"
#include "Poco/Net/FTPPasswordProvider.h"
namespace Poco {
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
{
public:
virtual std::string password(const std::string& username, const std::string& host) = 0;
/// Provide the password for the given user on the given host.
protected:
FTPPasswordProvider();
virtual ~FTPPasswordProvider();
};
class Net_API FTPStreamFactory: public Poco::URIStreamFactory
/// An implementation of the URIStreamFactory interface
/// that handles File Transfer Protocol (ftp) URIs.

View File

@@ -42,7 +42,7 @@ FTPClientSession::FTPClientSession():
}
FTPClientSession::FTPClientSession(const StreamSocket& socket):
FTPClientSession::FTPClientSession(const StreamSocket& socket, bool readWelcomeMessage):
_pControlSocket(new DialogSocket(socket)),
_pDataStream(0),
_host(socket.address().host().toString()),
@@ -55,6 +55,14 @@ FTPClientSession::FTPClientSession(const StreamSocket& socket):
_timeout(DEFAULT_TIMEOUT)
{
_pControlSocket->setReceiveTimeout(_timeout);
if (readWelcomeMessage)
{
receiveServerReadyReply();
}
else
{
_serverReady = true;
}
}
@@ -150,6 +158,10 @@ void FTPClientSession::receiveServerReadyReply()
if (!isPositiveCompletion(status))
throw FTPException("Cannot receive status message", response, status);
{
Poco::FastMutex::ScopedLock lock(_wmMutex);
_welcomeMessage = response;
}
_serverReady = true;
}

View File

@@ -23,19 +23,19 @@
namespace Poco {
namespace Net {
namespace Net {
class NetSSL_API FTPSClientSession :
class NetSSL_API FTPSClientSession :
public Poco::Net::FTPClientSession
{
public:
{
public:
FTPSClientSession();
/// Creates an FTPSClientSession.
///
/// Passive mode will be used for data transfers.
explicit FTPSClientSession(const StreamSocket& socket);
explicit FTPSClientSession(const StreamSocket& socket, bool readWelcomeMessage = true, bool tryUseFTPS = true);
/// Creates an FTPSClientSession using the given
/// connected socket for the control connection.
///
@@ -59,15 +59,15 @@ public:
bool isSecure() const;
/// Returns true if the session is FTPS.
protected:
protected:
virtual StreamSocket establishDataConnection(const std::string& command, const std::string& arg);
/// Create secure data connection
virtual void receiveServerReadyReply();
/// Function that read server welcome message after connetion and set and make secure socket
private:
bool _bTryFTPS = true;
private:
bool _tryFTPS = true;
void beforeCreateDataSocket();
///Send commands to check if we can encrypt data socket
@@ -75,23 +75,24 @@ private:
void afterCreateControlSocket();
///Send commands to make SSL negotiating of control channel
bool _bSecureDataConnection = false;
};
bool _secureDataConnection = false;
};
//
// inlines
//
//
// inlines
//
inline bool FTPSClientSession::isSecure() const
{
inline bool FTPSClientSession::isSecure() const
{
if (_pControlSocket != nullptr)
return _pControlSocket->secure();
return false;
}
}
}} // namespace Poco::Net
}
} // namespace Poco::Net
#endif // #define NetSSL_FTPSClientSession_INCLUDED

View File

@@ -21,28 +21,13 @@
#include "Poco/Net/NetSSL.h"
#include "Poco/Net/HTTPSession.h"
#include "Poco/URIStreamFactory.h"
#include "Poco/Net/FTPStreamFactory.h"
#include "Poco/Net/FTPPasswordProvider.h"
namespace Poco {
namespace Net {
class NetSSL_API FTPPasswordProvider
/// The base class for all password providers.
/// An instance of a subclass of this class can be
/// registered with the FTPSStreamFactory to
/// provide a password
{
public:
virtual std::string password(const std::string& username, const std::string& host) = 0;
/// Provide the password for the given user on the given host.
protected:
FTPPasswordProvider();
virtual ~FTPPasswordProvider();
};
class NetSSL_API FTPSStreamFactory: public Poco::URIStreamFactory
/// An implementation of the URIStreamFactory interface
/// that handles File Transfer Protocol (ftp) URIs.

View File

@@ -31,8 +31,8 @@ FTPSClientSession::~FTPSClientSession()
{
}
FTPSClientSession::FTPSClientSession(const StreamSocket& socket) :
FTPClientSession(socket)
FTPSClientSession::FTPSClientSession(const StreamSocket& socket, bool readWelcomeMessage, bool tryUseFTPS) :
FTPClientSession(socket, readWelcomeMessage), _tryFTPS(tryUseFTPS)
{
}
@@ -47,14 +47,14 @@ FTPSClientSession::FTPSClientSession(const std::string& host,
void FTPSClientSession::tryFTPSmode(bool bTryFTPS)
{
_bTryFTPS = bTryFTPS;
_tryFTPS = bTryFTPS;
}
void FTPSClientSession::beforeCreateDataSocket()
{
if (_bSecureDataConnection)
if (_secureDataConnection)
return;
_bSecureDataConnection = false;
_secureDataConnection = false;
if (!_pControlSocket->secure())
return;
std::string sResponse;
@@ -63,13 +63,13 @@ void FTPSClientSession::beforeCreateDataSocket()
{
status = sendCommand("PROT P", sResponse);
if (isPositiveCompletion(status))
_bSecureDataConnection = true;
_secureDataConnection = true;
}
}
void FTPSClientSession::afterCreateControlSocket()
{
if (!_bTryFTPS)
if (!_tryFTPS)
return;
_pControlSocket->setNoDelay(true);
if (_pControlSocket->secure())
@@ -95,7 +95,7 @@ void FTPSClientSession::afterCreateControlSocket()
}
else
{
_bTryFTPS = false;
_tryFTPS = false;
}
}
@@ -107,7 +107,7 @@ StreamSocket FTPSClientSession::establishDataConnection(const std::string& comma
ss.setNoDelay(true);
//SSL nogotiating of data socket
if ((_bSecureDataConnection) && (_pControlSocket->secure()))
if ((_secureDataConnection) && (_pControlSocket->secure()))
{
//We need to reuse the control socket SSL session so the server can ensure that client that opened control socket is the same using data socket
Poco::Net::SecureStreamSocketImpl* pSecure = dynamic_cast<Poco::Net::SecureStreamSocketImpl*>(_pControlSocket->impl());
@@ -126,4 +126,5 @@ void FTPSClientSession::receiveServerReadyReply()
afterCreateControlSocket();
}
}} // namespace Poco::Net
}
} // namespace Poco::Net

View File

@@ -99,20 +99,9 @@ private:
};
FTPPasswordProvider::FTPPasswordProvider()
{
}
FTPPasswordProvider::~FTPPasswordProvider()
{
}
std::string FTPSStreamFactory::_anonymousPassword("poco@localhost");
FTPPasswordProvider* FTPSStreamFactory::_pPasswordProvider(0);
FTPSStreamFactory::FTPSStreamFactory()
{
}

View File

@@ -195,12 +195,12 @@ const Image& Document::loadPNGImageImpl(const std::string& fileName, bool doLoad
std::pair<ImageContainer::iterator, bool> it;
if (doLoad)
{
Image image(&_pdf, HPDF_LoadPngImageFromFile(_pdf, fileName.c_str()));
Image image(&_pdf, HPDF_LoadPngImageFromFile(_pdf, Poco::Path::transcode(fileName).c_str()));
it = _images.insert(ImageContainer::value_type(path.getBaseName(), image));
}
else
{
Image image(&_pdf, HPDF_LoadPngImageFromFile2(_pdf, fileName.c_str()));
Image image(&_pdf, HPDF_LoadPngImageFromFile2(_pdf, Poco::Path::transcode(fileName).c_str()));
it = _images.insert(ImageContainer::value_type(path.getBaseName(), image));
}
if (it.second) return it.first->second;
@@ -216,7 +216,7 @@ const Image& Document::loadBMPImageImpl(const std::string& fileName, bool /*doLo
if (File(path).exists())
{
Image image(&_pdf, LoadBMPImageFromFile(_pdf, fileName.c_str()));
Image image(&_pdf, LoadBMPImageFromFile(_pdf, Poco::Path::transcode(fileName).c_str()));
std::pair<ImageContainer::iterator, bool> it =
_images.insert(ImageContainer::value_type(path.getBaseName(), image));
if (it.second) return it.first->second;
@@ -233,7 +233,7 @@ const Image& Document::loadJPEGImage(const std::string& fileName)
if (File(path).exists())
{
Image image(&_pdf, HPDF_LoadJpegImageFromFile(_pdf, fileName.c_str()));
Image image(&_pdf, HPDF_LoadJpegImageFromFile(_pdf, Poco::Path::transcode(fileName).c_str()));
std::pair<ImageContainer::iterator, bool> it =
_images.insert(ImageContainer::value_type(path.getBaseName(), image));
if (it.second) return it.first->second;