PageRenderTime 73ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/include/SFML/Network/Ftp.hpp

http://github.com/LaurentGomila/SFML
C++ Header | 616 lines | 119 code | 58 blank | 439 comment | 0 complexity | 4735d91a6d4d6259be87835fcbf98a84 MD5 | raw file
  1. ////////////////////////////////////////////////////////////
  2. //
  3. // SFML - Simple and Fast Multimedia Library
  4. // Copyright (C) 2007-2019 Laurent Gomila (laurent@sfml-dev.org)
  5. //
  6. // This software is provided 'as-is', without any express or implied warranty.
  7. // In no event will the authors be held liable for any damages arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it freely,
  11. // subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented;
  14. // you must not claim that you wrote the original software.
  15. // If you use this software in a product, an acknowledgment
  16. // in the product documentation would be appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such,
  19. // and must not be misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source distribution.
  22. //
  23. ////////////////////////////////////////////////////////////
  24. #ifndef SFML_FTP_HPP
  25. #define SFML_FTP_HPP
  26. ////////////////////////////////////////////////////////////
  27. // Headers
  28. ////////////////////////////////////////////////////////////
  29. #include <SFML/Network/Export.hpp>
  30. #include <SFML/Network/TcpSocket.hpp>
  31. #include <SFML/System/NonCopyable.hpp>
  32. #include <SFML/System/Time.hpp>
  33. #include <string>
  34. #include <vector>
  35. namespace sf
  36. {
  37. class IpAddress;
  38. ////////////////////////////////////////////////////////////
  39. /// \brief A FTP client
  40. ///
  41. ////////////////////////////////////////////////////////////
  42. class SFML_NETWORK_API Ftp : NonCopyable
  43. {
  44. public:
  45. ////////////////////////////////////////////////////////////
  46. /// \brief Enumeration of transfer modes
  47. ///
  48. ////////////////////////////////////////////////////////////
  49. enum TransferMode
  50. {
  51. Binary, //!< Binary mode (file is transfered as a sequence of bytes)
  52. Ascii, //!< Text mode using ASCII encoding
  53. Ebcdic //!< Text mode using EBCDIC encoding
  54. };
  55. ////////////////////////////////////////////////////////////
  56. /// \brief Define a FTP response
  57. ///
  58. ////////////////////////////////////////////////////////////
  59. class SFML_NETWORK_API Response
  60. {
  61. public:
  62. ////////////////////////////////////////////////////////////
  63. /// \brief Status codes possibly returned by a FTP response
  64. ///
  65. ////////////////////////////////////////////////////////////
  66. enum Status
  67. {
  68. // 1xx: the requested action is being initiated,
  69. // expect another reply before proceeding with a new command
  70. RestartMarkerReply = 110, //!< Restart marker reply
  71. ServiceReadySoon = 120, //!< Service ready in N minutes
  72. DataConnectionAlreadyOpened = 125, //!< Data connection already opened, transfer starting
  73. OpeningDataConnection = 150, //!< File status ok, about to open data connection
  74. // 2xx: the requested action has been successfully completed
  75. Ok = 200, //!< Command ok
  76. PointlessCommand = 202, //!< Command not implemented
  77. SystemStatus = 211, //!< System status, or system help reply
  78. DirectoryStatus = 212, //!< Directory status
  79. FileStatus = 213, //!< File status
  80. HelpMessage = 214, //!< Help message
  81. SystemType = 215, //!< NAME system type, where NAME is an official system name from the list in the Assigned Numbers document
  82. ServiceReady = 220, //!< Service ready for new user
  83. ClosingConnection = 221, //!< Service closing control connection
  84. DataConnectionOpened = 225, //!< Data connection open, no transfer in progress
  85. ClosingDataConnection = 226, //!< Closing data connection, requested file action successful
  86. EnteringPassiveMode = 227, //!< Entering passive mode
  87. LoggedIn = 230, //!< User logged in, proceed. Logged out if appropriate
  88. FileActionOk = 250, //!< Requested file action ok
  89. DirectoryOk = 257, //!< PATHNAME created
  90. // 3xx: the command has been accepted, but the requested action
  91. // is dormant, pending receipt of further information
  92. NeedPassword = 331, //!< User name ok, need password
  93. NeedAccountToLogIn = 332, //!< Need account for login
  94. NeedInformation = 350, //!< Requested file action pending further information
  95. // 4xx: the command was not accepted and the requested action did not take place,
  96. // but the error condition is temporary and the action may be requested again
  97. ServiceUnavailable = 421, //!< Service not available, closing control connection
  98. DataConnectionUnavailable = 425, //!< Can't open data connection
  99. TransferAborted = 426, //!< Connection closed, transfer aborted
  100. FileActionAborted = 450, //!< Requested file action not taken
  101. LocalError = 451, //!< Requested action aborted, local error in processing
  102. InsufficientStorageSpace = 452, //!< Requested action not taken; insufficient storage space in system, file unavailable
  103. // 5xx: the command was not accepted and
  104. // the requested action did not take place
  105. CommandUnknown = 500, //!< Syntax error, command unrecognized
  106. ParametersUnknown = 501, //!< Syntax error in parameters or arguments
  107. CommandNotImplemented = 502, //!< Command not implemented
  108. BadCommandSequence = 503, //!< Bad sequence of commands
  109. ParameterNotImplemented = 504, //!< Command not implemented for that parameter
  110. NotLoggedIn = 530, //!< Not logged in
  111. NeedAccountToStore = 532, //!< Need account for storing files
  112. FileUnavailable = 550, //!< Requested action not taken, file unavailable
  113. PageTypeUnknown = 551, //!< Requested action aborted, page type unknown
  114. NotEnoughMemory = 552, //!< Requested file action aborted, exceeded storage allocation
  115. FilenameNotAllowed = 553, //!< Requested action not taken, file name not allowed
  116. // 10xx: SFML custom codes
  117. InvalidResponse = 1000, //!< Not part of the FTP standard, generated by SFML when a received response cannot be parsed
  118. ConnectionFailed = 1001, //!< Not part of the FTP standard, generated by SFML when the low-level socket connection with the server fails
  119. ConnectionClosed = 1002, //!< Not part of the FTP standard, generated by SFML when the low-level socket connection is unexpectedly closed
  120. InvalidFile = 1003 //!< Not part of the FTP standard, generated by SFML when a local file cannot be read or written
  121. };
  122. ////////////////////////////////////////////////////////////
  123. /// \brief Default constructor
  124. ///
  125. /// This constructor is used by the FTP client to build
  126. /// the response.
  127. ///
  128. /// \param code Response status code
  129. /// \param message Response message
  130. ///
  131. ////////////////////////////////////////////////////////////
  132. explicit Response(Status code = InvalidResponse, const std::string& message = "");
  133. ////////////////////////////////////////////////////////////
  134. /// \brief Check if the status code means a success
  135. ///
  136. /// This function is defined for convenience, it is
  137. /// equivalent to testing if the status code is < 400.
  138. ///
  139. /// \return True if the status is a success, false if it is a failure
  140. ///
  141. ////////////////////////////////////////////////////////////
  142. bool isOk() const;
  143. ////////////////////////////////////////////////////////////
  144. /// \brief Get the status code of the response
  145. ///
  146. /// \return Status code
  147. ///
  148. ////////////////////////////////////////////////////////////
  149. Status getStatus() const;
  150. ////////////////////////////////////////////////////////////
  151. /// \brief Get the full message contained in the response
  152. ///
  153. /// \return The response message
  154. ///
  155. ////////////////////////////////////////////////////////////
  156. const std::string& getMessage() const;
  157. private:
  158. ////////////////////////////////////////////////////////////
  159. // Member data
  160. ////////////////////////////////////////////////////////////
  161. Status m_status; //!< Status code returned from the server
  162. std::string m_message; //!< Last message received from the server
  163. };
  164. ////////////////////////////////////////////////////////////
  165. /// \brief Specialization of FTP response returning a directory
  166. ///
  167. ////////////////////////////////////////////////////////////
  168. class SFML_NETWORK_API DirectoryResponse : public Response
  169. {
  170. public:
  171. ////////////////////////////////////////////////////////////
  172. /// \brief Default constructor
  173. ///
  174. /// \param response Source response
  175. ///
  176. ////////////////////////////////////////////////////////////
  177. DirectoryResponse(const Response& response);
  178. ////////////////////////////////////////////////////////////
  179. /// \brief Get the directory returned in the response
  180. ///
  181. /// \return Directory name
  182. ///
  183. ////////////////////////////////////////////////////////////
  184. const std::string& getDirectory() const;
  185. private:
  186. ////////////////////////////////////////////////////////////
  187. // Member data
  188. ////////////////////////////////////////////////////////////
  189. std::string m_directory; //!< Directory extracted from the response message
  190. };
  191. ////////////////////////////////////////////////////////////
  192. /// \brief Specialization of FTP response returning a
  193. /// filename listing
  194. ////////////////////////////////////////////////////////////
  195. class SFML_NETWORK_API ListingResponse : public Response
  196. {
  197. public:
  198. ////////////////////////////////////////////////////////////
  199. /// \brief Default constructor
  200. ///
  201. /// \param response Source response
  202. /// \param data Data containing the raw listing
  203. ///
  204. ////////////////////////////////////////////////////////////
  205. ListingResponse(const Response& response, const std::string& data);
  206. ////////////////////////////////////////////////////////////
  207. /// \brief Return the array of directory/file names
  208. ///
  209. /// \return Array containing the requested listing
  210. ///
  211. ////////////////////////////////////////////////////////////
  212. const std::vector<std::string>& getListing() const;
  213. private:
  214. ////////////////////////////////////////////////////////////
  215. // Member data
  216. ////////////////////////////////////////////////////////////
  217. std::vector<std::string> m_listing; //!< Directory/file names extracted from the data
  218. };
  219. ////////////////////////////////////////////////////////////
  220. /// \brief Destructor
  221. ///
  222. /// Automatically closes the connection with the server if
  223. /// it is still opened.
  224. ///
  225. ////////////////////////////////////////////////////////////
  226. ~Ftp();
  227. ////////////////////////////////////////////////////////////
  228. /// \brief Connect to the specified FTP server
  229. ///
  230. /// The port has a default value of 21, which is the standard
  231. /// port used by the FTP protocol. You shouldn't use a different
  232. /// value, unless you really know what you do.
  233. /// This function tries to connect to the server so it may take
  234. /// a while to complete, especially if the server is not
  235. /// reachable. To avoid blocking your application for too long,
  236. /// you can use a timeout. The default value, Time::Zero, means that the
  237. /// system timeout will be used (which is usually pretty long).
  238. ///
  239. /// \param server Name or address of the FTP server to connect to
  240. /// \param port Port used for the connection
  241. /// \param timeout Maximum time to wait
  242. ///
  243. /// \return Server response to the request
  244. ///
  245. /// \see disconnect
  246. ///
  247. ////////////////////////////////////////////////////////////
  248. Response connect(const IpAddress& server, unsigned short port = 21, Time timeout = Time::Zero);
  249. ////////////////////////////////////////////////////////////
  250. /// \brief Close the connection with the server
  251. ///
  252. /// \return Server response to the request
  253. ///
  254. /// \see connect
  255. ///
  256. ////////////////////////////////////////////////////////////
  257. Response disconnect();
  258. ////////////////////////////////////////////////////////////
  259. /// \brief Log in using an anonymous account
  260. ///
  261. /// Logging in is mandatory after connecting to the server.
  262. /// Users that are not logged in cannot perform any operation.
  263. ///
  264. /// \return Server response to the request
  265. ///
  266. ////////////////////////////////////////////////////////////
  267. Response login();
  268. ////////////////////////////////////////////////////////////
  269. /// \brief Log in using a username and a password
  270. ///
  271. /// Logging in is mandatory after connecting to the server.
  272. /// Users that are not logged in cannot perform any operation.
  273. ///
  274. /// \param name User name
  275. /// \param password Password
  276. ///
  277. /// \return Server response to the request
  278. ///
  279. ////////////////////////////////////////////////////////////
  280. Response login(const std::string& name, const std::string& password);
  281. ////////////////////////////////////////////////////////////
  282. /// \brief Send a null command to keep the connection alive
  283. ///
  284. /// This command is useful because the server may close the
  285. /// connection automatically if no command is sent.
  286. ///
  287. /// \return Server response to the request
  288. ///
  289. ////////////////////////////////////////////////////////////
  290. Response keepAlive();
  291. ////////////////////////////////////////////////////////////
  292. /// \brief Get the current working directory
  293. ///
  294. /// The working directory is the root path for subsequent
  295. /// operations involving directories and/or filenames.
  296. ///
  297. /// \return Server response to the request
  298. ///
  299. /// \see getDirectoryListing, changeDirectory, parentDirectory
  300. ///
  301. ////////////////////////////////////////////////////////////
  302. DirectoryResponse getWorkingDirectory();
  303. ////////////////////////////////////////////////////////////
  304. /// \brief Get the contents of the given directory
  305. ///
  306. /// This function retrieves the sub-directories and files
  307. /// contained in the given directory. It is not recursive.
  308. /// The \a directory parameter is relative to the current
  309. /// working directory.
  310. ///
  311. /// \param directory Directory to list
  312. ///
  313. /// \return Server response to the request
  314. ///
  315. /// \see getWorkingDirectory, changeDirectory, parentDirectory
  316. ///
  317. ////////////////////////////////////////////////////////////
  318. ListingResponse getDirectoryListing(const std::string& directory = "");
  319. ////////////////////////////////////////////////////////////
  320. /// \brief Change the current working directory
  321. ///
  322. /// The new directory must be relative to the current one.
  323. ///
  324. /// \param directory New working directory
  325. ///
  326. /// \return Server response to the request
  327. ///
  328. /// \see getWorkingDirectory, getDirectoryListing, parentDirectory
  329. ///
  330. ////////////////////////////////////////////////////////////
  331. Response changeDirectory(const std::string& directory);
  332. ////////////////////////////////////////////////////////////
  333. /// \brief Go to the parent directory of the current one
  334. ///
  335. /// \return Server response to the request
  336. ///
  337. /// \see getWorkingDirectory, getDirectoryListing, changeDirectory
  338. ///
  339. ////////////////////////////////////////////////////////////
  340. Response parentDirectory();
  341. ////////////////////////////////////////////////////////////
  342. /// \brief Create a new directory
  343. ///
  344. /// The new directory is created as a child of the current
  345. /// working directory.
  346. ///
  347. /// \param name Name of the directory to create
  348. ///
  349. /// \return Server response to the request
  350. ///
  351. /// \see deleteDirectory
  352. ///
  353. ////////////////////////////////////////////////////////////
  354. Response createDirectory(const std::string& name);
  355. ////////////////////////////////////////////////////////////
  356. /// \brief Remove an existing directory
  357. ///
  358. /// The directory to remove must be relative to the
  359. /// current working directory.
  360. /// Use this function with caution, the directory will
  361. /// be removed permanently!
  362. ///
  363. /// \param name Name of the directory to remove
  364. ///
  365. /// \return Server response to the request
  366. ///
  367. /// \see createDirectory
  368. ///
  369. ////////////////////////////////////////////////////////////
  370. Response deleteDirectory(const std::string& name);
  371. ////////////////////////////////////////////////////////////
  372. /// \brief Rename an existing file
  373. ///
  374. /// The filenames must be relative to the current working
  375. /// directory.
  376. ///
  377. /// \param file File to rename
  378. /// \param newName New name of the file
  379. ///
  380. /// \return Server response to the request
  381. ///
  382. /// \see deleteFile
  383. ///
  384. ////////////////////////////////////////////////////////////
  385. Response renameFile(const std::string& file, const std::string& newName);
  386. ////////////////////////////////////////////////////////////
  387. /// \brief Remove an existing file
  388. ///
  389. /// The file name must be relative to the current working
  390. /// directory.
  391. /// Use this function with caution, the file will be
  392. /// removed permanently!
  393. ///
  394. /// \param name File to remove
  395. ///
  396. /// \return Server response to the request
  397. ///
  398. /// \see renameFile
  399. ///
  400. ////////////////////////////////////////////////////////////
  401. Response deleteFile(const std::string& name);
  402. ////////////////////////////////////////////////////////////
  403. /// \brief Download a file from the server
  404. ///
  405. /// The filename of the distant file is relative to the
  406. /// current working directory of the server, and the local
  407. /// destination path is relative to the current directory
  408. /// of your application.
  409. /// If a file with the same filename as the distant file
  410. /// already exists in the local destination path, it will
  411. /// be overwritten.
  412. ///
  413. /// \param remoteFile Filename of the distant file to download
  414. /// \param localPath The directory in which to put the file on the local computer
  415. /// \param mode Transfer mode
  416. ///
  417. /// \return Server response to the request
  418. ///
  419. /// \see upload
  420. ///
  421. ////////////////////////////////////////////////////////////
  422. Response download(const std::string& remoteFile, const std::string& localPath, TransferMode mode = Binary);
  423. ////////////////////////////////////////////////////////////
  424. /// \brief Upload a file to the server
  425. ///
  426. /// The name of the local file is relative to the current
  427. /// working directory of your application, and the
  428. /// remote path is relative to the current directory of the
  429. /// FTP server.
  430. ///
  431. /// The append parameter controls whether the remote file is
  432. /// appended to or overwritten if it already exists.
  433. ///
  434. /// \param localFile Path of the local file to upload
  435. /// \param remotePath The directory in which to put the file on the server
  436. /// \param mode Transfer mode
  437. /// \param append Pass true to append to or false to overwrite the remote file if it already exists
  438. ///
  439. /// \return Server response to the request
  440. ///
  441. /// \see download
  442. ///
  443. ////////////////////////////////////////////////////////////
  444. Response upload(const std::string& localFile, const std::string& remotePath, TransferMode mode = Binary, bool append = false);
  445. ////////////////////////////////////////////////////////////
  446. /// \brief Send a command to the FTP server
  447. ///
  448. /// While the most often used commands are provided as member
  449. /// functions in the sf::Ftp class, this method can be used
  450. /// to send any FTP command to the server. If the command
  451. /// requires one or more parameters, they can be specified
  452. /// in \a parameter. If the server returns information, you
  453. /// can extract it from the response using Response::getMessage().
  454. ///
  455. /// \param command Command to send
  456. /// \param parameter Command parameter
  457. ///
  458. /// \return Server response to the request
  459. ///
  460. ////////////////////////////////////////////////////////////
  461. Response sendCommand(const std::string& command, const std::string& parameter = "");
  462. private:
  463. ////////////////////////////////////////////////////////////
  464. /// \brief Receive a response from the server
  465. ///
  466. /// This function must be called after each call to
  467. /// sendCommand that expects a response.
  468. ///
  469. /// \return Server response to the request
  470. ///
  471. ////////////////////////////////////////////////////////////
  472. Response getResponse();
  473. ////////////////////////////////////////////////////////////
  474. /// \brief Utility class for exchanging datas with the server
  475. /// on the data channel
  476. ///
  477. ////////////////////////////////////////////////////////////
  478. class DataChannel;
  479. friend class DataChannel;
  480. ////////////////////////////////////////////////////////////
  481. // Member data
  482. ////////////////////////////////////////////////////////////
  483. TcpSocket m_commandSocket; //!< Socket holding the control connection with the server
  484. std::string m_receiveBuffer; //!< Received command data that is yet to be processed
  485. };
  486. } // namespace sf
  487. #endif // SFML_FTP_HPP
  488. ////////////////////////////////////////////////////////////
  489. /// \class sf::Ftp
  490. /// \ingroup network
  491. ///
  492. /// sf::Ftp is a very simple FTP client that allows you
  493. /// to communicate with a FTP server. The FTP protocol allows
  494. /// you to manipulate a remote file system (list files,
  495. /// upload, download, create, remove, ...).
  496. ///
  497. /// Using the FTP client consists of 4 parts:
  498. /// \li Connecting to the FTP server
  499. /// \li Logging in (either as a registered user or anonymously)
  500. /// \li Sending commands to the server
  501. /// \li Disconnecting (this part can be done implicitly by the destructor)
  502. ///
  503. /// Every command returns a FTP response, which contains the
  504. /// status code as well as a message from the server. Some
  505. /// commands such as getWorkingDirectory() and getDirectoryListing()
  506. /// return additional data, and use a class derived from
  507. /// sf::Ftp::Response to provide this data. The most often used
  508. /// commands are directly provided as member functions, but it is
  509. /// also possible to use specific commands with the sendCommand() function.
  510. ///
  511. /// Note that response statuses >= 1000 are not part of the FTP standard,
  512. /// they are generated by SFML when an internal error occurs.
  513. ///
  514. /// All commands, especially upload and download, may take some
  515. /// time to complete. This is important to know if you don't want
  516. /// to block your application while the server is completing
  517. /// the task.
  518. ///
  519. /// Usage example:
  520. /// \code
  521. /// // Create a new FTP client
  522. /// sf::Ftp ftp;
  523. ///
  524. /// // Connect to the server
  525. /// sf::Ftp::Response response = ftp.connect("ftp://ftp.myserver.com");
  526. /// if (response.isOk())
  527. /// std::cout << "Connected" << std::endl;
  528. ///
  529. /// // Log in
  530. /// response = ftp.login("laurent", "dF6Zm89D");
  531. /// if (response.isOk())
  532. /// std::cout << "Logged in" << std::endl;
  533. ///
  534. /// // Print the working directory
  535. /// sf::Ftp::DirectoryResponse directory = ftp.getWorkingDirectory();
  536. /// if (directory.isOk())
  537. /// std::cout << "Working directory: " << directory.getDirectory() << std::endl;
  538. ///
  539. /// // Create a new directory
  540. /// response = ftp.createDirectory("files");
  541. /// if (response.isOk())
  542. /// std::cout << "Created new directory" << std::endl;
  543. ///
  544. /// // Upload a file to this new directory
  545. /// response = ftp.upload("local-path/file.txt", "files", sf::Ftp::Ascii);
  546. /// if (response.isOk())
  547. /// std::cout << "File uploaded" << std::endl;
  548. ///
  549. /// // Send specific commands (here: FEAT to list supported FTP features)
  550. /// response = ftp.sendCommand("FEAT");
  551. /// if (response.isOk())
  552. /// std::cout << "Feature list:\n" << response.getMessage() << std::endl;
  553. ///
  554. /// // Disconnect from the server (optional)
  555. /// ftp.disconnect();
  556. /// \endcode
  557. ///
  558. ////////////////////////////////////////////////////////////