sftpcontrolsocket.cpp
来自「一个支持FTP,SFTP的客户端程序」· C++ 代码 · 共 2,354 行 · 第 1/5 页
CPP
2,354 行
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;
ResetOperation(FZ_REPLY_ERROR);
return;
}
}
else
pData->pDirectoryListing->path = pData->realpath;
ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL,0);
//Merge new listing into cache
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;
}
}
if (m_Operation.nOpState==LIST_INIT)
{ //Initialize some variables
pData = new CListData(m_CurrentServer);;
pData->pParser->InitLog(this);
pData->nListMode=nListMode;
pData->path=path;
pData->subdir=subdir;
m_Operation.pData=pData;
ShowStatus(IDS_STATUSMSG_RETRIEVINGDIRLIST,0);
if (m_pDirectoryListing)
{
delete m_pDirectoryListing;
m_pDirectoryListing=0;
}
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_LIST;
}
}
}
else
{
if (pData->path.IsEmpty())
m_Operation.nOpState=LIST_PWD;
else
m_Operation.nOpState=LIST_CWD;
}
}
BOOL bSuccessful=FALSE;
if (m_Operation.nOpState==LIST_PWD)
bSuccessful=m_pDataChannel->Send(SFTP_DATAID_STC_PWD, 0, 0);
else if (m_Operation.nOpState==LIST_CWD)
bSuccessful=m_pDataChannel->Send(SFTP_DATAID_STC_CD, pData->path.GetPath());
else if (m_Operation.nOpState==LIST_CWD2)
{
if (!pData->subdir)
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
bSuccessful=m_pDataChannel->Send(SFTP_DATAID_STC_CD, pData->subdir);
}
else if (m_Operation.nOpState==LIST_LIST)
{
pData->ListStartTime=CTime::GetCurrentTime();
bSuccessful=m_pDataChannel->Send(SFTP_DATAID_STC_LIST, 0, 0);
}
if (!bSuccessful)
DoClose();
}
void CSFtpControlSocket::FtpCommand(LPCTSTR pCommand)
{
ASSERT(FALSE);
}
void CSFtpControlSocket::Disconnect()
{
ASSERT(!m_Operation.nOpMode);
m_Operation.nOpMode=CSMODE_DISCONNECT;
DoClose();
}
void CSFtpControlSocket::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_LIST 4
#define FILETRANSFER_RETRSTOR 13
#define FILETRANSFER_WAIT 15
//Flowchart of FileTransfer
//
// +----+
// /------|Init|--------\
// | +----+ |
// | | |
// | | |
// | +---+ |
// | |CWD|--\ |
// | +---+ | |
// | | | |
// | | | |
// | | +---+ |
// | | |MKD| |
// | | +---+ |
// | | | |
// | | | |
// | | +----+ |
// | | |CWD2| |
// | | +----+ |
// | | | |
// | +----/ |
// | | |
// | +----------/
// | |
// | +----+
// | |LIST|
// | +----+
// | |
// \---------+
// |
// +--------+
// |RETRSTOR|
// +--------+
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);
}
CFileTransferData *pData=static_cast<CFileTransferData *>(m_Operation.pData);
//////////////////
//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);
pData = new CFileTransferData(m_CurrentServer);
pData->pParser->InitLog(this);
m_Operation.pData=pData;
//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.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_RETRSTOR;
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;
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;
break;
}
}
if (i==dir.num)
{
SetDirectoryListing(&dir);
m_Operation.nOpState=FILETRANSFER_RETRSTOR;
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;
}
}
else
m_Operation.nOpState=FILETRANSFER_CWD;
}
else
{
///////////
//Replies//
///////////
switch(m_Operation.nOpState)
{
case FILETRANSFER_CWD:
if (m_bError)
{
if (!pData->transferfile.get)
m_Operation.nOpState = FILETRANSFER_MKD;
else
{
pData->bUseAbsolutePaths = TRUE;
m_Operation.nOpState = FILETRANSFER_RETRSTOR;
}
}
else
{
CServerPath path;
path.SetServer(m_CurrentServer);
if (!path.SetPath(A2CT(m_Reply)))
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_WARNING, _T("Can't parse path"));
nReplyError=FZ_REPLY_ERROR;
}
else
{
pData->rawpwd=m_Reply;
m_pOwner->SetCurrentPath(path);
if (path!=pData->transferfile.remotepath)
nReplyError=FZ_REPLY_ERROR | FZ_REPLY_CRITICALERROR;
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;
break;
}
}
if (i==dir.num)
{
SetDirectoryListing(&dir);
m_Operation.nOpState=FILETRANSFER_RETRSTOR;
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;
}
}
}
break;
case FILETRANSFER_MKD:
switch(pData->nMKDOpState)
{
case MKD_FINDPARENT:
if (!m_bError)
{
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 (!m_pDataChannel->Send(SFTP_DATAID_STC_MKD, Segment))
{
DoClose();
return;
}
}
else
{
if (!pData->MKDCurrent.HasParent())
nReplyError=FZ_REPLY_ERROR|FZ_REPLY_CRITICALERROR;
else
{
pData->MKDSegments.push_front(pData->MKDCurrent.GetLastSegment());
pData->MKDCurrent=pData->MKDCurrent.GetParent();
if (!m_pDataChannel->Send(SFTP_DATAID_STC_CD, pData->MKDCurrent.GetPath()))
{
DoClose();
return;
}
}
}
break;
case MKD_MAKESUBDIRS:
if (!m_bError)
{ //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 (m_pDataChannel->Send(SFTP_DATAID_STC_MKD, Segment))
pData->nMKDOpState=MKD_CHANGETOSUBDIR;
else
{
DoClose();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?