📄 ftpclnt.cpp
字号:
case WSAEPROTONOSUPPORT: m_szResponseMessage = "The specified port is not supported."; break;
case WSAEPROTOTYPE: m_szResponseMessage = "The specified port is the wrong type for this socket."; break;
case WSAESOCKTNOSUPPORT: m_szResponseMessage = "The specified socket type is not supported in this address family."; break;
default: m_szResponseMessage = lpszDefaultErrorMessage; break;
}
return TRUE;
}
BOOL CFtpClient::EstablishDataChannel(BOOL bPassive, LPCTSTR lpszCommand)
{
CString szMessage, szString, szAddress; INT nPortNum;
if( m_bIsDataChannelEstablished ) return FALSE; // data channel is established already
if( ! bPassive ) { // active mode
if( ! ListenServer(szAddress, nPortNum) ) return FALSE;
if( ! StringFromAddress( szString, szAddress, nPortNum ) ) return FALSE;
szMessage.Format("PORT %s\r\n", szString);
if( ! WriteToControlChannel(szMessage) ) return FALSE;
if( ! ReadFromControlChannel() ) return FALSE; // 200 PORT command successful.
if( m_nResponseCode < 200 || m_nResponseCode >= 300 ) return FALSE;
szMessage.Format("%s\r\n", lpszCommand);
if( ! WriteToControlChannel(szMessage) ) return FALSE;
if( ! ReadFromControlChannel() ) return FALSE; // 150 Opening ASCII mode data connection for file list.
if( m_nResponseCode < 100 || m_nResponseCode >= 200 ) return FALSE;
if( ! AcceptDataChannel() ) return FALSE;
} else { // passive mode
if( ! WriteToControlChannel("PASV\r\n") ) return FALSE;
if( ! ReadFromControlChannel() ) return FALSE; // 227 Entering Passive Mode (xxx,xxx,xxx,xxx,xxx,xxx).
if( m_nResponseCode < 200 || m_nResponseCode >= 300 ) return FALSE;
INT i = m_szResponseMessage.Find('('); if( i < 0 ) return FALSE;
INT j = m_szResponseMessage.Find(')'); if( j < 0 ) return FALSE;
szString = m_szResponseMessage.Mid(i+1, (j-i)-1);
szMessage.Format("%s\r\n", lpszCommand);
if( ! WriteToControlChannel(szMessage) ) return FALSE;
if( ! AddressFromString(szAddress, nPortNum, szString) ) return FALSE;
if( ! ConnectDataChannel(szAddress, nPortNum) ) return FALSE;
if( ! ReadFromControlChannel() ) return FALSE; // 150 Opening ASCII mode data connection for file list.
if( m_nResponseCode < 100 || m_nResponseCode >= 200 ) return FALSE;
}
m_bIsDataChannelEstablished = TRUE;
m_bPassiveModeDataChannel = bPassive;
return TRUE;
}
BOOL CFtpClient::DestroyDataChannel()
{
if( ! m_bIsDataChannelEstablished ) return FALSE; // no data chennel is established yet
if( ! m_bPassiveModeDataChannel ) { // active mode
if( ! CloseDataChannel() ) return FALSE;
if( ! CloseServer() ) return FALSE;
if( ! ReadFromControlChannel() ) return FALSE; // 226 Transfer complete
if( m_nResponseCode < 200 || m_nResponseCode >= 300 ) return FALSE;
} else { // passive mode
if( ! CloseDataChannel() ) return FALSE;
if( ! ReadFromControlChannel() ) return FALSE; // 226 Transfer complete.
if( m_nResponseCode < 200 || m_nResponseCode >= 300 ) return FALSE;
}
m_bIsDataChannelEstablished = FALSE;
m_bPassiveModeDataChannel = FALSE;
return TRUE;
}
BOOL CFtpClient::StringFromAddress(CString & rString, LPCTSTR lpszAddress, INT nPortNum)
{
CString szAddress = lpszAddress;
INT i, len = szAddress.GetLength();
for( i = 0; i < len; i++ ) if( szAddress.GetAt(i) == '.' ) szAddress.SetAt(i, ',');
rString.Format("%s,%d,%d", szAddress, nPortNum / 256, nPortNum % 256);
return TRUE;
}
BOOL CFtpClient::AddressFromString(CString & rAddress, INT & rPortNum, LPCTSTR lpszString)
{
INT i; CString szString = lpszString;
i = szString.ReverseFind(',');
rPortNum = atoi( szString.Mid(i+1) );
szString = szString.Left(i);
i = szString.ReverseFind(',');
rPortNum += 256 * atoi( szString.Mid(i+1) );
rAddress = szString.Left(i); INT len = rAddress.GetLength();
for( i = 0; i < len; i++ ) if( rAddress.GetAt(i) == ',' ) rAddress.SetAt(i, '.');
return TRUE;
}
BOOL CFtpClient::WriteToControlChannel(LPCTSTR lpszString)
{
if( ! m_pControlWriteArchive ) return FALSE;
m_pControlWriteArchive->WriteString(lpszString);
m_pControlWriteArchive->Flush();
// lpszString already contains linefeed
TRACE1("FTP-SEND: %s", lpszString);
return TRUE;
}
BOOL CFtpClient::ReadFromControlChannel()
{
CString szResponseMessage, szCode;
if( ! m_pControlReadArchive ) return FALSE;
// The client can identify the last line of the response as follows:
// it begins with three ASCII digits and a space;
// previous lines do not. The three digits form a code.
if( ! m_pControlReadArchive->ReadString(szResponseMessage) ) return FALSE;
m_szResponseMessage = szResponseMessage;
szCode = szResponseMessage.Mid(0,3); m_nResponseCode = atoi(szCode);
// Codes between 100 and 199 indicate marks;
// codes between 200 and 399 indicate acceptance;
// codes between 400 and 599 indicate rejection.
while( szResponseMessage[3] != ' ' || szCode.Compare("100") < 0 || szCode.Compare("999") > 0 ) {
if( ! m_pControlReadArchive->ReadString(szResponseMessage) ) return FALSE;
m_szResponseMessage += CString("\n") + szResponseMessage;
szCode = szResponseMessage.Mid(0,3); m_nResponseCode = atoi(szCode);
}
TRACE1("FTP-RECV: %s\n", m_szResponseMessage);
return TRUE;
}
BOOL CFtpClient::ReadFromDataChannel(CString & rString)
{
if( ! m_pDataReadArchive ) return FALSE;
return m_pDataReadArchive->ReadString(rString);
}
UINT CFtpClient::ReadFromDataChannel(VOID * lpBuf, UINT nMax)
{
if( ! m_pDataReadArchive ) return 0;
return m_pDataReadArchive->Read(lpBuf, nMax);
}
BOOL CFtpClient::WriteToDataChannel(VOID * lpBuf, UINT nMax)
{
if( ! m_pDataReadArchive ) return FALSE;
m_pDataWriteArchive->Write(lpBuf, nMax); return TRUE;
}
BOOL CFtpClient::OpenControlChannel(LPCTSTR lpszServer, INT nPortNum)
{
if( ! (m_pControlSocket = new CSocket) ) return FALSE;
if( ! m_pControlSocket->Create() ) {
SetSocketErrorMessage( m_pControlSocket->GetLastError(), "An error occured in creating socket object." );
return FALSE;
}
if( ! m_pControlSocket->Connect(lpszServer, nPortNum) ) {
SetSocketErrorMessage( m_pControlSocket->GetLastError(), "An error occured in connecting control channel." );
return FALSE;
}
if( ! (m_pControlSocketFile = new CSocketFile(m_pControlSocket)) ) return FALSE;
if( ! (m_pControlReadArchive = new CArchive(m_pControlSocketFile, CArchive::load)) ) return FALSE;
if( ! (m_pControlWriteArchive = new CArchive(m_pControlSocketFile, CArchive::store)) ) return FALSE;
return TRUE;
}
BOOL CFtpClient::CloseControlChannel()
{
try {
if( m_pControlReadArchive ) delete m_pControlReadArchive;
m_pControlReadArchive = NULL;
if( m_pControlWriteArchive ) delete m_pControlWriteArchive;
m_pControlWriteArchive = NULL;
if( m_pControlSocketFile ) delete m_pControlSocketFile;
m_pControlSocketFile = NULL;
if( m_pControlSocket ) delete m_pControlSocket;
m_pControlSocket = NULL;
} catch( CException * ex ) {
ex->ReportError(MB_OK | MB_ICONSTOP);
ex->Delete(); return FALSE;
}
return TRUE;
}
BOOL CFtpClient::ListenServer(CString & rAddress, INT & rPortNum)
{
CString szAddress; UINT nPortNum;
if( ! m_pControlSocket ) return FALSE;
if( ! m_pControlSocket->GetSockName(rAddress, nPortNum) ) return FALSE;
if( ! (m_pServerSocket = new CSocket) ) return FALSE;
if( ! m_pServerSocket->Create() ) return FALSE;
if( ! m_pServerSocket->Listen() ) return FALSE;
if( ! m_pServerSocket->GetSockName(szAddress, nPortNum) ) return FALSE;
rPortNum = (INT)nPortNum;
return TRUE;
}
BOOL CFtpClient::CloseServer()
{
try {
if( m_pServerSocket ) delete m_pServerSocket;
m_pServerSocket = NULL;
} catch( CException * ex ) {
ex->ReportError(MB_OK | MB_ICONSTOP);
ex->Delete(); return FALSE;
}
return TRUE;
}
BOOL CFtpClient::AcceptDataChannel()
{
if( ! m_pServerSocket || m_pDataSocket ) return FALSE;
if( ! (m_pDataSocket = new CSocket) ) return FALSE;
if( ! m_pServerSocket->Accept( * m_pDataSocket ) ) return FALSE;
if( ! (m_pDataSocketFile = new CSocketFile(m_pDataSocket)) ) return FALSE;
if( ! (m_pDataReadArchive = new CArchive(m_pDataSocketFile, CArchive::load)) ) return FALSE;
if( ! (m_pDataWriteArchive = new CArchive(m_pDataSocketFile, CArchive::store)) ) return FALSE;
return TRUE;
}
BOOL CFtpClient::ConnectDataChannel(LPCTSTR lpszServer, INT nPortNum)
{
if( m_pDataSocket ) return FALSE;
if( ! (m_pDataSocket = new CSocket) ) return FALSE;
if( ! m_pDataSocket->Create() ) return FALSE;
m_pDataSocket->Connect(lpszServer, nPortNum); /* WSAEWOULDBLOCK error for CAsyncSocket */
if( ! (m_pDataSocketFile = new CSocketFile(m_pDataSocket)) ) return FALSE;
if( ! (m_pDataReadArchive = new CArchive(m_pDataSocketFile, CArchive::load)) ) return FALSE;
if( ! (m_pDataWriteArchive = new CArchive(m_pDataSocketFile, CArchive::store)) ) return FALSE;
return TRUE;
}
BOOL CFtpClient::CloseDataChannel()
{
try {
if( m_pDataReadArchive ) delete m_pDataReadArchive;
m_pDataReadArchive = NULL;
if( m_pDataWriteArchive ) delete m_pDataWriteArchive;
m_pDataWriteArchive = NULL;
if( m_pDataSocketFile ) delete m_pDataSocketFile;
m_pDataSocketFile = NULL;
if( m_pDataSocket ) delete m_pDataSocket;
m_pDataSocket = NULL;
} catch( CException * ex ) {
ex->ReportError(MB_OK | MB_ICONSTOP);
ex->Delete(); return FALSE;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -