📄 ftpcontrolsocket.cpp
字号:
delete m_pTransferSocket;
m_pTransferSocket=0;
ResetOperation(FZ_REPLY_ERROR);
return;
}
}
else
pData->pDirectoryListing->path=pData->realpath;
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 = m_RecvBuffer.front();
BOOL error = FALSE;
int code = GetReplyCode();
switch(m_Operation.nOpState)
{
case LIST_PWD: //Reply to PWD command
if (code!=2 && code!=3)
error = TRUE;
else
{
if (!ParsePwdReply(retmsg))
return;
}
m_Operation.nOpState = LIST_PORT_PASV;
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
{
if (!ParsePwdReply(retmsg))
return;
}
if (pData->subdir != "")
{
if (pData->path != pData->realpath)
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
m_Operation.nOpState = LIST_CWD2;
}
else
m_Operation.nOpState = LIST_PORT_PASV;
break;
case LIST_CWD2:
if (code != 2 && code != 3)
error = TRUE;
m_Operation.nOpState = LIST_PWD3;
break;
case LIST_PWD3: //Reply to PWD command
if (code!=2 && code!=3)
error=TRUE;
else
{
if (!ParsePwdReply(retmsg))
return;
}
m_Operation.nOpState = LIST_PORT_PASV;
break;
case LIST_PORT_PASV:
if (code!=2 && code!=3)
{
error=TRUE;
break;
}
if (pData->bPasv)
{
CString temp;
int i,j;
if((i=retmsg.Find(_T("(")))==-1||(j=retmsg.Find(_T(")")))==-1)
{
if (!pData->bTriedPortPasvOnce)
{
pData->bTriedPortPasvOnce = TRUE;
pData->bPasv = !pData->bPasv;
}
else
error=TRUE;
break;
}
temp=retmsg.Mid(i+1,(j-i)-1);
i=temp.ReverseFind(',');
pData->port=atol( T2CA( temp.Right(temp.GetLength()-(i+1)) ) ); //get ls byte of server socket
temp=temp.Left(i);
i=temp.ReverseFind(',');
pData->port+=256*atol( T2CA( temp.Right(temp.GetLength()-(i+1)) ) ); // add ms byte to server socket
pData->host=temp.Left(i);
while(1) { // convert commas to dots in IP
if((i=pData->host.Find( _T(",") ))==-1) break;
pData->host.SetAt(i,'.');
}
}
m_Operation.nOpState = LIST_TYPE;
break;
case LIST_TYPE:
if (code!=2 && code!=3)
error=TRUE;
m_Operation.nOpState=LIST_LIST;
break;
case LIST_LIST:
if (code!=1)
error=TRUE;
else
m_Operation.nOpState=LIST_WAITFINISH;
break;
default:
error = TRUE;
}
if (error)
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
}
if (m_Operation.nOpState==LIST_INIT)
{ //Initialize some variables
pData=new CListData;
pData->nListMode=nListMode;
pData->path=path;
pData->subdir=subdir;
m_Operation.pData=pData;
ShowStatus(IDS_STATUSMSG_RETRIEVINGDIRLIST,0);
pData->nFinish=-1;
if (m_pDirectoryListing)
{
delete m_pDirectoryListing;
m_pDirectoryListing=0;
}
if (COptions::GetOptionVal(OPTION_PROXYTYPE)!=PROXYTYPE_NOPROXY && !m_CurrentServer.fwbypass)
pData->bPasv = TRUE;
else if (m_CurrentServer.nPasv == 1)
pData->bPasv = TRUE;
else if (m_CurrentServer.nPasv == 2)
pData->bPasv = FALSE;
else
pData->bPasv = COptions::GetOptionVal(OPTION_PASV);
CServerPath path = pData->path;
m_pOwner->GetCurrentPath(pData->realpath);
CServerPath realpath=pData->realpath;
if (!pData->realpath.IsEmpty())
{
if (!pData->path.IsEmpty() && pData->path!=pData->realpath)
m_Operation.nOpState=LIST_CWD;
else if (!pData->path.IsEmpty() && pData->subdir!="")
m_Operation.nOpState=LIST_CWD2;
else
{
if (pData->nListMode&FZ_LIST_REALCHANGE)
{
if (pData->subdir=="")
m_Operation.nOpState=LIST_CWD;
else
m_Operation.nOpState=LIST_CWD2;
}
else
{
if (pData->nListMode&FZ_LIST_USECACHE)
{
t_directory dir;
CDirectoryCache cache;
BOOL res=cache.Lookup(pData->realpath,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=LIST_PORT_PASV;
}
}
}
else
{
if (pData->path.IsEmpty())
m_Operation.nOpState=LIST_PWD;
else
m_Operation.nOpState=LIST_CWD;
}
}
CString cmd;
if (m_Operation.nOpState==LIST_PWD)
cmd=_T("PWD");
else if (m_Operation.nOpState==LIST_CWD)
cmd=_T("CWD ") + pData->path.GetPath(); //Command to retrieve the current directory
else if (m_Operation.nOpState==LIST_PWD2)
cmd=_T("PWD");
else if (m_Operation.nOpState==LIST_CWD2)
{
if (!pData->subdir)
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
if (pData->subdir != _T("..") )
cmd=_T("CWD ") + pData->subdir;
else
cmd=_T("CDUP");
}
else if (m_Operation.nOpState==LIST_PWD3)
cmd=_T("PWD");
else if (m_Operation.nOpState==LIST_PORT_PASV)
{
m_pTransferSocket=new CTransferSocket(this, m_Operation.nOpMode);
m_pTransferSocket->m_nInternalMessageID=m_pOwner->m_nInternalMessageID;
if (m_pGssLayer && m_pGssLayer->AuthSuccessful())
m_pTransferSocket->UseGSS(m_pGssLayer);
if (!m_pTransferSocket->Create(m_pSslLayer?TRUE:FALSE) ||
!m_pTransferSocket->AsyncSelect())
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
if (pData->bPasv)
cmd=_T("PASV");
else
{
m_pTransferSocket->m_bListening=TRUE;
if (m_pProxyLayer)
{
SOCKADDR_IN addr;
int len=sizeof(addr);
if (!m_pProxyLayer->GetPeerName((SOCKADDR *)&addr,&len))
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
else if (!m_pTransferSocket->Listen(addr.sin_addr.S_un.S_addr))
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
}
else
{
//Set up an active file transfer
CString temp;
UINT nPort;
if (// create listen socket (let MFC choose the port) & start the socket listening
!m_pTransferSocket->Listen() ||
!m_pTransferSocket->GetSockName(temp, nPort))
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
CString host = COptions::GetOption(OPTION_TRANSFERIP);
if (host != "")
{
DWORD ip = inet_addr(T2CA(host));
if (ip != INADDR_NONE)
host.Format(_T("%d,%d,%d,%d"), ip%256, (ip>>8)%256, (ip>>16)%256, ip>>24);
else
{
hostent *fullname = gethostbyname(T2CA(host));
if (!fullname)
host = "";
else
{
DWORD ip = ((LPIN_ADDR)fullname->h_addr)->s_addr;
if (ip != INADDR_NONE)
host.Format(_T("%d,%d,%d,%d"), ip%256, (ip>>8)%256, (ip>>16)%256, ip>>24);
else
host = "";
}
}
}
if (host == "")
{
UINT temp;
if(!GetSockName(host, temp))
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
host.Replace('.', ',');
}
host.Format(host+",%d,%d", nPort/256, nPort%256);
cmd = _T("PORT ") + host; // send PORT cmd to server
}
}
}
else if (m_Operation.nOpState==LIST_TYPE)
cmd=_T("TYPE A");
else if (m_Operation.nOpState==LIST_LIST)
{
if (!m_pTransferSocket)
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_APIERROR, _T("Error: m_pTransferSocket==NULL") );
ResetOperation(FZ_REPLY_ERROR);
return;
}
m_pTransferSocket->SetActive();
cmd="LIST";
if ( m_pOwner->GetOption(FZAPI_OPTION_SHOWHIDDEN) )
cmd+=" -a";
if (!Send(cmd))
return;
pData->ListStartTime=CTime::GetCurrentTime();
if (pData->bPasv)
{
// if PASV create the socket & initiate outbound data channel connection
if (!m_pTransferSocket->Connect(pData->host,pData->port))
{
if (GetLastError()!=WSAEWOULDBLOCK)
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
}
}
return;
}
if ( cmd != _T("") )
Send(cmd);
}
void CFtpControlSocket::TransferEnd(int nMode)
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("TransferEnd(%d) OpMode=%d OpState=%d"), nMode, m_Operation.nOpMode, m_Operation.nOpState);
if (!m_Operation.nOpMode)
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_INFO, _T("Ignoring old TransferEnd message"));
return;
}
m_LastRecvTime=CTime::GetCurrentTime();
if (m_Operation.nOpMode&CSMODE_TRANSFER)
FileTransfer(0,TRUE,nMode&(CSMODE_TRANSFERERROR|CSMODE_TRANSFERTIMEOUT));
else if (m_Operation.nOpMode&CSMODE_LIST)
List(TRUE,nMode&(CSMODE_TRANSFERERROR|CSMODE_TRANSFERTIMEOUT));
}
void CFtpControlSocket::OnClose(int nErrorCode)
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("OnClose(%d) OpMode=%d OpState=%d"), nErrorCode, m_Operation.nOpMode, m_Operation.nOpState);
ShowStatus(IDS_STATUSMSG_DISCONNECTED, 1);
if (m_pTransferSocket)
{
m_pTransferSocket->OnClose(0);
m_pTransferSocket->Close();
delete m_pTransferSocket;
m_pTransferSocket=0;
DoClose();
ShowStatus(IDS_ERRORMSG_TIMEOUT,1);
return;
}
DoClose();
}
void CFtpControlSocket::FileTransfer(t_transferfile *transferfile/*=0*/,BOOL bFinish/*=FALSE*/,int nError/*=0*/)
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("FileTransfer(%d, %s, %d) OpMode=%d OpState=%d"), transferfile,bFinish?_T("TRUE"):_T("FALSE"), nError, m_Operation.nOpMode, m_Operation.nOpState);
USES_CONVERSION;
#define FILETRANSFER_INIT -1 //Opt: LIST TYPE
#define FILETRANSFER_CWD 0 //PWD
#define FILETRANSFER_MKD 1
#define FILETRANSFER_CWD2 2
#define FILETRANSFER_PWD 3
#define FILETRANSFER_LIST_PORTPASV 4
#define FILETRANSFER_LIST_TYPE 5
#define FILETRANSFER_LIST_LIST 6
#define FILETRANSFER_LIST_WAITFINISH 7
#define FILETRANSFER_NOLIST_SIZE 8
#define FILETRANSFER_NOLIST_MDTM 9
#define FILETRANSFER_TYPE 10
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -