Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-06-02 08:58:14

0001 ////////////////////////////////////////////////////////////
0002 //
0003 // SFML - Simple and Fast Multimedia Library
0004 // Copyright (C) 2007-2023 Laurent Gomila (laurent@sfml-dev.org)
0005 //
0006 // This software is provided 'as-is', without any express or implied warranty.
0007 // In no event will the authors be held liable for any damages arising from the use of this software.
0008 //
0009 // Permission is granted to anyone to use this software for any purpose,
0010 // including commercial applications, and to alter it and redistribute it freely,
0011 // subject to the following restrictions:
0012 //
0013 // 1. The origin of this software must not be misrepresented;
0014 //    you must not claim that you wrote the original software.
0015 //    If you use this software in a product, an acknowledgment
0016 //    in the product documentation would be appreciated but is not required.
0017 //
0018 // 2. Altered source versions must be plainly marked as such,
0019 //    and must not be misrepresented as being the original software.
0020 //
0021 // 3. This notice may not be removed or altered from any source distribution.
0022 //
0023 ////////////////////////////////////////////////////////////
0024 
0025 #ifndef SFML_FTP_HPP
0026 #define SFML_FTP_HPP
0027 
0028 ////////////////////////////////////////////////////////////
0029 // Headers
0030 ////////////////////////////////////////////////////////////
0031 #include <SFML/Network/Export.hpp>
0032 #include <SFML/Network/TcpSocket.hpp>
0033 #include <SFML/System/NonCopyable.hpp>
0034 #include <SFML/System/Time.hpp>
0035 #include <string>
0036 #include <vector>
0037 
0038 
0039 namespace sf
0040 {
0041 class IpAddress;
0042 
0043 ////////////////////////////////////////////////////////////
0044 /// \brief A FTP client
0045 ///
0046 ////////////////////////////////////////////////////////////
0047 class SFML_NETWORK_API Ftp : NonCopyable
0048 {
0049 public:
0050 
0051     ////////////////////////////////////////////////////////////
0052     /// \brief Enumeration of transfer modes
0053     ///
0054     ////////////////////////////////////////////////////////////
0055     enum TransferMode
0056     {
0057         Binary, //!< Binary mode (file is transfered as a sequence of bytes)
0058         Ascii,  //!< Text mode using ASCII encoding
0059         Ebcdic  //!< Text mode using EBCDIC encoding
0060     };
0061 
0062     ////////////////////////////////////////////////////////////
0063     /// \brief Define a FTP response
0064     ///
0065     ////////////////////////////////////////////////////////////
0066     class SFML_NETWORK_API Response
0067     {
0068     public:
0069 
0070         ////////////////////////////////////////////////////////////
0071         /// \brief Status codes possibly returned by a FTP response
0072         ///
0073         ////////////////////////////////////////////////////////////
0074         enum Status
0075         {
0076             // 1xx: the requested action is being initiated,
0077             // expect another reply before proceeding with a new command
0078             RestartMarkerReply          = 110, //!< Restart marker reply
0079             ServiceReadySoon            = 120, //!< Service ready in N minutes
0080             DataConnectionAlreadyOpened = 125, //!< Data connection already opened, transfer starting
0081             OpeningDataConnection       = 150, //!< File status ok, about to open data connection
0082 
0083             // 2xx: the requested action has been successfully completed
0084             Ok                    = 200, //!< Command ok
0085             PointlessCommand      = 202, //!< Command not implemented
0086             SystemStatus          = 211, //!< System status, or system help reply
0087             DirectoryStatus       = 212, //!< Directory status
0088             FileStatus            = 213, //!< File status
0089             HelpMessage           = 214, //!< Help message
0090             SystemType            = 215, //!< NAME system type, where NAME is an official system name from the list in the Assigned Numbers document
0091             ServiceReady          = 220, //!< Service ready for new user
0092             ClosingConnection     = 221, //!< Service closing control connection
0093             DataConnectionOpened  = 225, //!< Data connection open, no transfer in progress
0094             ClosingDataConnection = 226, //!< Closing data connection, requested file action successful
0095             EnteringPassiveMode   = 227, //!< Entering passive mode
0096             LoggedIn              = 230, //!< User logged in, proceed. Logged out if appropriate
0097             FileActionOk          = 250, //!< Requested file action ok
0098             DirectoryOk           = 257, //!< PATHNAME created
0099 
0100             // 3xx: the command has been accepted, but the requested action
0101             // is dormant, pending receipt of further information
0102             NeedPassword       = 331, //!< User name ok, need password
0103             NeedAccountToLogIn = 332, //!< Need account for login
0104             NeedInformation    = 350, //!< Requested file action pending further information
0105 
0106             // 4xx: the command was not accepted and the requested action did not take place,
0107             // but the error condition is temporary and the action may be requested again
0108             ServiceUnavailable        = 421, //!< Service not available, closing control connection
0109             DataConnectionUnavailable = 425, //!< Can't open data connection
0110             TransferAborted           = 426, //!< Connection closed, transfer aborted
0111             FileActionAborted         = 450, //!< Requested file action not taken
0112             LocalError                = 451, //!< Requested action aborted, local error in processing
0113             InsufficientStorageSpace  = 452, //!< Requested action not taken; insufficient storage space in system, file unavailable
0114 
0115             // 5xx: the command was not accepted and
0116             // the requested action did not take place
0117             CommandUnknown          = 500, //!< Syntax error, command unrecognized
0118             ParametersUnknown       = 501, //!< Syntax error in parameters or arguments
0119             CommandNotImplemented   = 502, //!< Command not implemented
0120             BadCommandSequence      = 503, //!< Bad sequence of commands
0121             ParameterNotImplemented = 504, //!< Command not implemented for that parameter
0122             NotLoggedIn             = 530, //!< Not logged in
0123             NeedAccountToStore      = 532, //!< Need account for storing files
0124             FileUnavailable         = 550, //!< Requested action not taken, file unavailable
0125             PageTypeUnknown         = 551, //!< Requested action aborted, page type unknown
0126             NotEnoughMemory         = 552, //!< Requested file action aborted, exceeded storage allocation
0127             FilenameNotAllowed      = 553, //!< Requested action not taken, file name not allowed
0128 
0129             // 10xx: SFML custom codes
0130             InvalidResponse  = 1000, //!< Not part of the FTP standard, generated by SFML when a received response cannot be parsed
0131             ConnectionFailed = 1001, //!< Not part of the FTP standard, generated by SFML when the low-level socket connection with the server fails
0132             ConnectionClosed = 1002, //!< Not part of the FTP standard, generated by SFML when the low-level socket connection is unexpectedly closed
0133             InvalidFile      = 1003  //!< Not part of the FTP standard, generated by SFML when a local file cannot be read or written
0134         };
0135 
0136         ////////////////////////////////////////////////////////////
0137         /// \brief Default constructor
0138         ///
0139         /// This constructor is used by the FTP client to build
0140         /// the response.
0141         ///
0142         /// \param code    Response status code
0143         /// \param message Response message
0144         ///
0145         ////////////////////////////////////////////////////////////
0146         explicit Response(Status code = InvalidResponse, const std::string& message = "");
0147 
0148         ////////////////////////////////////////////////////////////
0149         /// \brief Check if the status code means a success
0150         ///
0151         /// This function is defined for convenience, it is
0152         /// equivalent to testing if the status code is < 400.
0153         ///
0154         /// \return True if the status is a success, false if it is a failure
0155         ///
0156         ////////////////////////////////////////////////////////////
0157         bool isOk() const;
0158 
0159         ////////////////////////////////////////////////////////////
0160         /// \brief Get the status code of the response
0161         ///
0162         /// \return Status code
0163         ///
0164         ////////////////////////////////////////////////////////////
0165         Status getStatus() const;
0166 
0167         ////////////////////////////////////////////////////////////
0168         /// \brief Get the full message contained in the response
0169         ///
0170         /// \return The response message
0171         ///
0172         ////////////////////////////////////////////////////////////
0173         const std::string& getMessage() const;
0174 
0175     private:
0176 
0177         ////////////////////////////////////////////////////////////
0178         // Member data
0179         ////////////////////////////////////////////////////////////
0180         Status      m_status;  //!< Status code returned from the server
0181         std::string m_message; //!< Last message received from the server
0182     };
0183 
0184     ////////////////////////////////////////////////////////////
0185     /// \brief Specialization of FTP response returning a directory
0186     ///
0187     ////////////////////////////////////////////////////////////
0188     class SFML_NETWORK_API DirectoryResponse : public Response
0189     {
0190     public:
0191 
0192         ////////////////////////////////////////////////////////////
0193         /// \brief Default constructor
0194         ///
0195         /// \param response Source response
0196         ///
0197         ////////////////////////////////////////////////////////////
0198         DirectoryResponse(const Response& response);
0199 
0200         ////////////////////////////////////////////////////////////
0201         /// \brief Get the directory returned in the response
0202         ///
0203         /// \return Directory name
0204         ///
0205         ////////////////////////////////////////////////////////////
0206         const std::string& getDirectory() const;
0207 
0208     private:
0209 
0210         ////////////////////////////////////////////////////////////
0211         // Member data
0212         ////////////////////////////////////////////////////////////
0213         std::string m_directory; //!< Directory extracted from the response message
0214     };
0215 
0216 
0217     ////////////////////////////////////////////////////////////
0218     /// \brief Specialization of FTP response returning a
0219     ///        filename listing
0220     ////////////////////////////////////////////////////////////
0221     class SFML_NETWORK_API ListingResponse : public Response
0222     {
0223     public:
0224 
0225         ////////////////////////////////////////////////////////////
0226         /// \brief Default constructor
0227         ///
0228         /// \param response  Source response
0229         /// \param data      Data containing the raw listing
0230         ///
0231         ////////////////////////////////////////////////////////////
0232         ListingResponse(const Response& response, const std::string& data);
0233 
0234         ////////////////////////////////////////////////////////////
0235         /// \brief Return the array of directory/file names
0236         ///
0237         /// \return Array containing the requested listing
0238         ///
0239         ////////////////////////////////////////////////////////////
0240         const std::vector<std::string>& getListing() const;
0241 
0242     private:
0243 
0244         ////////////////////////////////////////////////////////////
0245         // Member data
0246         ////////////////////////////////////////////////////////////
0247         std::vector<std::string> m_listing; //!< Directory/file names extracted from the data
0248     };
0249 
0250 
0251     ////////////////////////////////////////////////////////////
0252     /// \brief Destructor
0253     ///
0254     /// Automatically closes the connection with the server if
0255     /// it is still opened.
0256     ///
0257     ////////////////////////////////////////////////////////////
0258     ~Ftp();
0259 
0260     ////////////////////////////////////////////////////////////
0261     /// \brief Connect to the specified FTP server
0262     ///
0263     /// The port has a default value of 21, which is the standard
0264     /// port used by the FTP protocol. You shouldn't use a different
0265     /// value, unless you really know what you do.
0266     /// This function tries to connect to the server so it may take
0267     /// a while to complete, especially if the server is not
0268     /// reachable. To avoid blocking your application for too long,
0269     /// you can use a timeout. The default value, Time::Zero, means that the
0270     /// system timeout will be used (which is usually pretty long).
0271     ///
0272     /// \param server  Name or address of the FTP server to connect to
0273     /// \param port    Port used for the connection
0274     /// \param timeout Maximum time to wait
0275     ///
0276     /// \return Server response to the request
0277     ///
0278     /// \see disconnect
0279     ///
0280     ////////////////////////////////////////////////////////////
0281     Response connect(const IpAddress& server, unsigned short port = 21, Time timeout = Time::Zero);
0282 
0283     ////////////////////////////////////////////////////////////
0284     /// \brief Close the connection with the server
0285     ///
0286     /// \return Server response to the request
0287     ///
0288     /// \see connect
0289     ///
0290     ////////////////////////////////////////////////////////////
0291     Response disconnect();
0292 
0293     ////////////////////////////////////////////////////////////
0294     /// \brief Log in using an anonymous account
0295     ///
0296     /// Logging in is mandatory after connecting to the server.
0297     /// Users that are not logged in cannot perform any operation.
0298     ///
0299     /// \return Server response to the request
0300     ///
0301     ////////////////////////////////////////////////////////////
0302     Response login();
0303 
0304     ////////////////////////////////////////////////////////////
0305     /// \brief Log in using a username and a password
0306     ///
0307     /// Logging in is mandatory after connecting to the server.
0308     /// Users that are not logged in cannot perform any operation.
0309     ///
0310     /// \param name     User name
0311     /// \param password Password
0312     ///
0313     /// \return Server response to the request
0314     ///
0315     ////////////////////////////////////////////////////////////
0316     Response login(const std::string& name, const std::string& password);
0317 
0318     ////////////////////////////////////////////////////////////
0319     /// \brief Send a null command to keep the connection alive
0320     ///
0321     /// This command is useful because the server may close the
0322     /// connection automatically if no command is sent.
0323     ///
0324     /// \return Server response to the request
0325     ///
0326     ////////////////////////////////////////////////////////////
0327     Response keepAlive();
0328 
0329     ////////////////////////////////////////////////////////////
0330     /// \brief Get the current working directory
0331     ///
0332     /// The working directory is the root path for subsequent
0333     /// operations involving directories and/or filenames.
0334     ///
0335     /// \return Server response to the request
0336     ///
0337     /// \see getDirectoryListing, changeDirectory, parentDirectory
0338     ///
0339     ////////////////////////////////////////////////////////////
0340     DirectoryResponse getWorkingDirectory();
0341 
0342     ////////////////////////////////////////////////////////////
0343     /// \brief Get the contents of the given directory
0344     ///
0345     /// This function retrieves the sub-directories and files
0346     /// contained in the given directory. It is not recursive.
0347     /// The \a directory parameter is relative to the current
0348     /// working directory.
0349     ///
0350     /// \param directory Directory to list
0351     ///
0352     /// \return Server response to the request
0353     ///
0354     /// \see getWorkingDirectory, changeDirectory, parentDirectory
0355     ///
0356     ////////////////////////////////////////////////////////////
0357     ListingResponse getDirectoryListing(const std::string& directory = "");
0358 
0359     ////////////////////////////////////////////////////////////
0360     /// \brief Change the current working directory
0361     ///
0362     /// The new directory must be relative to the current one.
0363     ///
0364     /// \param directory New working directory
0365     ///
0366     /// \return Server response to the request
0367     ///
0368     /// \see getWorkingDirectory, getDirectoryListing, parentDirectory
0369     ///
0370     ////////////////////////////////////////////////////////////
0371     Response changeDirectory(const std::string& directory);
0372 
0373     ////////////////////////////////////////////////////////////
0374     /// \brief Go to the parent directory of the current one
0375     ///
0376     /// \return Server response to the request
0377     ///
0378     /// \see getWorkingDirectory, getDirectoryListing, changeDirectory
0379     ///
0380     ////////////////////////////////////////////////////////////
0381     Response parentDirectory();
0382 
0383     ////////////////////////////////////////////////////////////
0384     /// \brief Create a new directory
0385     ///
0386     /// The new directory is created as a child of the current
0387     /// working directory.
0388     ///
0389     /// \param name Name of the directory to create
0390     ///
0391     /// \return Server response to the request
0392     ///
0393     /// \see deleteDirectory
0394     ///
0395     ////////////////////////////////////////////////////////////
0396     Response createDirectory(const std::string& name);
0397 
0398     ////////////////////////////////////////////////////////////
0399     /// \brief Remove an existing directory
0400     ///
0401     /// The directory to remove must be relative to the
0402     /// current working directory.
0403     /// Use this function with caution, the directory will
0404     /// be removed permanently!
0405     ///
0406     /// \param name Name of the directory to remove
0407     ///
0408     /// \return Server response to the request
0409     ///
0410     /// \see createDirectory
0411     ///
0412     ////////////////////////////////////////////////////////////
0413     Response deleteDirectory(const std::string& name);
0414 
0415     ////////////////////////////////////////////////////////////
0416     /// \brief Rename an existing file
0417     ///
0418     /// The filenames must be relative to the current working
0419     /// directory.
0420     ///
0421     /// \param file    File to rename
0422     /// \param newName New name of the file
0423     ///
0424     /// \return Server response to the request
0425     ///
0426     /// \see deleteFile
0427     ///
0428     ////////////////////////////////////////////////////////////
0429     Response renameFile(const std::string& file, const std::string& newName);
0430 
0431     ////////////////////////////////////////////////////////////
0432     /// \brief Remove an existing file
0433     ///
0434     /// The file name must be relative to the current working
0435     /// directory.
0436     /// Use this function with caution, the file will be
0437     /// removed permanently!
0438     ///
0439     /// \param name File to remove
0440     ///
0441     /// \return Server response to the request
0442     ///
0443     /// \see renameFile
0444     ///
0445     ////////////////////////////////////////////////////////////
0446     Response deleteFile(const std::string& name);
0447 
0448     ////////////////////////////////////////////////////////////
0449     /// \brief Download a file from the server
0450     ///
0451     /// The filename of the distant file is relative to the
0452     /// current working directory of the server, and the local
0453     /// destination path is relative to the current directory
0454     /// of your application.
0455     /// If a file with the same filename as the distant file
0456     /// already exists in the local destination path, it will
0457     /// be overwritten.
0458     ///
0459     /// \param remoteFile Filename of the distant file to download
0460     /// \param localPath  The directory in which to put the file on the local computer
0461     /// \param mode       Transfer mode
0462     ///
0463     /// \return Server response to the request
0464     ///
0465     /// \see upload
0466     ///
0467     ////////////////////////////////////////////////////////////
0468     Response download(const std::string& remoteFile, const std::string& localPath, TransferMode mode = Binary);
0469 
0470     ////////////////////////////////////////////////////////////
0471     /// \brief Upload a file to the server
0472     ///
0473     /// The name of the local file is relative to the current
0474     /// working directory of your application, and the
0475     /// remote path is relative to the current directory of the
0476     /// FTP server.
0477     ///
0478     /// The append parameter controls whether the remote file is
0479     /// appended to or overwritten if it already exists.
0480     ///
0481     /// \param localFile  Path of the local file to upload
0482     /// \param remotePath The directory in which to put the file on the server
0483     /// \param mode       Transfer mode
0484     /// \param append     Pass true to append to or false to overwrite the remote file if it already exists
0485     ///
0486     /// \return Server response to the request
0487     ///
0488     /// \see download
0489     ///
0490     ////////////////////////////////////////////////////////////
0491     Response upload(const std::string& localFile, const std::string& remotePath, TransferMode mode = Binary, bool append = false);
0492 
0493     ////////////////////////////////////////////////////////////
0494     /// \brief Send a command to the FTP server
0495     ///
0496     /// While the most often used commands are provided as member
0497     /// functions in the sf::Ftp class, this method can be used
0498     /// to send any FTP command to the server. If the command
0499     /// requires one or more parameters, they can be specified
0500     /// in \a parameter. If the server returns information, you
0501     /// can extract it from the response using Response::getMessage().
0502     ///
0503     /// \param command   Command to send
0504     /// \param parameter Command parameter
0505     ///
0506     /// \return Server response to the request
0507     ///
0508     ////////////////////////////////////////////////////////////
0509     Response sendCommand(const std::string& command, const std::string& parameter = "");
0510 
0511 private:
0512 
0513     ////////////////////////////////////////////////////////////
0514     /// \brief Receive a response from the server
0515     ///
0516     /// This function must be called after each call to
0517     /// sendCommand that expects a response.
0518     ///
0519     /// \return Server response to the request
0520     ///
0521     ////////////////////////////////////////////////////////////
0522     Response getResponse();
0523 
0524     ////////////////////////////////////////////////////////////
0525     /// \brief Utility class for exchanging datas with the server
0526     ///        on the data channel
0527     ///
0528     ////////////////////////////////////////////////////////////
0529     class DataChannel;
0530 
0531     friend class DataChannel;
0532 
0533     ////////////////////////////////////////////////////////////
0534     // Member data
0535     ////////////////////////////////////////////////////////////
0536     TcpSocket   m_commandSocket; //!< Socket holding the control connection with the server
0537     std::string m_receiveBuffer; //!< Received command data that is yet to be processed
0538 };
0539 
0540 } // namespace sf
0541 
0542 
0543 #endif // SFML_FTP_HPP
0544 
0545 
0546 ////////////////////////////////////////////////////////////
0547 /// \class sf::Ftp
0548 /// \ingroup network
0549 ///
0550 /// sf::Ftp is a very simple FTP client that allows you
0551 /// to communicate with a FTP server. The FTP protocol allows
0552 /// you to manipulate a remote file system (list files,
0553 /// upload, download, create, remove, ...).
0554 ///
0555 /// Using the FTP client consists of 4 parts:
0556 /// \li Connecting to the FTP server
0557 /// \li Logging in (either as a registered user or anonymously)
0558 /// \li Sending commands to the server
0559 /// \li Disconnecting (this part can be done implicitly by the destructor)
0560 ///
0561 /// Every command returns a FTP response, which contains the
0562 /// status code as well as a message from the server. Some
0563 /// commands such as getWorkingDirectory() and getDirectoryListing()
0564 /// return additional data, and use a class derived from
0565 /// sf::Ftp::Response to provide this data. The most often used
0566 /// commands are directly provided as member functions, but it is
0567 /// also possible to use specific commands with the sendCommand() function.
0568 ///
0569 /// Note that response statuses >= 1000 are not part of the FTP standard,
0570 /// they are generated by SFML when an internal error occurs.
0571 ///
0572 /// All commands, especially upload and download, may take some
0573 /// time to complete. This is important to know if you don't want
0574 /// to block your application while the server is completing
0575 /// the task.
0576 ///
0577 /// Usage example:
0578 /// \code
0579 /// // Create a new FTP client
0580 /// sf::Ftp ftp;
0581 ///
0582 /// // Connect to the server
0583 /// sf::Ftp::Response response = ftp.connect("ftp://ftp.myserver.com");
0584 /// if (response.isOk())
0585 ///     std::cout << "Connected" << std::endl;
0586 ///
0587 /// // Log in
0588 /// response = ftp.login("laurent", "dF6Zm89D");
0589 /// if (response.isOk())
0590 ///     std::cout << "Logged in" << std::endl;
0591 ///
0592 /// // Print the working directory
0593 /// sf::Ftp::DirectoryResponse directory = ftp.getWorkingDirectory();
0594 /// if (directory.isOk())
0595 ///     std::cout << "Working directory: " << directory.getDirectory() << std::endl;
0596 ///
0597 /// // Create a new directory
0598 /// response = ftp.createDirectory("files");
0599 /// if (response.isOk())
0600 ///     std::cout << "Created new directory" << std::endl;
0601 ///
0602 /// // Upload a file to this new directory
0603 /// response = ftp.upload("local-path/file.txt", "files", sf::Ftp::Ascii);
0604 /// if (response.isOk())
0605 ///     std::cout << "File uploaded" << std::endl;
0606 ///
0607 /// // Send specific commands (here: FEAT to list supported FTP features)
0608 /// response = ftp.sendCommand("FEAT");
0609 /// if (response.isOk())
0610 ///     std::cout << "Feature list:\n" << response.getMessage() << std::endl;
0611 ///
0612 /// // Disconnect from the server (optional)
0613 /// ftp.disconnect();
0614 /// \endcode
0615 ///
0616 ////////////////////////////////////////////////////////////