📄 ftpcontrolsocket.cpp
字号:
#define FILETRANSFER_REST 11
#define FILETRANSFER_PORTPASV 12
#define FILETRANSFER_RETRSTOR 13
#define FILETRANSFER_WAITFINISH 14
#define FILETRANSFER_WAIT 15
//Flowchart of FileTransfer
//
// +----+
// /------|Init|--------\
// | +----+ |
// | | |
// | | |
// | +---+ |
// | |CWD|--\ |
// | +---+ | |
// | | | |
// | | | |
// | | +---+ |
// | | |MKD| |
// | | +---+ |
// | | | |
// | | | |
// | | +----+ |
// | | |CWD2| |
// | | +----+ |
// | | | |
// | +----/ |
// | | |
// | +---+ |
// +-------|PWD| |
// | +---+ |
// | | |
// | +----------/
// | |
// | +-------------+
// | |LIST_PORTPASV|
// | +-------------+
// | |
// | |
// | +---------+
// | |LIST_TYPE|
// | +---------+
// | |
// | |
// | +---------+
// | |LIST_LIST|-----\ //List failes, maybe folder is list protected
// | +---------+ | //Use SIZE and MDTM to get file information
// | | +----+
// | | |SIZE|
// | | +----+
// | | |
// | | +----+
// | | |MDTM|
// | | +----+
// | | |
// | | |
// | +---------------+ |
// | |LIST_WAITFINISH| |
// | +---------------+ |
// | | |
// | | |
// | +----------/
// | |
// \---------+
// |
// +----+
// |TYPE|
// +----+
// |
// |
// +--------+
// |PORTPASV|--\
// +--------+ |
// | |
// | |
// | +----+
// | |REST|
// | +----+
// | |
// +------/
// |
// +--------+
// |RETRSTOR|
// +--------+
// |
// |
// +----------+
// |WAITFINISH|
// +----------+
ASSERT(!m_Operation.nOpMode || m_Operation.nOpMode&CSMODE_TRANSFER);
if (!m_pOwner->IsConnected())
{
m_Operation.nOpMode=CSMODE_TRANSFER|(transferfile->get?CSMODE_DOWNLOAD:CSMODE_UPLOAD);
ResetOperation(FZ_REPLY_ERROR|FZ_REPLY_DISCONNECTED);
return;
}
CFileTransferData *pData=static_cast<CFileTransferData *>(m_Operation.pData);
//Process finish and error messages
if (bFinish || nError)
{
ASSERT(m_Operation.nOpMode&CSMODE_TRANSFER);
if (!(m_Operation.nOpMode&CSMODE_TRANSFER))
return;
if (nError)
{
if (m_Operation.nOpState==FILETRANSFER_LIST_LIST && nError&CSMODE_TRANSFERERROR)
{ //Don't abort operation, use fallback to SIZE and MDTM (when actual LIST reply comes in)
if (m_pTransferSocket)
m_pTransferSocket=0;
delete m_pDirectoryListing;
m_pDirectoryListing=0;
}
else if (nError&CSMODE_TRANSFERTIMEOUT)
DoClose();
else
ResetOperation(FZ_REPLY_ERROR);
return;
}
if (m_Operation.nOpState<=FILETRANSFER_LIST_PORTPASV)
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
else if (m_Operation.nOpState<=FILETRANSFER_LIST_WAITFINISH)
{
if (!m_pTransferSocket || m_pTransferSocket->m_bListening)
{
delete m_pDirectoryListing;
m_pDirectoryListing=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(m_CurrentServer);
pData->pDirectoryListing->path = pData->transferfile.remotepath;
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;
}
}
else
pData->pDirectoryListing->path=pData->transferfile.remotepath;
if (m_Operation.nOpState!=FILETRANSFER_LIST_WAITFINISH)
return;
}
else if (m_Operation.nOpState<=FILETRANSFER_PORTPASV)
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
else if (m_Operation.nOpState<=FILETRANSFER_WAITFINISH)
{
if (m_pTransferSocket->m_bListening)
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
pData->nGotTransferEndReply|=2;
if (m_Operation.nOpState!=FILETRANSFER_WAITFINISH)
return;
else
{
delete m_pTransferSocket;
m_pTransferSocket=0;
}
}
}
//////////////////
//Initialization//
//////////////////
int nReplyError=0;
if (m_Operation.nOpState==FILETRANSFER_INIT)
{
ASSERT(transferfile);
ASSERT(!m_Operation.nOpMode);
ASSERT(!m_Operation.pData);
CString str;
str.Format(transferfile->get?IDS_STATUSMSG_DOWNLOADSTART:IDS_STATUSMSG_UPLOADSTART,transferfile->get?transferfile->remotepath.GetPath()+transferfile->remotefile:transferfile->localfile);
ShowStatus(str,0);
m_Operation.nOpMode=CSMODE_TRANSFER|(transferfile->get?CSMODE_DOWNLOAD:CSMODE_UPLOAD);
m_Operation.pData=new CFileTransferData;
pData=static_cast<CFileTransferData *>(m_Operation.pData);
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);
//Replace invalid characters in the local filename
int pos=transferfile->localfile.ReverseFind('\\');
for (int i=(pos+1);i<transferfile->localfile.GetLength();i++)
if (transferfile->localfile[i]==':')
transferfile->localfile.SetAt(i, '_');
pData->transferfile=*transferfile;
pData->transferdata.transfersize=pData->transferfile.size;
pData->transferdata.transferleft=pData->transferfile.size;
pData->transferdata.bResume = FALSE;
pData->transferdata.bType = (pData->transferfile.nType == 1) ? TRUE : FALSE;
CServerPath path;
VERIFY (m_pOwner->GetCurrentPath(path));
if (path==pData->transferfile.remotepath)
{
if (m_pDirectoryListing)
{
m_Operation.nOpState=FILETRANSFER_TYPE;
CString remotefile=pData->transferfile.remotefile;
int i;
for (i=0; i<m_pDirectoryListing->num; i++)
{
if (m_pDirectoryListing->direntry[i].name==remotefile &&
( m_pDirectoryListing->direntry[i].bUnsure || m_pDirectoryListing->direntry[i].size==-1 ))
{
delete m_pDirectoryListing;
m_pDirectoryListing=0;
m_Operation.nOpState = FILETRANSFER_LIST_PORTPASV;
break;
}
}
if (m_pDirectoryListing && i==m_pDirectoryListing->num)
{
nReplyError=CheckOverwriteFile();
if (!nReplyError)
{
if (pData->transferfile.get)
{
CString path=pData->transferfile.localfile;
if (path.ReverseFind('\\')!=-1)
{
path=path.Left(path.ReverseFind('\\')+1);
CString path2;
while (path!="")
{
path2+=path.Left(path.Find( _T("\\") )+1);
path=path.Mid(path.Find( _T("\\") )+1);
int res=CreateDirectory(path2,0);
}
}
}
}
}
}
else
{
CDirectoryCache cache;
t_server server;
m_pOwner->GetCurrentServer(server);
t_directory dir;
BOOL res=cache.Lookup(pData->transferfile.remotepath,server,dir);
if (res)
{
CString remotefile=pData->transferfile.remotefile;
int i;
for (i=0; i<dir.num; i++)
{
if (dir.direntry[i].name==remotefile &&
( dir.direntry[i].bUnsure || dir.direntry[i].size==-1 ))
{
m_Operation.nOpState = FILETRANSFER_LIST_PORTPASV;
break;
}
}
if (i == dir.num)
{
SetDirectoryListing(&dir);
m_Operation.nOpState=FILETRANSFER_TYPE;
nReplyError=CheckOverwriteFile();
if (!nReplyError)
{
if (pData->transferfile.get)
{
CString path=pData->transferfile.localfile;
if (path.ReverseFind('\\')!=-1)
{
path=path.Left(path.ReverseFind('\\')+1);
CString path2;
while (path!="")
{
path2+=path.Left(path.Find( _T("\\") )+1);
path=path.Mid(path.Find(_T( "\\") )+1);
int res=CreateDirectory(path2,0);
}
}
}
}
}
}
else
m_Operation.nOpState = FILETRANSFER_LIST_PORTPASV;
}
}
else
{
m_Operation.nOpState=FILETRANSFER_CWD;
}
}
else
{
///////////
//Replies//
///////////
switch(m_Operation.nOpState)
{
case FILETRANSFER_CWD:
if (GetReplyCode()!=2 && GetReplyCode()!=3)
if (GetReplyCode()==4)
nReplyError=FZ_REPLY_ERROR;
else if (pData->transferfile.get)
{
pData->bUseAbsolutePaths = TRUE;
m_Operation.nOpState = FILETRANSFER_NOLIST_SIZE;
}
else
m_Operation.nOpState=FILETRANSFER_MKD;
else
m_Operation.nOpState=FILETRANSFER_PWD;
break;
case FILETRANSFER_MKD:
switch(pData->nMKDOpState)
{
case MKD_FINDPARENT:
{
int res=GetReplyCode();
if (res==2 || res==3)
{
m_pOwner->SetCurrentPath(pData->MKDCurrent);
if (!m_pDirectoryListing)
{
CDirectoryCache cache;
t_directory dir;
BOOL res=cache.Lookup(pData->MKDCurrent, m_CurrentServer, dir, TRUE);
if (res)
SetDirectoryListing(&dir);
}
pData->nMKDOpState=MKD_CHANGETOSUBDIR;
pData->MKDCurrent.AddSubdir(pData->MKDSegments.front());
CString Segment=pData->MKDSegments.front();
pData->MKDSegments.pop_front();
if (!Send( _T("MKD ") + Segment))
return;
}
else
{
if (!pData->MKDCurrent.HasParent())
nReplyError=FZ_REPLY_ERROR|((res==5)?FZ_REPLY_CRITICALERROR:0);
else
{
pData->MKDSegments.push_front(pData->MKDCurrent.GetLastSegment());
pData->MKDCurrent=pData->MKDCurrent.GetParent();
if (!Send("CWD "+pData->MKDCurrent.GetPath()))
return;
}
}
}
break;
case MKD_MAKESUBDIRS:
{
int res=GetReplyCode();
if (res==2 || res==3)
{ //Create dir entry in parent dir
ASSERT(!pData->MKDSegments.empty());
pData->MKDCurrent.AddSubdir(pData->MKDSegments.front());
CString Segment=pData->MKDSegments.front();
pData->MKDSegments.pop_front();
if (Send( _T("MKD ") + Segment))
pData->nMKDOpState=MKD_CHANGETOSUBDIR;
else
return;
}
else
nReplyError=FZ_REPLY_ERROR;
}
break;
case MKD_CHANGETOSUBDIR:
{
int res=GetReplyCode();
if (res==2 || res==3 || //Creation successful
m_RecvBuffer.front()==_T("550 Directory already exists") )//Creation was successful, although someone else did the work for us
{
if (m_RecvBuffer.front()==_T("550 Directory already exists") )
printf("OK");
CServerPath path2=pData->MKDCurrent;
if (path2.HasParent())
{
CString name=path2.GetLastSegment();
path2=path2.GetParent();
CDirectoryCache cache;
cache.Lock();
t_directory dir;
BOOL bCached=TRUE;
BOOL res=cache.Lookup(path2,m_CurrentServer,dir);
if (!res)
bCached=FALSE;
if (!res && m_pDirectoryListing)
{
if (m_pDirectoryListing->path==path2)
{
dir=*m_pDirectoryListing;
res=TRUE;
}
}
t_directory WorkingDir;
BOOL bFound=m_pOwner->GetWorkingDir(&WorkingDir);
if (!res && bFound)
if (WorkingDir.path==path2)
{
dir=WorkingDir;
res=TRUE;
}
if (!res)
{
dir.path=path2;
dir.server=m_CurrentServer;
}
int i;
for (i=0; i<dir.num; i++)
if (dir.direntry[i].name == name)
{
LogMessage(__FILE__, __LINE__, this, FZ_LOG_WARNING, _T("Dir already exists in cache!"));
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -