ftpcontrolsocket.cpp
来自「一个支持FTP,SFTP的客户端程序」· C++ 代码 · 共 2,319 行 · 第 1/5 页
CPP
2,319 行
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 = "";
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";
int res = 0;
if (m_bUTF8)
{
LPCWSTR unicode = T2CW(str);
int len = WideCharToMultiByte(CP_UTF8, 0, unicode, -1, 0, 0, 0, 0);
if (!len)
{
ShowStatus(IDS_ERRORMSG_CANTSENDCOMMAND, 1);
DoClose();
return FALSE;
}
char* utf8 = new char[len + 1];
WideCharToMultiByte(CP_UTF8, 0, unicode, -1, utf8, len + 1, 0, 0);
int sendLen = strlen(utf8);
if (!m_awaitsReply && !m_sendBuffer)
res = CAsyncSocketEx::Send(utf8, strlen(utf8));
else
res = -2;
if ((res == SOCKET_ERROR && GetLastError() != WSAEWOULDBLOCK) || !res)
{
delete [] utf8;
ShowStatus(IDS_ERRORMSG_CANTSENDCOMMAND, 1);
DoClose();
return FALSE;
}
if (res != sendLen)
{
if (res == -2)
res = 0;
if (!m_sendBuffer)
{
m_sendBuffer = new char[sendLen - res];
memcpy(m_sendBuffer, utf8 + res, sendLen - res);
m_sendBufferLen = sendLen - res;
}
else
{
char* tmp = new char[m_sendBufferLen + sendLen - res];
memcpy(tmp, m_sendBuffer, m_sendBufferLen);
memcpy(tmp + m_sendBufferLen, utf8 + res, sendLen - res);
delete [] m_sendBuffer;
m_sendBuffer = tmp;
m_sendBufferLen += sendLen - res;
}
}
delete [] utf8;
}
else
{
LPCSTR lpszAsciiSend = T2CA(str);
int sendLen = strlen(lpszAsciiSend);
if (!m_awaitsReply && !m_sendBuffer)
res = CAsyncSocketEx::Send(lpszAsciiSend, strlen(lpszAsciiSend));
else
res = -2;
if ((res == SOCKET_ERROR && GetLastError() != WSAEWOULDBLOCK) || !res)
{
ShowStatus(IDS_ERRORMSG_CANTSENDCOMMAND, 1);
DoClose();
return FALSE;
}
if (res != sendLen)
{
if (res == -2)
res = 0;
if (!m_sendBuffer)
{
m_sendBuffer = new char[sendLen - res];
memcpy(m_sendBuffer, lpszAsciiSend, sendLen - res);
m_sendBufferLen = sendLen - res;
}
else
{
char* tmp = new char[m_sendBufferLen + sendLen - res];
memcpy(tmp, m_sendBuffer, m_sendBufferLen);
memcpy(tmp + m_sendBufferLen, lpszAsciiSend + res, sendLen - res);
delete [] m_sendBuffer;
m_sendBuffer = tmp;
m_sendBufferLen += sendLen - res;
}
}
}
if (res > 0)
{
m_awaitsReply = true;
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;
CStringA 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 = "";
m_bDidRejectCertificate = FALSE;
m_useZlib = false;
m_zlibSupported = false;
m_zlibLevel = 0;
m_bUTF8 = false;
m_hasClntCmd = false;
m_awaitsReply = false;
m_skipReply = false;
delete [] m_sendBuffer;
m_sendBuffer = 0;
m_sendBufferLen = 0;
m_bProtP = false;
m_mayBeMvsFilesystem = false;
m_mayBeBS2000Filesystem = false;
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::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_MODE 5
#define LIST_OPTS 6
#define LIST_PORT_PASV 7
#define LIST_TYPE 8
#define LIST_LIST 9
#define LIST_WAITFINISH 10
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;
delete m_pTransferSocket;
m_pTransferSocket=0;
ResetOperation(FZ_REPLY_ERROR);
return;
}
m_pOwner->SetCurrentPath(pData->pDirectoryListing->path);
}
else
pData->pDirectoryListing->path = m_pOwner->GetCurrentPath();
if (m_Operation.nOpState!=LIST_WAITFINISH)
return;
else
{
delete m_pTransferSocket;
m_pTransferSocket=0;
}
}
if (m_Operation.nOpState==LIST_WAITFINISH)
{
if (!bFinish)
{
if (pData->nFinish==-1)
{
int code=GetReplyCode();
if (code== 2)
{
pData->nFinish=1;
}
else
pData->nFinish=0;
}
}
else
{
if (m_pTransferSocket)
delete m_pTransferSocket;
m_pTransferSocket=0;
}
if (pData->nFinish==0)
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
else if (pData->pDirectoryListing && pData->nFinish==1)
{
ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL,0);
CDirectoryCache cache;
cache.Lock();
t_directory dir;
if (!pData->path.IsEmpty() && pData->subdir!="")
{
if (cache.Lookup(pData->pDirectoryListing->path, pData->pDirectoryListing->server, dir))
pData->pDirectoryListing->Merge(dir, pData->ListStartTime);
cache.Store(*pData->pDirectoryListing,pData->path,pData->subdir);
}
else
{
if (cache.Lookup(pData->pDirectoryListing->path, pData->pDirectoryListing->server, dir))
pData->pDirectoryListing->Merge(dir, pData->ListStartTime);
cache.Store(*pData->pDirectoryListing);
}
cache.Unlock();
SetDirectoryListing(pData->pDirectoryListing);
ResetOperation(FZ_REPLY_OK);
return;
}
return;
}
else if (m_Operation.nOpState != LIST_INIT)
{
CString retmsg = GetReply();
BOOL error = FALSE;
int code = GetReplyCode();
switch (m_Operation.nOpState)
{
case LIST_PWD: //Reply to PWD command
if (code != 2 && code !=3 )
{
error = TRUE;
break;
}
pData->rawpwd = retmsg;
if ((m_mayBeMvsFilesystem || m_mayBeBS2000Filesystem) && m_CurrentServer.nServerType & FZ_SERVERTYPE_FTP &&
pData->rawpwd[0] != '/')
{
m_mayBeMvsFilesystem = false;
m_mayBeBS2000Filesystem = false;
if (m_mayBeBS2000Filesystem)
m_CurrentServer.nServerType |= FZ_SERVERTYPE_SUB_FTP_BS2000;
else
m_CurrentServer.nServerType |= FZ_SERVERTYPE_SUB_FTP_MVS;
if (!pData->path.IsEmpty())
pData->path.SetServer(m_CurrentServer);
}
if (!ParsePwdReply(pData->rawpwd))
return;
if (pData->path.IsEmpty() || pData->path == m_pOwner->GetCurrentPath())
{
if (pData->nListMode & FZ_LIST_USECACHE)
{
t_directory dir;
CDirectoryCache cache;
BOOL res = cache.Lookup(m_pOwner->GetCurrentPath(), m_CurrentServer, dir);
if (res)
{
BOOL bExact = TRUE;
if (pData->nListMode & FZ_LIST_EXACT)
for (int i=0; i<dir.num; i++)
if (dir.direntry[i].bUnsure || (dir.direntry[i].size==-1 && !dir.direntry[i].dir))
{
bExact = FALSE;
break;
}
if (bExact)
{
ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL, 0);
SetDirectoryListing(&dir);
ResetOperation(FZ_REPLY_OK);
return;
}
}
}
m_Operation.nOpState = NeedModeCommand() ? LIST_MODE : (NeedOptsCommand() ? LIST_OPTS : LIST_TYPE);
}
else
m_Operation.nOpState = LIST_CWD;
break;
case LIST_CWD:
if (code != 2 && code != 3)
error = TRUE;
m_Operation.nOpState = LIST_PWD2;
break;
case LIST_PWD2: //Reply to PWD command
if (code !=2 && code != 3)
error = TRUE;
else
{
pData->rawpwd = retmsg;
if (!ParsePwdReply(pData->rawpwd))
return;
}
if (pData->subdir != "")
{
if (pData->path != m_pOwner->GetCurrentPath())
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
m_Operation.nOpState = LIST_CWD2;
}
else
{
if (pData->nListMode & FZ_LIST_USECACHE)
{
t_directory dir;
CDirectoryCache cache;
BOOL res = cache.Lookup(m_pOwner->GetCurrentPath(), m_CurrentServer, dir);
if (res)
{
BOOL bExact = TRUE;
if (pData->nListMode & FZ_LIST_EXACT)
for (int i=0; i<dir.num; i++)
if (dir.direntry[i].bUnsure || (dir.direntry[i].size==-1 && !dir.direntry[i].dir))
{
bExact = FALSE;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?