Permalink
Browse files

Merge remote-tracking branch 'origin/FTPClientSession' into develop

  • Loading branch information...
2 parents 560908b + 98c3709 commit aab3b51f62b261f773fd5b4d941a6eea5c1d8244 @aleks-f aleks-f committed Dec 13, 2012
View
56 Net/include/Poco/Net/FTPClientSession.h
@@ -1,7 +1,7 @@
//
// FTPClientSession.h
//
-// $Id: //poco/1.4/Net/include/Poco/Net/FTPClientSession.h#1 $
+// $Id: //poco/svn/Net/include/Poco/Net/FTPClientSession.h#2 $
//
// Library: Net
// Package: FTP
@@ -80,15 +80,24 @@ class Net_API FTPClientSession
TYPE_BINARY // TYPE I (Image)
};
+ FTPClientSession();
+ /// Creates an FTPClientSession.
+ ///
+ /// Passive mode will be used for data transfers.
+
explicit FTPClientSession(const StreamSocket& socket);
/// 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);
+ 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.
+ /// to the given host and port. If username is supplied,
+ /// login is attempted.
///
/// Passive mode will be used for data transfers.
@@ -112,6 +121,13 @@ class Net_API FTPClientSession
bool getPassive() const;
/// Returns true iff passive mode is enabled for this connection.
+ 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.
+
void login(const std::string& username, const std::string& password);
/// Authenticates the user against the FTP server. Must be
/// called before any other commands (except QUIT) can be sent.
@@ -122,8 +138,10 @@ class Net_API FTPClientSession
/// Throws a FTPException in case of a FTP-specific error, or a
/// NetException in case of a general network communication failure.
+ void logout();
+
void close();
- /// Sends a QUIT command and closes the connection to the server.
+ /// 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.
@@ -300,6 +318,12 @@ class Net_API FTPClientSession
/// Sends the given command verbatim to the server
/// and waits for a response.
+ bool isOpen() const;
+ /// Returns true if the connection with FTP server is opened.
+
+ bool isLoggedIn() const;
+ /// Returns true if the session is logged in.
+
protected:
enum StatusClass
{
@@ -334,16 +358,18 @@ class Net_API FTPClientSession
void endTransfer();
private:
- FTPClientSession();
FTPClientSession(const FTPClientSession&);
FTPClientSession& operator = (const FTPClientSession&);
- DialogSocket _controlSocket;
+ std::string _host;
+ Poco::UInt16 _port;
+ DialogSocket* _pControlSocket;
SocketStream* _pDataStream;
- bool _passiveMode;
+ bool _passiveMode;
FileType _fileType;
- bool _supports1738;
- bool _isOpen;
+ bool _supports1738;
+ bool _serverReady;
+ bool _isLoggedIn;
Poco::Timespan _timeout;
};
@@ -381,6 +407,18 @@ inline bool FTPClientSession::isPermanentNegative(int status)
}
+inline bool FTPClientSession::isOpen() const
+{
+ return _pControlSocket != 0;
+}
+
+
+inline bool FTPClientSession::isLoggedIn() const
+{
+ return _isLoggedIn;
+}
+
+
} } // namespace Poco::Net
View
214 Net/src/FTPClientSession.cpp
@@ -1,7 +1,7 @@
//
// FTPClientSession.cpp
//
-// $Id: //poco/1.4/Net/src/FTPClientSession.cpp#1 $
+// $Id: //poco/svn/Net/src/FTPClientSession.cpp#2 $
//
// Library: Net
// Package: FTP
@@ -50,48 +50,72 @@ namespace Poco {
namespace Net {
-FTPClientSession::FTPClientSession(const StreamSocket& socket):
- _controlSocket(socket),
+FTPClientSession::FTPClientSession():
+ _port(0),
+ _pControlSocket(0),
_pDataStream(0),
_passiveMode(true),
_fileType(TYPE_BINARY),
_supports1738(true),
- _isOpen(true),
+ _serverReady(false),
+ _isLoggedIn(false),
_timeout(DEFAULT_TIMEOUT)
{
- _controlSocket.setReceiveTimeout(_timeout);
}
-FTPClientSession::FTPClientSession(const std::string& host, Poco::UInt16 port):
- _controlSocket(SocketAddress(host, port)),
+FTPClientSession::FTPClientSession(const StreamSocket& socket):
+ _host(socket.address().host().toString()),
+ _port(socket.address().port()),
+ _pControlSocket(new DialogSocket(socket)),
_pDataStream(0),
_passiveMode(true),
_fileType(TYPE_BINARY),
_supports1738(true),
- _isOpen(true),
+ _serverReady(false),
+ _isLoggedIn(false),
_timeout(DEFAULT_TIMEOUT)
{
- _controlSocket.setReceiveTimeout(_timeout);
+ _pControlSocket->setReceiveTimeout(_timeout);
}
-FTPClientSession::~FTPClientSession()
-{
- try
+FTPClientSession::FTPClientSession(const std::string& host,
+ Poco::UInt16 port,
+ const std::string& username,
+ const std::string& password):
+ _host(host),
+ _port(port),
+ _pControlSocket(new DialogSocket(SocketAddress(host, port))),
+ _pDataStream(0),
+ _passiveMode(true),
+ _fileType(TYPE_BINARY),
+ _supports1738(true),
+ _serverReady(false),
+ _isLoggedIn(false),
+ _timeout(DEFAULT_TIMEOUT)
{
- close();
+ if (!username.empty())
+ login(username, password);
+ else
+ _pControlSocket->setReceiveTimeout(_timeout);
}
- catch (...)
+
+
+FTPClientSession::~FTPClientSession()
{
- }
+ try { close(); }
+ catch (...) { }
}
void FTPClientSession::setTimeout(const Poco::Timespan& timeout)
{
+ if (!isOpen())
+ throw FTPException("Connection is closed.");
+
_timeout = timeout;
- _controlSocket.setReceiveTimeout(timeout);
+ _pControlSocket->setReceiveTimeout(timeout);
}
@@ -114,38 +138,81 @@ bool FTPClientSession::getPassive() const
}
+void FTPClientSession::open(const std::string& host,
+ Poco::UInt16 port,
+ const std::string& username,
+ const std::string& password)
+{
+ _host = host;
+ _port = port;
+ if (!username.empty())
+ login(username, password);
+ else
+ {
+ _pControlSocket = new DialogSocket(SocketAddress(_host, _port));
+ _pControlSocket->setReceiveTimeout(_timeout);
+ }
+}
+
+
void FTPClientSession::login(const std::string& username, const std::string& password)
{
+ if (_isLoggedIn) logout();
+
+ int status = FTP_POSITIVE_COMPLETION * 100;
std::string response;
- int status = _controlSocket.receiveStatusMessage(response);
- if (!isPositiveCompletion(status)) throw FTPException("Cannot login to server", response, status);
+ if (!_pControlSocket)
+ {
+ _pControlSocket = new DialogSocket(SocketAddress(_host, _port));
+ _pControlSocket->setReceiveTimeout(_timeout);
+ }
+
+ if (!_serverReady)
+ {
+ status = _pControlSocket->receiveStatusMessage(response);
+ if (!isPositiveCompletion(status))
+ throw FTPException("Cannot login to server", response, status);
+
+ _serverReady = true;
+ }
+
status = sendCommand("USER", username, response);
if (isPositiveIntermediate(status))
status = sendCommand("PASS", password, response);
- if (!isPositiveCompletion(status)) throw FTPException("Login denied", response, status);
+ if (!isPositiveCompletion(status))
+ throw FTPException("Login denied", response, status);
+
setFileType(_fileType);
+ _isLoggedIn = true;
}
-void FTPClientSession::close()
-{
- if (_isOpen)
- {
- try
+void FTPClientSession::logout()
{
- endTransfer();
- }
- catch (...)
+ if (!isOpen())
+ throw FTPException("Connection is closed.");
+
+ if (_isLoggedIn)
{
- }
+ try { endTransfer(); }
+ catch (...) { }
std::string response;
sendCommand("QUIT", response);
- _controlSocket.close();
- _isOpen = false;
+ _isLoggedIn = false;
}
}
+void FTPClientSession::close()
+{
+ logout();
+ _pControlSocket->close();
+ delete _pControlSocket;
+ _pControlSocket = 0;
+ _serverReady = false;
+}
+
+
void FTPClientSession::setFileType(FTPClientSession::FileType type)
{
std::string response;
@@ -176,7 +243,8 @@ void FTPClientSession::setWorkingDirectory(const std::string& path)
{
std::string response;
int status = sendCommand("CWD", path, response);
- if (!isPositiveCompletion(status)) throw FTPException("Cannot change directory", response, status);
+ if (!isPositiveCompletion(status))
+ throw FTPException("Cannot change directory", response, status);
}
@@ -195,46 +263,55 @@ void FTPClientSession::cdup()
{
std::string response;
int status = sendCommand("CDUP", response);
- if (!isPositiveCompletion(status)) throw FTPException("Cannot change directory", response, status);
+ if (!isPositiveCompletion(status))
+ 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)) throw FTPException(std::string("Cannot rename ") + oldName, response, status);
+ if (!isPositiveIntermediate(status))
+ throw FTPException(std::string("Cannot rename ") + oldName, response, status);
status = sendCommand("RNTO", newName, response);
- if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot rename to ") + newName, response, 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)) throw FTPException(std::string("Cannot remove " + path), response, status);
+ if (!isPositiveCompletion(status))
+ throw FTPException(std::string("Cannot remove " + path), response, status);
}
void FTPClientSession::createDirectory(const std::string& path)
{
std::string response;
int status = sendCommand("MKD", path, response);
- if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot create directory ") + path, response, status);
+ if (!isPositiveCompletion(status))
+ throw FTPException(std::string("Cannot create directory ") + path, response, status);
}
void FTPClientSession::removeDirectory(const std::string& path)
{
std::string response;
int status = sendCommand("RMD", path, response);
- if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot remove directory ") + path, response, status);
+ if (!isPositiveCompletion(status))
+ throw FTPException(std::string("Cannot remove directory ") + path, response, status);
}
std::istream& FTPClientSession::beginDownload(const std::string& path)
{
+ if (!isOpen())
+ throw FTPException("Connection is closed.");
+
delete _pDataStream;
_pDataStream = 0;
_pDataStream = new SocketStream(establishDataConnection("RETR", path));
@@ -250,6 +327,9 @@ void FTPClientSession::endDownload()
std::ostream& FTPClientSession::beginUpload(const std::string& path)
{
+ if (!isOpen())
+ throw FTPException("Connection is closed.");
+
delete _pDataStream;
_pDataStream = 0;
_pDataStream = new SocketStream(establishDataConnection("STOR", path));
@@ -265,6 +345,9 @@ void FTPClientSession::endUpload()
std::istream& FTPClientSession::beginList(const std::string& path, bool extended)
{
+ if (!isOpen())
+ throw FTPException("Connection is closed.");
+
delete _pDataStream;
_pDataStream = 0;
_pDataStream = new SocketStream(establishDataConnection(extended ? "LIST" : "NLST", path));
@@ -280,27 +363,37 @@ void FTPClientSession::endList()
void FTPClientSession::abort()
{
- _controlSocket.sendByte(DialogSocket::TELNET_IP);
- _controlSocket.synch();
+ if (!isOpen())
+ throw FTPException("Connection is closed.");
+
+ _pControlSocket->sendByte(DialogSocket::TELNET_IP);
+ _pControlSocket->synch();
std::string response;
int status = sendCommand("ABOR", response);
if (status == 426)
- status = _controlSocket.receiveStatusMessage(response);
- if (status != 226) throw FTPException("Cannot abort transfer", response, status);
+ status = _pControlSocket->receiveStatusMessage(response);
+ if (status != 226)
+ throw FTPException("Cannot abort transfer", response, status);
}
int FTPClientSession::sendCommand(const std::string& command, std::string& response)
{
- _controlSocket.sendMessage(command);
- return _controlSocket.receiveStatusMessage(response);
+ if (!isOpen())
+ throw FTPException("Connection is closed.");
+
+ _pControlSocket->sendMessage(command);
+ return _pControlSocket->receiveStatusMessage(response);
}
int FTPClientSession::sendCommand(const std::string& command, const std::string& arg, std::string& response)
{
- _controlSocket.sendMessage(command, arg);
- return _controlSocket.receiveStatusMessage(response);
+ if (!isOpen())
+ throw FTPException("Connection is closed.");
+
+ _pControlSocket->sendMessage(command, arg);
+ return _pControlSocket->receiveStatusMessage(response);
}
@@ -329,23 +422,24 @@ std::string FTPClientSession::extractPath(const std::string& response)
StreamSocket FTPClientSession::establishDataConnection(const std::string& command, const std::string& arg)
{
- StreamSocket ss;
if (_passiveMode)
- ss = passiveDataConnection(command, arg);
+ return passiveDataConnection(command, arg);
else
- ss = activeDataConnection(command, arg);
- ss.setReceiveTimeout(_timeout);
- return ss;
+ return activeDataConnection(command, arg);
}
StreamSocket FTPClientSession::activeDataConnection(const std::string& command, const std::string& arg)
{
- ServerSocket server(SocketAddress(_controlSocket.address().host(), 0));
+ if (!isOpen())
+ throw FTPException("Connection is closed.");
+
+ ServerSocket server(SocketAddress(_pControlSocket->address().host(), 0));
sendPortCommand(server.address());
std::string response;
int status = sendCommand(command, arg, response);
- if (!isPositivePreliminary(status)) throw FTPException(command + " command failed", response, status);
+ if (!isPositivePreliminary(status))
+ throw FTPException(command + " command failed", response, status);
if (server.poll(_timeout, Socket::SELECT_READ))
return server.acceptConnection();
else
@@ -359,7 +453,8 @@ StreamSocket FTPClientSession::passiveDataConnection(const std::string& command,
StreamSocket sock(sa);
std::string response;
int status = sendCommand(command, arg, response);
- if (!isPositivePreliminary(status)) throw FTPException(command + " command failed", response, status);
+ if (!isPositivePreliminary(status))
+ throw FTPException(command + " command failed", response, status);
return sock;
}
@@ -426,7 +521,8 @@ void FTPClientSession::sendPORT(const SocketAddress& addr)
arg += NumberFormatter::format(port % 256);
std::string response;
int status = sendCommand("PORT", arg, response);
- if (!isPositiveCompletion(status)) throw FTPException("PORT command failed", response, status);
+ if (!isPositiveCompletion(status))
+ throw FTPException("PORT command failed", response, status);
}
@@ -451,7 +547,8 @@ void FTPClientSession::sendPASV(SocketAddress& addr)
{
std::string response;
int status = sendCommand("PASV", response);
- if (!isPositiveCompletion(status)) throw FTPException("PASV command failed", response, status);
+ if (!isPositiveCompletion(status))
+ throw FTPException("PASV command failed", response, status);
parseAddress(response, addr);
}
@@ -492,7 +589,7 @@ void FTPClientSession::parseExtAddress(const std::string& str, SocketAddress& ad
if (it != end && *it == delim) ++it;
Poco::UInt16 port = 0;
while (it != end && Poco::Ascii::isDigit(*it)) { port *= 10; port += *it++ - '0'; }
- addr = SocketAddress(_controlSocket.peerAddress().host(), port);
+ addr = SocketAddress(_pControlSocket->peerAddress().host(), port);
}
@@ -503,8 +600,9 @@ void FTPClientSession::endTransfer()
delete _pDataStream;
_pDataStream = 0;
std::string response;
- int status = _controlSocket.receiveStatusMessage(response);
- if (!isPositiveCompletion(status)) throw FTPException("Data transfer failed", response, status);
+ int status = _pControlSocket->receiveStatusMessage(response);
+ if (!isPositiveCompletion(status))
+ throw FTPException("Data transfer failed", response, status);
}
}
View
87 Net/testsuite/src/FTPClientSessionTest.cpp
@@ -1,7 +1,7 @@
//
// FTPClientSessionTest.cpp
//
-// $Id: //poco/1.4/Net/testsuite/src/FTPClientSessionTest.cpp#1 $
+// $Id: //poco/svn/Net/testsuite/src/FTPClientSessionTest.cpp#2 $
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
@@ -93,14 +93,11 @@ FTPClientSessionTest::~FTPClientSessionTest()
}
-void FTPClientSessionTest::testLogin()
+void FTPClientSessionTest::login(DialogServer& server, FTPClientSession& session)
{
- DialogServer server;
- server.addResponse("220 localhost FTP ready");
server.addResponse("331 Password required");
server.addResponse("230 Welcome");
server.addResponse("200 Type set to I");
- FTPClientSession session("localhost", server.port());
session.login("user", "password");
std::string cmd = server.popCommand();
assert (cmd == "USER user");
@@ -110,12 +107,86 @@ void FTPClientSessionTest::testLogin()
assert (cmd == "TYPE I");
assert (session.getFileType() == FTPClientSession::TYPE_BINARY);
-
+}
+
+
+void FTPClientSessionTest::testLogin1()
+{
+ DialogServer server;
+ server.addResponse("220 localhost FTP ready");
+ FTPClientSession session("localhost", server.port());
+ assert (session.isOpen());
+ assert (!session.isLoggedIn());
+ login(server, session);
+ assert (session.isOpen());
+ assert (session.isLoggedIn());
+ server.addResponse("221 Good Bye");
+ session.logout();
+ assert (session.isOpen());
+ assert (!session.isLoggedIn());
+
+ server.clearCommands();
+ server.clearResponses();
+ login(server, session);
+ assert (session.isOpen());
+ assert (session.isLoggedIn());
server.addResponse("221 Good Bye");
session.close();
+ assert (!session.isOpen());
+ assert (!session.isLoggedIn());
}
+void FTPClientSessionTest::testLogin2()
+{
+ DialogServer server;
+ server.addResponse("220 localhost FTP ready");
+ server.addResponse("331 Password required");
+ server.addResponse("230 Welcome");
+ server.addResponse("200 Type set to I");
+ FTPClientSession session("localhost", server.port(), "user", "password");
+ assert (session.isOpen());
+ assert (session.isLoggedIn());
+ server.addResponse("221 Good Bye");
+ session.close();
+ assert (!session.isOpen());
+ assert (!session.isLoggedIn());
+
+ server.clearCommands();
+ server.clearResponses();
+ server.addResponse("220 localhost FTP ready");
+ server.addResponse("331 Password required");
+ server.addResponse("230 Welcome");
+ server.addResponse("200 Type set to I");
+ session.open("localhost", server.port(), "user", "password");
+ assert (session.isOpen());
+ assert (session.isLoggedIn());
+ server.addResponse("221 Good Bye");
+ session.close();
+ assert (!session.isOpen());
+ assert (!session.isLoggedIn());
+}
+
+
+void FTPClientSessionTest::testLogin3()
+{
+ DialogServer server;
+ server.addResponse("220 localhost FTP ready");
+ server.addResponse("331 Password required");
+ server.addResponse("230 Welcome");
+ server.addResponse("200 Type set to I");
+ FTPClientSession session;
+ assert (!session.isOpen());
+ assert (!session.isLoggedIn());
+ session.open("localhost", server.port(), "user", "password");
+ server.addResponse("221 Good Bye");
+ session.close();
+ assert (!session.isOpen());
+ assert (!session.isLoggedIn());
+}
+
+
+
void FTPClientSessionTest::testLoginFailed1()
{
DialogServer server;
@@ -535,7 +606,9 @@ CppUnit::Test* FTPClientSessionTest::suite()
{
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("FTPClientSessionTest");
- CppUnit_addTest(pSuite, FTPClientSessionTest, testLogin);
+ CppUnit_addTest(pSuite, FTPClientSessionTest, testLogin1);
+ CppUnit_addTest(pSuite, FTPClientSessionTest, testLogin2);
+ CppUnit_addTest(pSuite, FTPClientSessionTest, testLogin3);
CppUnit_addTest(pSuite, FTPClientSessionTest, testLoginFailed1);
CppUnit_addTest(pSuite, FTPClientSessionTest, testLoginFailed2);
CppUnit_addTest(pSuite, FTPClientSessionTest, testCommands);
View
16 Net/testsuite/src/FTPClientSessionTest.h
@@ -1,7 +1,7 @@
//
// FTPClientSessionTest.h
//
-// $Id: //poco/1.4/Net/testsuite/src/FTPClientSessionTest.h#1 $
+// $Id: //poco/svn/Net/testsuite/src/FTPClientSessionTest.h#2 $
//
// Definition of the FTPClientSessionTest class.
//
@@ -40,13 +40,24 @@
#include "CppUnit/TestCase.h"
+namespace Poco {
+namespace Net {
+
+class FTPClientSession;
+
+} }
+
+class DialogServer;
+
class FTPClientSessionTest: public CppUnit::TestCase
{
public:
FTPClientSessionTest(const std::string& name);
~FTPClientSessionTest();
- void testLogin();
+ void testLogin1();
+ void testLogin2();
+ void testLogin3();
void testLoginFailed1();
void testLoginFailed2();
void testCommands();
@@ -63,6 +74,7 @@ class FTPClientSessionTest: public CppUnit::TestCase
static CppUnit::Test* suite();
private:
+ void login(DialogServer& server, Poco::Net::FTPClientSession& session);
};
View
2 Net/testsuite/src/FTPClientTestSuite.cpp
@@ -1,7 +1,7 @@
//
// FTPClientTestSuite.cpp
//
-// $Id: //poco/1.4/Net/testsuite/src/FTPClientTestSuite.cpp#1 $
+// $Id: //poco/svn/Net/testsuite/src/FTPClientTestSuite.cpp#2 $
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
View
2 Net/testsuite/src/FTPClientTestSuite.h
@@ -1,7 +1,7 @@
//
// FTPClientTestSuite.h
//
-// $Id: //poco/1.4/Net/testsuite/src/FTPClientTestSuite.h#1 $
+// $Id: //poco/svn/Net/testsuite/src/FTPClientTestSuite.h#2 $
//
// Definition of the FTPClientTestSuite class.
//

0 comments on commit aab3b51

Please sign in to comment.