📄 ftpcontrolsocket.cpp
字号:
if (GetReplyCode() == 2) // we're logged on
{
ShowStatus(IDS_STATUSMSG_CONNECTED,0);
m_pOwner->SetConnected(TRUE);
ResetOperation(FZ_REPLY_OK);
return;
}
else
//GSS authentication complete but we still have to go through the standard logon procedure
m_Operation.nOpState = CONNECT_INIT;
}
if (m_Operation.nOpState==CONNECT_INIT)
{
if (logontype)
{
CString str;
str.Format(IDS_STATUSMSG_FWCONNECT,hostname);
ShowStatus(str,0);
}
m_Operation.nOpState++;
}
else if (!bSkipReply)
{
m_Operation.nOpState=logonseq[logontype][m_Operation.nOpState+GetReplyCode()-1]; //get next command from array
switch(m_Operation.nOpState)
{
case ER: // ER means summat has gone wrong
DoClose();
return;
case LO: //LO means we are logged on
m_pOwner->SetConnected(TRUE);
ShowStatus(IDS_STATUSMSG_CONNECTED,0);
ResetOperation(FZ_REPLY_OK);
return;
}
}
// go through appropriate logon procedure
int i = logonseq[logontype][m_Operation.nOpState];
if (m_pGssLayer)
{
if ((i == 0 || i == 6 || i == 9 || i == 10) &&
(m_CurrentServer.user == "anonymous" || m_CurrentServer.user == ""))
{
//Extract user from kerberos ticket
char str[256];
if (m_pGssLayer->GetUserFromKrbTicket(str))
m_CurrentServer.user = str;
if (m_CurrentServer.user == "")
{
CGssNeedUserRequestData *pData = new CGssNeedUserRequestData;
pData->nRequestID = m_pOwner->GetNextAsyncRequestID();
pData->nOldOpState = m_Operation.nOpState;
m_Operation.nOpState = CONNECT_GSS_NEEDUSER;
if (!PostMessage(m_pOwner->m_hOwnerWnd, m_pOwner->m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_ASYNCREQUEST, FZ_ASYNCREQUEST_GSS_NEEDUSER), (LPARAM)pData))
delete pData;
return;
}
}
else if ((i == 1 || i == 11) && (m_CurrentServer.pass == "anon@" || m_CurrentServer.pass == ""))
{
CGssNeedPassRequestData *pData=new CGssNeedPassRequestData;
pData->nRequestID=m_pOwner->GetNextAsyncRequestID();
pData->nOldOpState = m_Operation.nOpState;
m_Operation.nOpState = CONNECT_GSS_NEEDPASS;
if (!PostMessage(m_pOwner->m_hOwnerWnd, m_pOwner->m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_ASYNCREQUEST, FZ_ASYNCREQUEST_GSS_NEEDPASS), (LPARAM)pData))
delete pData;
return;
}
}
switch(logonseq[logontype][m_Operation.nOpState])
{
case 0:
temp="USER "+m_CurrentServer.user;
break;
case 1:
temp="PASS "+m_CurrentServer.pass;
break;
case 2:
temp="ACCT "+CCrypt::decrypt(COptions::GetOption(OPTION_FWPASS));
break;
case 3:
temp="USER "+COptions::GetOption(OPTION_FWUSER);
break;
case 4:
temp="PASS "+CCrypt::decrypt(COptions::GetOption(OPTION_FWPASS));
break;
case 5:
temp="SITE "+hostname;
break;
case 6:
temp="USER "+m_CurrentServer.user+"@"+hostname;
break;
case 7:
temp="OPEN "+hostname;
break;
case 8:
temp="USER "+COptions::GetOption(OPTION_FWUSER)+"@"+hostname;
break;
case 9:
temp="USER "+m_CurrentServer.user+"@"+hostname+" "+COptions::GetOption(OPTION_FWUSER);
break;
case 10:
temp="USER "+m_CurrentServer.user+"@"+COptions::GetOption(OPTION_FWUSER)+"@"+hostname;
break;
case 11:
temp="PASS "+m_CurrentServer.pass+"@"+CCrypt::decrypt(COptions::GetOption(OPTION_FWPASS));
break;
}
// send command, get response
if(!Send(temp))
return;
}
#define BUFFERSIZE 4096
void CFtpControlSocket::OnReceive(int nErrorCode)
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("OnReceive(%d) OpMode=%d OpState=%d"), nErrorCode, m_Operation.nOpMode, m_Operation.nOpState);
m_LastRecvTime=CTime::GetCurrentTime();
PostMessage(m_pOwner->m_hOwnerWnd, m_pOwner->m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_SOCKETSTATUS, FZ_SOCKETSTATUS_RECV), 0);
if (!m_pOwner->IsConnected())
{
if (!m_Operation.nOpMode)
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_INFO, _T("Socket has been closed, don't process receive") );
return;
}
m_MultiLine=_T("");
CString str;
str.Format(IDS_STATUSMSG_CONNECTEDWITH,m_ServerName);
ShowStatus(str,0);
m_pOwner->SetConnected(TRUE);
}
char *buffer=new char[BUFFERSIZE];
AsyncSelect(FD_CLOSE);
int numread=Receive(buffer, BUFFERSIZE);
while (numread!=SOCKET_ERROR && numread)
{
for (int i=0;i<numread;i++)
{
if ((buffer[i]=='\r')||(buffer[i]=='\n')||(buffer[i]==0))
{
if (!m_RecvBuffer.empty() && m_RecvBuffer.back()!=_T("") )
{
ShowStatus(m_RecvBuffer.back(), 3);
//Check for multi-line responses
if (m_RecvBuffer.back().GetLength()>3)
{
if (m_MultiLine!=_T(""))
{
if (m_RecvBuffer.back().Left(4)!=m_MultiLine)
m_RecvBuffer.pop_back();
else // end of multi-line found
{
m_MultiLine=_T("");
m_pOwner->PostThreadMessage(m_pOwner->m_nInternalMessageID,FZAPI_THREADMSG_PROCESSREPLY,0);
}
}
// start of new multi-line
else if (m_RecvBuffer.back()[3]=='-')
{
// DDD<SP> is the end of a multi-line response
m_MultiLine=m_RecvBuffer.back().Left(3)+' ';
m_RecvBuffer.pop_back();
}
else
m_pOwner->PostThreadMessage(m_pOwner->m_nInternalMessageID,FZAPI_THREADMSG_PROCESSREPLY,0);
}
else
m_RecvBuffer.pop_back();
m_RecvBuffer.push_back(_T(""));
}
}
else
{
//The command may only be 2000 chars long. This ensures that a malicious user can't
//send extremely large commands to fill the memory of the server
if (m_RecvBuffer.empty())
m_RecvBuffer.push_back(_T(""));
if (m_RecvBuffer.back().GetLength()<2000)
m_RecvBuffer.back()+=buffer[i];
}
}
if (numread<BUFFERSIZE)
break;
numread=Receive(buffer,BUFFERSIZE);
if (numread && numread!=SOCKET_ERROR)
{
m_LastRecvTime=CTime::GetCurrentTime();
PostMessage(m_pOwner->m_hOwnerWnd, m_pOwner->m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_SOCKETSTATUS, FZ_SOCKETSTATUS_RECV), 0);
}
}
delete buffer;
if (numread==SOCKET_ERROR)
if (GetLastError()!=WSAEWOULDBLOCK)
{
ShowStatus(IDS_STATUSMSG_DISCONNECTED,1);
DoClose();
return;
}
AsyncSelect(FD_READ | FD_WRITE | FD_CLOSE);
}
void CFtpControlSocket::ProcessReply()
{
if (m_RecvBuffer.empty())
return;
CString reply=m_RecvBuffer.front();
if ( reply==_T("") )
return;
if (m_bKeepAliveActive)
{
m_bKeepAliveActive=FALSE;
m_pOwner->PostThreadMessage(m_pOwner->m_nInternalMessageID,FZAPI_THREADMSG_POSTKEEPALIVE,0);
}
else if (m_Operation.nOpMode&CSMODE_CONNECT)
LogOnToServer();
else if (m_Operation.nOpMode& (CSMODE_COMMAND|CSMODE_CHMOD) )
{
if (GetReplyCode()==2 || GetReplyCode()==3)
ResetOperation(FZ_REPLY_OK);
else
ResetOperation(FZ_REPLY_ERROR);
}
else if (m_Operation.nOpMode&CSMODE_TRANSFER)
{
FileTransfer(0);
}
else if (m_Operation.nOpMode&CSMODE_LIST)
List(FALSE);
else if (m_Operation.nOpMode&CSMODE_DELETE)
Delete( _T(""),CServerPath());
else if (m_Operation.nOpMode&CSMODE_RMDIR)
RemoveDir( _T(""),CServerPath());
else if (m_Operation.nOpMode&CSMODE_MKDIR)
MakeDir(CServerPath());
else if (m_Operation.nOpMode&CSMODE_RENAME)
Rename(_T(""), _T(""), CServerPath(), CServerPath());
if (!m_RecvBuffer.empty())
m_RecvBuffer.pop_front();
}
void CFtpControlSocket::OnConnect(int nErrorCode)
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("OnConnect(%d) OpMode=%d OpState=%d"), nErrorCode, m_Operation.nOpMode, m_Operation.nOpState);
if (!m_Operation.nOpMode)
{
if (!m_pOwner->IsConnected())
DoClose();
return;
}
if (!nErrorCode)
{
if (!m_pOwner->IsConnected())
{
m_MultiLine=_T("");
m_pOwner->SetConnected(TRUE);
CString str;
str.Format(m_pSslLayer ? IDS_STATUSMSG_CONNECTEDWITHSSL : IDS_STATUSMSG_CONNECTEDWITH, m_ServerName);
ShowStatus(str,0);
}
}
else
{
if (nErrorCode == WSAHOST_NOT_FOUND)
ShowStatus(IDS_ERRORMSG_CANTRESOLVEHOST, 1);
DoClose();
}
}
BOOL CFtpControlSocket::Send(CString str)
{
USES_CONVERSION;
ShowStatus(str,2);
str+="\r\n";
LPCSTR lpszAsciiSend=T2CA(str);
int res = CAsyncSocketEx::Send(lpszAsciiSend,strlen(lpszAsciiSend));
if (!res)
{
if (GetLastError()!=WSAEWOULDBLOCK)
{
ShowStatus(IDS_ERRORMSG_CANTSENDCOMMAND,1);
DoClose();
return FALSE;
}
}
m_LastSendTime=CTime::GetCurrentTime();
PostMessage(m_pOwner->m_hOwnerWnd, m_pOwner->m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_SOCKETSTATUS, FZ_SOCKETSTATUS_SEND), 0);
return TRUE;
}
int CFtpControlSocket::GetReplyCode()
{
if (m_RecvBuffer.empty())
return 0;
CString str = m_RecvBuffer.front();
if (str == "")
return 0;
else
return str[0]-'0';
}
void CFtpControlSocket::DoClose(int nError /*=0*/)
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("DoClose(%d) OpMode=%d OpState=%d"), nError, m_Operation.nOpMode, m_Operation.nOpState);
m_bCheckForTimeout=TRUE;
m_pOwner->SetConnected(FALSE);
m_bKeepAliveActive=FALSE;
PostMessage(m_pOwner->m_hOwnerWnd, m_pOwner->m_nReplyMessageID, FZ_MSG_MAKEMSG(FZ_MSG_SECURESERVER, FALSE), 0);
if (nError & FZ_REPLY_CRITICALERROR)
nError |= FZ_REPLY_ERROR;
ResetOperation(FZ_REPLY_ERROR|FZ_REPLY_DISCONNECTED|nError);
m_RecvBuffer.clear();
m_MultiLine="";
CControlSocket::Close();
}
void CFtpControlSocket::Disconnect()
{
ASSERT(!m_Operation.nOpMode);
m_Operation.nOpMode=CSMODE_DISCONNECT;
DoClose();
ShowStatus(IDS_STATUSMSG_DISCONNECTED,0); //Send the disconnected message to the message log
}
void CFtpControlSocket::CheckForTimeout()
{
if (!m_Operation.nOpMode && !m_bKeepAliveActive)
return;
if (!m_bCheckForTimeout)
return;
int delay=COptions::GetOptionVal(OPTION_TIMEOUTLENGTH);
if (m_pTransferSocket)
{
int res=m_pTransferSocket->CheckForTimeout(delay);
if (res)
return;
}
CTimeSpan span=CTime::GetCurrentTime()-m_LastRecvTime;
if (span.GetTotalSeconds()>=delay)
{
ShowStatus(IDS_ERRORMSG_TIMEOUT, 1);
DoClose();
}
}
void CFtpControlSocket::FtpCommand(LPCTSTR pCommand)
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("FtpCommand(%s) OpMode=%d OpState=%d"), pCommand, m_Operation.nOpMode, m_Operation.nOpState);
m_Operation.nOpMode=CSMODE_COMMAND;
Send(pCommand);
}
void CFtpControlSocket::Cancel(BOOL bQuit/*=FALSE*/)
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("Cancel(%s) OpMode=%d OpState=%d"), bQuit?_T("TRUE"):_T("FALSE"), m_Operation.nOpMode, m_Operation.nOpState);
int nOpMode=m_Operation.nOpMode;
if (m_Operation.nOpMode&CSMODE_LIST || m_Operation.nOpMode&CSMODE_TRANSFER)
{
Send("ABOR");
if (m_pTransferSocket)
{
m_pTransferSocket->Close();
delete m_pTransferSocket;
m_pTransferSocket=0;
}
}
if (m_Operation.nOpMode==CSMODE_CONNECT)
DoClose(FZ_REPLY_CANCEL);
else if (m_Operation.nOpMode&CSMODE_TRANSFER)
ResetOperation(FZ_REPLY_ERROR|FZ_REPLY_CANCEL|FZ_REPLY_ABORTED);
else if (m_Operation.nOpMode!=CSMODE_NONE)
ResetOperation(FZ_REPLY_ERROR|FZ_REPLY_CANCEL);
if (nOpMode!=CSMODE_NONE && !bQuit)
ShowStatus(IDS_ERRORMSG_INTERRUPTED,1);
}
void CFtpControlSocket::List(BOOL bFinish, int nError /*=FALSE*/, CServerPath path /*=CServerPath()*/, CString subdir /*=""*/,int nListMode/*=0*/)
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("List(%s,%d,\"%s\",\"%s\",%d) OpMode=%d OpState=%d"), bFinish?_T("TRUE"):_T("FALSE"), nError, path.GetPath(), subdir, nListMode,
m_Operation.nOpMode, m_Operation.nOpState);
USES_CONVERSION;
#define LIST_INIT -1
#define LIST_PWD 0
#define LIST_CWD 1
#define LIST_PWD2 2
#define LIST_CWD2 3
#define LIST_PWD3 4
#define LIST_PORT_PASV 5
#define LIST_TYPE 6
#define LIST_LIST 7
#define LIST_WAITFINISH 8
ASSERT(!m_Operation.nOpMode || m_Operation.nOpMode&CSMODE_LIST);
m_Operation.nOpMode|=CSMODE_LIST;
if (!m_pOwner->IsConnected())
{
ResetOperation(FZ_REPLY_ERROR|FZ_REPLY_NOTCONNECTED);
return;
}
if (bFinish || nError)
if (m_Operation.nOpMode!=CSMODE_LIST)
return; //Old message coming in
if (nError)
{
delete m_pTransferSocket;
m_pTransferSocket=0;
if (nError&CSMODE_TRANSFERTIMEOUT)
DoClose();
else
ResetOperation(FZ_REPLY_ERROR);
return;
}
CListData *pData = static_cast<CListData *>(m_Operation.pData);
if (bFinish)
{
if (!m_pTransferSocket || m_pTransferSocket->m_bListening)
{
delete m_pDirectoryListing;
m_pDirectoryListing=0;
delete m_pTransferSocket;
m_pTransferSocket=0;
ResetOperation(FZ_REPLY_ERROR);
return;
}
int num=0;
pData->pDirectoryListing=new t_directory;
if (COptions::GetOptionVal(OPTION_DEBUGSHOWLISTING))
m_pTransferSocket->m_pListResult->SendToMessageLog(m_pOwner->m_hOwnerWnd, m_pOwner->m_nReplyMessageID);
pData->pDirectoryListing->direntry=m_pTransferSocket->m_pListResult->getList(num, pData->ListStartTime);
pData->pDirectoryListing->num=num;
if (m_pTransferSocket->m_pListResult->m_server.nServerType&FZ_SERVERTYPE_SUB_FTP_VMS && m_CurrentServer.nServerType&FZ_SERVERTYPE_FTP)
m_CurrentServer.nServerType |= FZ_SERVERTYPE_SUB_FTP_VMS;
pData->pDirectoryListing->server = m_CurrentServer;
pData->pDirectoryListing->path.SetServer(pData->pDirectoryListing->server);
if (pData->rawpwd != "")
{
if (!pData->pDirectoryListing->path.SetPath(pData->rawpwd))
{
delete m_pDirectoryListing;
m_pDirectoryListing=0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -