📄 ftpclnt.cpp
字号:
#include "stdafx.h"
#include "FtpClnt.h"
CFtpClient::CFtpClient()
{
m_pControlSocket = NULL;
m_pControlSocketFile = NULL;
m_pControlReadArchive = NULL;
m_pControlWriteArchive = NULL;
m_pServerSocket = NULL;
m_pDataSocket = NULL;
m_pDataSocketFile = NULL;
m_pDataReadArchive = NULL;
m_pDataWriteArchive = NULL;
m_bIsDataChannelEstablished = FALSE;
m_bPassiveModeDataChannel = FALSE;
m_bIsRemoteFileOpen = FALSE;
m_bOpenRemoteFileToGet = FALSE;
m_nResponseCode = 0x00;
m_szResponseMessage = "";
}
CFtpClient::~CFtpClient()
{
try { if( m_pDataReadArchive ) delete m_pDataReadArchive; } catch( CException * ex ) { ex->Delete(); }
try { if( m_pDataWriteArchive ) delete m_pDataWriteArchive; } catch( CException * ex ) { ex->Delete(); }
try { if( m_pDataSocketFile ) delete m_pDataSocketFile; } catch( CException * ex ) { ex->Delete(); }
try { if( m_pDataSocket ) delete m_pDataSocket; } catch( CException * ex ) { ex->Delete(); }
try { if( m_pServerSocket ) delete m_pServerSocket; } catch( CException * ex ) { ex->Delete(); }
try { if( m_pControlReadArchive ) delete m_pControlReadArchive; } catch( CException * ex ) { ex->Delete(); }
try { if( m_pControlWriteArchive ) delete m_pControlWriteArchive; } catch( CException * ex ) { ex->Delete(); }
try { if( m_pControlSocketFile ) delete m_pControlSocketFile; } catch( CException * ex ) { ex->Delete(); }
try { if( m_pControlSocket ) delete m_pControlSocket; } catch( CException * ex ) { ex->Delete(); }
}
BOOL CFtpClient::Open(LPCTSTR lpszServer, INT nPortNum)
{
if( ! OpenControlChannel(lpszServer, nPortNum) ) return FALSE;
if( ! ReadFromControlChannel() ) return FALSE; // 220 xxx FTP server (Version x.xxx Wek Mon DD HH:MM:SS EST 1997) ready.
if( m_nResponseCode < 200 || m_nResponseCode >= 300 ) return FALSE;
return TRUE;
}
BOOL CFtpClient::Close()
{
if( ! CloseControlChannel() ) return FALSE;
return TRUE;
}
BOOL CFtpClient::LogOn(LPCTSTR lpszUser, LPCTSTR lpszPassword)
{
CString szString;
szString.Format("USER %s\r\n", lpszUser);
if( ! WriteToControlChannel( szString ) ) return FALSE;
if( ! ReadFromControlChannel() ) return FALSE; // 331 Password required for xxx.
if( m_nResponseCode < 200 || m_nResponseCode >= 400 ) return FALSE;
// check if this server does not need password...
if( m_nResponseCode == 230 ) return TRUE;
szString.Format("PASS %s\r\n", lpszPassword);
if( ! WriteToControlChannel( szString ) ) return FALSE;
if( ! ReadFromControlChannel() ) return FALSE; // 230 User xxx logged in.
if( m_nResponseCode < 200 || m_nResponseCode >= 300 ) return FALSE;
return TRUE;
}
BOOL CFtpClient::LogOff()
{
if( ! WriteToControlChannel("QUIT\r\n") ) return FALSE;
if( ! ReadFromControlChannel() ) return FALSE;
if( m_nResponseCode < 200 || m_nResponseCode >= 300 ) return FALSE;
return TRUE;
}
BOOL CFtpClient::GetCurrentDirectory(CString & szDirName)
{
if( ! WriteToControlChannel("PWD\r\n") ) return FALSE;
if( ! ReadFromControlChannel() ) return FALSE;
if( m_nResponseCode < 200 || m_nResponseCode >= 300 ) return FALSE;
INT i = m_szResponseMessage.Find('"'); if( i < 0 ) return FALSE;
INT j = m_szResponseMessage.Find('"', i+1); if( j < 0 ) return FALSE;
szDirName = m_szResponseMessage.Mid(i+1, (j-i)-1);
return TRUE;
}
BOOL CFtpClient::SetCurrentDirectory(LPCTSTR lpszDirName)
{
CString szMessage; szMessage.Format("CWD %s\r\n", lpszDirName);
if( ! WriteToControlChannel(szMessage) ) return FALSE;
if( ! ReadFromControlChannel() ) return FALSE;
if( m_nResponseCode < 200 || m_nResponseCode >= 300 ) return FALSE;
return TRUE;
}
BOOL CFtpClient::SendCommand(LPCTSTR lpszCommand)
{
CString szMessage; szMessage.Format("%s\r\n", lpszCommand);
if( ! WriteToControlChannel(szMessage) ) return FALSE;
if( ! ReadFromControlChannel() ) return FALSE;
if( m_nResponseCode < 200 || m_nResponseCode >= 300 ) return FALSE;
return TRUE;
}
BOOL CFtpClient::SetFileTransferType(BOOL bBinary)
{
CString szMessage;
szMessage.Format(bBinary ? "TYPE I\r\n" : "TYPE A\r\n");
if( ! WriteToControlChannel(szMessage) ) return FALSE;
if( ! ReadFromControlChannel() ) return FALSE; // 200 Type set to I
if( m_nResponseCode < 200 || m_nResponseCode >= 300 ) return FALSE;
return TRUE;
}
BOOL CFtpClient::RenameFile(LPCTSTR lpszExisting, LPCTSTR lpszNewName)
{
CString szMessage;
szMessage.Format("RNFR %s\r\n", lpszExisting);
if( ! WriteToControlChannel(szMessage) ) return FALSE;
if( ! ReadFromControlChannel() ) return FALSE; // 350 File exists, ready for destination name.
if( m_nResponseCode < 300 || m_nResponseCode >= 400 ) return FALSE;
szMessage.Format("RNTO %s\r\n", lpszNewName);
if( ! WriteToControlChannel(szMessage) ) return FALSE;
if( ! ReadFromControlChannel() ) return FALSE; // 250 RNTO command successful.
if( m_nResponseCode < 200 || m_nResponseCode >= 300 ) return FALSE;
return TRUE;
}
BOOL CFtpClient::ListDirectory(CStringArray & arrList, LPCTSTR lpszFilter, BOOL bPassive)
{
CString szCommand = "LIST";
if( lpszFilter ) szCommand.Format("LIST %s", lpszFilter);
if( ! EstablishDataChannel(bPassive, szCommand) ) return FALSE;
CString szString; arrList.RemoveAll();
while( ReadFromDataChannel(szString) ) arrList.Add(szString);
if( ! DestroyDataChannel() ) return FALSE;
return TRUE;
}
BOOL CFtpClient::GetFile(LPCTSTR lpszRemoteFile, LPCTSTR lpszLocalFile, BOOL bBinary, BOOL bPassive)
{
CFile localFile; TCHAR szBuffer[FTP_TRANSFER_BUFFER_SIZE];
if( ! OpenFile(TRUE, lpszRemoteFile, bBinary, bPassive) ) return FALSE;
if( ! localFile.Open(lpszLocalFile, CFile::modeReadWrite | CFile::modeCreate) ) return FALSE;
UINT nRead, nTotalRead = 0;
while( TRUE ) {
try {
nRead = ReadFromDataChannel(szBuffer, FTP_TRANSFER_BUFFER_SIZE);
localFile.Write(szBuffer, nRead); nTotalRead += nRead;
} catch( CException * ex ) {
localFile.Close(); throw ex;
}
if( nRead < FTP_TRANSFER_BUFFER_SIZE ) break;
}
localFile.Close();
if( ! CloseFile() ) return FALSE;
return TRUE;
}
BOOL CFtpClient::PutFile(LPCTSTR lpszLocalFile, LPCTSTR lpszRemoteFile, BOOL bBinary, BOOL bPassive)
{
CFile localFile; TCHAR szBuffer[FTP_TRANSFER_BUFFER_SIZE];
if( ! OpenFile(FALSE, lpszRemoteFile, bBinary, bPassive) ) return FALSE;
if( ! localFile.Open(lpszLocalFile, CFile::modeRead) ) return FALSE;
UINT nRead, nTotalRead = 0;
while( TRUE ) {
try {
nRead = localFile.Read(szBuffer, FTP_TRANSFER_BUFFER_SIZE);
WriteToDataChannel(szBuffer, nRead); nTotalRead += nRead;
} catch( CException * ex ) {
localFile.Close(); throw ex;
}
if( nRead < FTP_TRANSFER_BUFFER_SIZE ) break;
}
localFile.Close();
if( ! CloseFile() ) return FALSE;
return TRUE;
}
BOOL CFtpClient::OpenFile(BOOL bGet, LPCTSTR lpszRemoteFile, BOOL bBinary, BOOL bPassive)
{
CString szCommand;
if( m_bIsRemoteFileOpen ) return FALSE; // remote file is open already
if( bGet ) szCommand.Format("RETR %s", lpszRemoteFile);
else szCommand.Format("STOR %s", lpszRemoteFile);
// type set to binary
if( ! SetFileTransferType(bBinary) ) return FALSE;
if( ! EstablishDataChannel(bPassive, szCommand) ) return FALSE;
m_bIsRemoteFileOpen = TRUE;
m_bOpenRemoteFileToGet = bGet;
return TRUE;
}
BOOL CFtpClient::CloseFile()
{
if( ! m_bIsRemoteFileOpen ) return FALSE; // remote file is not open yet
if( ! DestroyDataChannel() ) return FALSE;
m_bIsRemoteFileOpen = FALSE;
m_bOpenRemoteFileToGet = FALSE;
return TRUE;
}
UINT CFtpClient::ReadFile(VOID * lpBuf, UINT nMax)
{
if( ! m_bIsRemoteFileOpen || ! m_bOpenRemoteFileToGet ) return FALSE;
return ReadFromDataChannel(lpBuf, nMax);
}
BOOL CFtpClient::WriteFile(VOID * lpBuf, UINT nMax)
{
if( ! m_bIsRemoteFileOpen || m_bOpenRemoteFileToGet ) return FALSE;
return WriteToDataChannel(lpBuf, nMax);
}
BOOL CFtpClient::SetSocketErrorMessage(INT nErrorCode, LPCTSTR lpszDefaultErrorMessage)
{
switch( nErrorCode ) {
case WSANOTINITIALISED: m_szResponseMessage = "A successful AfxSocketInit must occur before using this API."; break;
case WSAENETDOWN: m_szResponseMessage = "The Windows Sockets implementation detected that the network subsystem failed."; break;
case WSAEADDRINUSE: m_szResponseMessage = "The specified address is already in use."; break;
case WSAEINPROGRESS: m_szResponseMessage = "A blocking Windows Sockets call is in progress."; break;
case WSAEADDRNOTAVAIL: m_szResponseMessage = "The specified address is not available from the local machine."; break;
case WSAEAFNOSUPPORT: m_szResponseMessage = "Addresses in the specified family cannot be used with this socket."; break;
case WSAECONNREFUSED: m_szResponseMessage = "The attempt to connect was rejected."; break;
case WSAEDESTADDRREQ: m_szResponseMessage = "A destination address is required."; break;
case WSAEFAULT: m_szResponseMessage = "The nSockAddrLen argument is incorrect."; break;
case WSAEINVAL: m_szResponseMessage = "Invalid host address."; break;
case WSAEISCONN: m_szResponseMessage = "The socket is already connected."; break;
case WSAEMFILE: m_szResponseMessage = "No more file descriptors are available."; break;
case WSAENETUNREACH: m_szResponseMessage = "The network cannot be reached from this host at this time."; break;
case WSAENOBUFS: m_szResponseMessage = "No buffer space is available. The socket cannot be connected."; break;
case WSAENOTSOCK: m_szResponseMessage = "The descriptor is not a socket."; break;
case WSAETIMEDOUT: m_szResponseMessage = "Attempt to connect timed out without establishing a connection."; break;
case WSAEWOULDBLOCK: m_szResponseMessage = "The socket is marked as nonblocking and the connection cannot be completed immediately."; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -