📄 ftpclient.h
字号:
////////////////////////////////////////////////////////////////////////////////
//
// The official specification of the File Transfer Protocol (FTP) is the RFC 959.
// Most of the documentation are taken from this RFC.
// This is an implementation of an simple ftp client. I have tried to implement
// platform independent. For the communication i used the classes CBlockingSocket,
// CSockAddr, ... from David J. Kruglinski (Inside Visual C++). These classes are
// only small wrappers for the sockets-API.
// Further I used a smart pointer-implementation from Scott Meyers (Effective C++,
// More Effective C++, Effective STL).
// The implementation of the logon-sequence (with firewall support) was published
// in an article on Codeguru by Phil Anderson.
// The code for the parsing of the different FTP LIST responses is taken from
// D. J. Bernstein (http://cr.yp.to/ftpparse.html). I only wrapped the c-code in
// a class.
// I haven't tested the code on other platforms, but i think with little
// modifications it would compile.
//
// Copyright (c) 2004 Thomas Oswald
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INC_FTPCLIENT_H
#define INC_FTPCLIENT_H
// STL-includes
#include <memory>
#include <queue>
// other includes
#include "FTPDataTypes.h"
#include "BlockingSocket.h"
#include "FTPFileState.h"
#include "FTPListParse.h"
#include "FTPHelp.h"
using namespace nsHelper;
////////////////////////////////////////////////////////////////////////////////
/// Namespace for all FTP-related classes.
////////////////////////////////////////////////////////////////////////////////
namespace nsFTP
{
using namespace nsSocket;
/// @brief FTP client class
///
/// Use this class for all the ftp-client stuff such as
/// - logon server
/// - send and receive data
/// - get directory listing
/// - ...
///
/// @brief interface for notification
///
/// Derive your class from this base-class and register this class on CFTPClient.
/// For example you can use this for logging the sended and received commands.
class CFTPClient
{
public:
CFTPClient(IBlockingSocket* pSocket=nsSocket::CreateDefaultBlockingSocketInstance(),
unsigned int uiTimeout=10, unsigned int uiBufferSize=2048, unsigned int uiResponseWait=0);
virtual ~CFTPClient();
void SetNotification(CNotification *pNotification) { m_pNotification = pNotification;}
bool IsConnected();
bool IsTransferringData();
void SetResumeMode(bool fEnable=true);
bool Login(CLogonInfo& loginInfo);
int Logout();
CLogonInfo& LastLogonInfo() { return m_LastLogonInfo; }
bool List(CStringA strPath, TStringVector& vstrFileList, bool fPasv=false);
bool NameList(CStringA strPath, TStringVector& vstrFileList, bool fPasv=false);
bool List(CStringA strPath, TSpFTPFileStatusVector& vFileList, bool fPasv=false);
bool NameList(CStringA strPath, TSpFTPFileStatusVector& vFileList, bool fPasv=false);
int Delete(CStringA& strFile);
int Rename(CStringA& strOldName, CStringA& strNewName);
bool DownloadFile(CStringA strRemoteFile, CStringA strLocalFile,
CRepresentation& repType=CRepresentation(CType::Image()), bool fPasv=true);
bool UploadFile(CStringA& strLocalFile, CStringA& strRemoteFile, bool fStoreUnique=false,
CRepresentation& repType=CRepresentation(CType::Image()), bool fPasv=false);
int RemoveDirectory(CStringA& strDirectory);
int MakeDirectory(CStringA& strDirectory);
int PrintWorkingDirectory();
int ChangeToParentDirectory();
int ChangeWorkingDirectory(CStringA strDirectory);
int Passive(ULONG& ulIpAddress, USHORT& ushPort);
int DataPort(CStringA& strHostIP, USHORT ushPort);
int Abort();
int System();
int Noop();
int RepresentationType(CRepresentation& repType, DWORD dwSize=0);
int FileStructure(CStructure& crStructure);
int TransferMode(CTransferMode& crTransferMode);
int Allocate(int iReserveBytes, int* piMaxPageOrRecordSize=NULL);
int StructureMount(CStringA& strPath);
int SiteParameters(CStringA& strCmd);
int Status(CStringA& strPath);
int Help(CStringA& strTopic);
int Reinitialize();
int Restart(DWORD dwPosition);
int FileSize(CStringA& strPath, long& lSize);
int FileModificationTime(CStringA& strPath, tm& tmModificationTime);
int FileModificationTime(CStringA& strPath, CStringA& strModificationTime);
protected:
bool ExecuteDatachannelCommand(CDatachannelCmd crDatachannelCmd, CStringA& strPath, CRepresentation& representation,
bool fPasv, DWORD dwByteOffset, ITransferNotification* pObserver);
private:
bool TransferData(CDatachannelCmd& crDatachannelCmd, ITransferNotification* pObserver, IBlockingSocket& sckDataConnection);
bool OpenActiveDataConnection(IBlockingSocket& sckDataConnection, CDatachannelCmd& crDatachannelCmd, CStringA& strPath, DWORD dwByteOffset);
bool OpenPassiveDataConnection(IBlockingSocket& sckDataConnection, CDatachannelCmd& crDatachannelCmd, CStringA& strPath, DWORD dwByteOffset);
bool SendData(ITransferNotification* pObserver, IBlockingSocket& sckDataConnection);
bool ReceiveData(ITransferNotification* pObserver, IBlockingSocket& sckDataConnection);
CStringA GetCmdString(CDatachannelCmd& crDatachannelCmd, CStringA& strPath);
int SimpleErrorCheck(CReply& Reply);
bool SendCommand(CStringA& strCommand);
bool SendCommand(CStringA& strCommand, CReply& Reply);
bool GetResponse(CReply& Reply);
bool GetSingleResponseLine(CStringA& strResponse);
bool OpenControlChannel(CStringA& strServerHost, USHORT ushServerPort=DEFAULT_FTP_PORT);
void CloseControlChannel();
void ReportError(CStringA strErrorMsg, CStringA strFile, DWORD dwLineNr);
bool GetIpAddressFromResponse(CStringA strResponse, ULONG& ulIpAddress, USHORT& ushPort);
// data members
private:
unsigned int mc_uiTimeout; ///< timeout for socket-functions
unsigned int mc_uiResponseWait; ///< sleep time between receive calls to socket when getting the response
CStringA mc_strEolCharacterSequence; ///< end-of-line sequence of current operating system
CDataStack2 m_vBuffer; ///< buffer for sending and receiving
std::queue<CStringA> m_qResponseBuffer; ///< buffer for server-responses
std::auto_ptr<CRepresentation> m_apCurrentRepresentation; ///< representation currently set
std::auto_ptr<IBlockingSocket> m_apSckControlConnection; ///< socket for connection to ftp-server
bool m_fTransferInProgress; ///< if true, a file transfer is in progress
bool m_fAbortTransfer; ///< indicates that a running filetransfer should be canceled
bool m_fResumeIfPossible; ///< try to resume download/upload if possible
CLogonInfo m_LastLogonInfo; ///< logon-info, which was used at the last call of login
CNotification* m_pNotification;
};
}
#endif // INC_FTPCLIENT_H
// FTP commands - Overview
// simple commands
// CDUP <CRLF>
// QUIT <CRLF>
// REIN <CRLF>
// PASV <CRLF>
// STOU <CRLF>
// ABOR <CRLF>
// PWD <CRLF>
// SYST <CRLF>
// NOOP <CRLF>
// PORT <SP> <host-port> <CRLF>
// TYPE <SP> <type-code> <CRLF>
// CWD <SP> <pathname> <CRLF>
// MKD <SP> <pathname> <CRLF>
// SITE <SP> <string> <CRLF>
// HELP [<SP> <string>] <CRLF>
// DELE <SP> <pathname> <CRLF>
// RMD <SP> <pathname> <CRLF>
// STRU <SP> <structure-code> <CRLF>
// MODE <SP> <mode-code> <CRLF>
// STAT [<SP> <pathname>] <CRLF>
// ALLO <SP> <decimal-integer>
// [<SP> R <SP> <decimal-integer>] <CRLF>
// SMNT <SP> <pathname> <CRLF>
// commands for logon sequence
// USER <SP> <username> <CRLF>
// PASS <SP> <password> <CRLF>
// ACCT <SP> <account-information> <CRLF>
// commands for renaming
// RNFR <SP> <pathname> <CRLF>
// RNTO <SP> <pathname> <CRLF>
// RETR <SP> <pathname> <CRLF>
// STOR <SP> <pathname> <CRLF>
// APPE <SP> <pathname> <CRLF>
// REST <SP> <marker> <CRLF>
// LIST [<SP> <pathname>] <CRLF>
// NLST [<SP> <pathname>] <CRLF>
// non RFC-Commands
// SIZE <SP> <pathname> <CRLF>
// MDTM <SP> <pathname> <CRLF>
/** \class nsFTP::CStructure
In addition to different representation types, FTP allows the
structure of a file to be specified. Three file structures are
defined in FTP:
- file-structure, where there is no internal structure and
the file is considered to be a
continuous sequence of data bytes,
- record-structure, where the file is made up of sequential
records,
- and page-structure, where the file is made up of independent
indexed pages.
File-structure is the default to be assumed if the STRUcture
command has not been used but both file and record structures
must be accepted for "text" files (i.e., files with TYPE ASCII
or EBCDIC) by all FTP implementations. The structure of a file
will affect both the transfer mode of a file (see the Section
on Transmission Modes) and the interpretation and storage of
the file.
The "natural" structure of a file will depend on which host
stores the file. A source-code file will usually be stored on
an IBM Mainframe in fixed length records but on a DEC TOPS-20
as a stream of characters partitioned into lines, for example
by <CRLF>. If the transfer of files between such disparate
sites is to be useful, there must be some way for one site to
recognize the other's assumptions about the file.
With some sites being naturally file-oriented and others
naturally record-oriented there may be problems if a file with
one structure is sent to a host oriented to the other. If a
text file is sent with record-structure to a host which is file
oriented, then that host should apply an internal
transformation to the file based on the record structure.
Obviously, this transformation should be useful, but it must
also be invertible so that an identical file may be retrieved
using record structure.
In the case of a file being sent with file-structure to a
record-oriented host, there exists the question of what
criteria the host should use to divide the file into records
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -