⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftpclnt.cpp

📁 Crimson编辑器的英文版,完成从韩文版变成英文版的移植,并且附带可执行文件和注册表文件,无需原先的安装包,是改写编辑器的最理想选择.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#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 + -