FTPClientSession.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. //
  2. // FTPClientSession.h
  3. //
  4. // Library: Net
  5. // Package: FTP
  6. // Module: FTPClientSession
  7. //
  8. // Definition of the FTPClientSession class.
  9. //
  10. // Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // SPDX-License-Identifier: BSL-1.0
  14. //
  15. #ifndef Net_FTPClientSession_INCLUDED
  16. #define Net_FTPClientSession_INCLUDED
  17. #include "Poco/Net/Net.h"
  18. #include "Poco/Net/DialogSocket.h"
  19. #include "Poco/Timespan.h"
  20. #include <istream>
  21. #include <ostream>
  22. namespace Poco {
  23. namespace Net {
  24. class SocketStream;
  25. class Net_API FTPClientSession
  26. /// This class implements an File Transfer Protocol
  27. /// (FTP, RFC 959) client.
  28. ///
  29. /// Most of the features of the FTP protocol, as specified
  30. /// in RFC 959, are supported. Not supported are EBCDIC and
  31. /// LOCAL data types and format control and structured files.
  32. ///
  33. /// Also supported are the EPRT and EPSV commands from
  34. /// RFC 1738 (FTP Extensions for IPv6 and NAT).
  35. /// The client will first attempt to use the EPRT and EPSV
  36. /// commands. If the server does not supports these commands,
  37. /// the client will fall back to PORT and PASV.
  38. {
  39. public:
  40. enum
  41. {
  42. FTP_PORT = 21
  43. };
  44. enum FileType
  45. {
  46. TYPE_TEXT, // TYPE A (ASCII)
  47. TYPE_BINARY // TYPE I (Image)
  48. };
  49. FTPClientSession();
  50. /// Creates an FTPClientSession.
  51. ///
  52. /// Passive mode will be used for data transfers.
  53. explicit FTPClientSession(const StreamSocket& socket);
  54. /// Creates an FTPClientSession using the given
  55. /// connected socket for the control connection.
  56. ///
  57. /// Passive mode will be used for data transfers.
  58. FTPClientSession(const std::string& host,
  59. Poco::UInt16 port = FTP_PORT,
  60. const std::string& username = "",
  61. const std::string& password = "");
  62. /// Creates an FTPClientSession using a socket connected
  63. /// to the given host and port. If username is supplied,
  64. /// login is attempted.
  65. ///
  66. /// Passive mode will be used for data transfers.
  67. virtual ~FTPClientSession();
  68. /// Destroys the FTPClientSession.
  69. void setTimeout(const Poco::Timespan& timeout);
  70. /// Sets the timeout for socket operations.
  71. Poco::Timespan getTimeout() const;
  72. /// Returns the timeout for socket operations.
  73. void setPassive(bool flag, bool useRFC1738 = true);
  74. /// Enables (default) or disables FTP passive mode for this session.
  75. ///
  76. /// If useRFC1738 is true (the default), the RFC 1738
  77. /// EPSV command is used (with a fallback to PASV if EPSV fails)
  78. /// for switching to passive mode. The same applies to
  79. /// EPRT and PORT for active connections.
  80. bool getPassive() const;
  81. /// Returns true iff passive mode is enabled for this connection.
  82. void open(const std::string& host,
  83. Poco::UInt16 port,
  84. const std::string& username = "",
  85. const std::string& password = "");
  86. /// Opens the FTP connection to the given host and port.
  87. /// If username is supplied, login is attempted.
  88. void login(const std::string& username, const std::string& password);
  89. /// Authenticates the user against the FTP server. Must be
  90. /// called before any other commands (except QUIT) can be sent.
  91. ///
  92. /// Sends a USER command followed by a PASS command with the
  93. /// respective arguments to the server.
  94. ///
  95. /// Throws a FTPException in case of a FTP-specific error, or a
  96. /// NetException in case of a general network communication failure.
  97. void logout();
  98. void close();
  99. /// Sends a QUIT command and closes the connection to the server.
  100. ///
  101. /// Throws a FTPException in case of a FTP-specific error, or a
  102. /// NetException in case of a general network communication failure.
  103. std::string systemType();
  104. /// Returns the system type of the FTP server.
  105. ///
  106. /// Sends a SYST command to the server and returns the result.
  107. void setFileType(FileType type);
  108. /// Sets the file type for transferring files.
  109. ///
  110. /// Sends a TYPE command with a corresponding argument to the
  111. /// server.
  112. ///
  113. /// Throws a FTPException in case of a FTP-specific error, or a
  114. /// NetException in case of a general network communication failure.
  115. FileType getFileType() const;
  116. /// Returns the file type for transferring files.
  117. void setWorkingDirectory(const std::string& path);
  118. /// Changes the current working directory on the server.
  119. ///
  120. /// Sends a CWD command with the given path as argument to the
  121. /// server.
  122. ///
  123. /// Throws a FTPException in case of a FTP-specific error, or a
  124. /// NetException in case of a general network communication failure.
  125. std::string getWorkingDirectory();
  126. /// Returns the current working directory on the server.
  127. ///
  128. /// Throws a FTPException in case of a FTP-specific error, or a
  129. /// NetException in case of a general network communication failure.
  130. void cdup();
  131. /// Moves one directory up from the current working directory
  132. /// on the server.
  133. ///
  134. /// Sends a CDUP command to the server.
  135. ///
  136. /// Throws a FTPException in case of a FTP-specific error, or a
  137. /// NetException in case of a general network communication failure.
  138. void rename(const std::string& oldName, const std::string& newName);
  139. /// Renames the file on the server given by oldName to newName.
  140. ///
  141. /// Sends a RNFR command, followed by a RNTO command to the server.
  142. ///
  143. /// Throws a FTPException in case of a FTP-specific error, or a
  144. /// NetException in case of a general network communication failure.
  145. void remove(const std::string& path);
  146. /// Deletes the file specified by path on the server.
  147. ///
  148. /// Sends a DELE command with path as argument to the server.
  149. ///
  150. /// Throws a FTPException in case of a FTP-specific error, or a
  151. /// NetException in case of a general network communication failure.
  152. void createDirectory(const std::string& path);
  153. /// Creates a new directory with the given path on the server.
  154. ///
  155. /// Sends a MKD command with path as argument to the server.
  156. ///
  157. /// Throws a FTPException in case of a FTP-specific error, or a
  158. /// NetException in case of a general network communication failure.
  159. void removeDirectory(const std::string& path);
  160. /// Removes the directory specified by path from the server.
  161. ///
  162. /// Sends a RMD command with path as argument to the server.
  163. ///
  164. /// Throws a FTPException in case of a FTP-specific error, or a
  165. /// NetException in case of a general network communication failure.
  166. std::istream& beginDownload(const std::string& path);
  167. /// Starts downloading the file with the given name.
  168. /// After all data has been read from the returned stream,
  169. /// endDownload() must be called to finish the download.
  170. ///
  171. /// A stream for reading the file's content is returned.
  172. /// The stream is valid until endDownload() is called.
  173. ///
  174. /// Creates a data connection between the client and the
  175. /// server. If passive mode is on, then the server waits for
  176. /// a connection request from the client. Otherwise, the
  177. /// client waits for a connection request from the server.
  178. /// After establishing the data connection, a SocketStream
  179. /// for transferring the data is created.
  180. ///
  181. /// If ASCII transfer mode is selected, the caller is
  182. /// responsible for converting the received data to
  183. /// the native text file format.
  184. /// The InputLineEndingConverter class from the Foundation
  185. /// library can be used for that purpose.
  186. void endDownload();
  187. /// Must be called to complete a download initiated with
  188. /// beginDownload().
  189. std::ostream& beginUpload(const std::string& path);
  190. /// Starts uploading the file with the given name.
  191. /// After all data has been written to the returned stream,
  192. /// endUpload() must be called to finish the upload.
  193. ///
  194. /// A stream for reading the file's content is returned.
  195. /// The stream is valid until endUpload() is called.
  196. ///
  197. /// Creates a data connection between the client and the
  198. /// server. If passive mode is on, then the server waits for
  199. /// a connection request from the client. Otherwise, the
  200. /// client waits for a connection request from the server.
  201. /// After establishing the data connection, a SocketStream
  202. /// for transferring the data is created.
  203. ///
  204. /// If ASCII transfer mode is selected, the caller is
  205. /// responsible for converting the data to be sent
  206. /// into network (CR-LF line endings) format.
  207. /// The OutputLineEndingConverter class from the Foundation
  208. /// library can be used for that purpose.
  209. void endUpload();
  210. /// Must be called to complete an upload initiated with
  211. /// beginUpload().
  212. std::istream& beginList(const std::string& path = "", bool extended = false);
  213. /// Starts downloading a directory listing.
  214. /// After all data has been read from the returned stream,
  215. /// endList() must be called to finish the download.
  216. ///
  217. /// A stream for reading the directory data is returned.
  218. /// The stream is valid until endList() is called.
  219. ///
  220. /// Optionally, a path to a directory or file can be specified.
  221. /// According to the FTP protocol, if a path to a filename is
  222. /// given, only information for the specific file is returned.
  223. /// If a path to a directory is given, a listing of that directory
  224. /// is returned. If no path is given, a listing of the current
  225. /// working directory is returned.
  226. ///
  227. /// If extended is false, only a filenames (one per line) are
  228. /// returned. Otherwise, a full directory listing including
  229. /// file attributes is returned. The format of this listing
  230. /// depends on the FTP server. No attempt is made to interpret
  231. /// this data.
  232. ///
  233. /// Creates a data connection between the client and the
  234. /// server. If passive mode is on, then the server waits for
  235. /// a connection request from the client. Otherwise, the
  236. /// client waits for a connection request from the server.
  237. /// After establishing the data connection, a SocketStream
  238. /// for transferring the data is created.
  239. void endList();
  240. /// Must be called to complete a directory listing download
  241. /// initiated with beginList().
  242. void abort();
  243. /// Aborts the download or upload currently in progress.
  244. ///
  245. /// Sends a TELNET IP/SYNCH sequence, followed by an ABOR
  246. /// command to the server.
  247. ///
  248. /// A separate call to endDownload() or endUpload() is
  249. /// not necessary.
  250. int sendCommand(const std::string& command, std::string& response);
  251. /// Sends the given command verbatim to the server
  252. /// and waits for a response.
  253. int sendCommand(const std::string& command, const std::string& arg, std::string& response);
  254. /// Sends the given command verbatim to the server
  255. /// and waits for a response.
  256. bool isOpen() const;
  257. /// Returns true if the connection with FTP server is opened.
  258. bool isLoggedIn() const;
  259. /// Returns true if the session is logged in.
  260. protected:
  261. enum StatusClass
  262. {
  263. FTP_POSITIVE_PRELIMINARY = 1,
  264. FTP_POSITIVE_COMPLETION = 2,
  265. FTP_POSITIVE_INTERMEDIATE = 3,
  266. FTP_TRANSIENT_NEGATIVE = 4,
  267. FTP_PERMANENT_NEGATIVE = 5
  268. };
  269. enum
  270. {
  271. DEFAULT_TIMEOUT = 30000000 // 30 seconds default timeout for socket operations
  272. };
  273. static bool isPositivePreliminary(int status);
  274. static bool isPositiveCompletion(int status);
  275. static bool isPositiveIntermediate(int status);
  276. static bool isTransientNegative(int status);
  277. static bool isPermanentNegative(int status);
  278. std::string extractPath(const std::string& response);
  279. StreamSocket establishDataConnection(const std::string& command, const std::string& arg);
  280. StreamSocket activeDataConnection(const std::string& command, const std::string& arg);
  281. StreamSocket passiveDataConnection(const std::string& command, const std::string& arg);
  282. void sendPortCommand(const SocketAddress& addr);
  283. SocketAddress sendPassiveCommand();
  284. bool sendEPRT(const SocketAddress& addr);
  285. void sendPORT(const SocketAddress& addr);
  286. bool sendEPSV(SocketAddress& addr);
  287. void sendPASV(SocketAddress& addr);
  288. void parseAddress(const std::string& str, SocketAddress& addr);
  289. void parseExtAddress(const std::string& str, SocketAddress& addr);
  290. void endTransfer();
  291. private:
  292. FTPClientSession(const FTPClientSession&);
  293. FTPClientSession& operator = (const FTPClientSession&);
  294. std::string _host;
  295. Poco::UInt16 _port;
  296. DialogSocket* _pControlSocket;
  297. SocketStream* _pDataStream;
  298. bool _passiveMode;
  299. FileType _fileType;
  300. bool _supports1738;
  301. bool _serverReady;
  302. bool _isLoggedIn;
  303. Poco::Timespan _timeout;
  304. };
  305. //
  306. // inlines
  307. //
  308. inline bool FTPClientSession::isPositivePreliminary(int status)
  309. {
  310. return status/100 == FTP_POSITIVE_PRELIMINARY;
  311. }
  312. inline bool FTPClientSession::isPositiveCompletion(int status)
  313. {
  314. return status/100 == FTP_POSITIVE_COMPLETION;
  315. }
  316. inline bool FTPClientSession::isPositiveIntermediate(int status)
  317. {
  318. return status/100 == FTP_POSITIVE_INTERMEDIATE;
  319. }
  320. inline bool FTPClientSession::isTransientNegative(int status)
  321. {
  322. return status/100 == FTP_TRANSIENT_NEGATIVE;
  323. }
  324. inline bool FTPClientSession::isPermanentNegative(int status)
  325. {
  326. return status/100 == FTP_PERMANENT_NEGATIVE;
  327. }
  328. inline bool FTPClientSession::isOpen() const
  329. {
  330. return _pControlSocket != 0;
  331. }
  332. inline bool FTPClientSession::isLoggedIn() const
  333. {
  334. return _isLoggedIn;
  335. }
  336. } } // namespace Poco::Net
  337. #endif // Net_FTPClientSession_INCLUDED