ftpcontrolsocket.cpp
来自「一个支持FTP,SFTP的客户端程序」· C++ 代码 · 共 2,319 行 · 第 1/5 页
CPP
2,319 行
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);
}
break;
case LIST_CWD2:
if (pData->lastCmdSentCDUP)
{
CString reply = GetReply().Left(3);
int replycode = _ttoi(reply);
if (replycode >= 500 && replycode < 505)
break;
pData->lastCmdSentCDUP = false;
}
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
{
pData->rawpwd = retmsg;
if (!ParsePwdReply(pData->rawpwd))
return;
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);
break;
case LIST_MODE:
if (code == 2 || code == 3)
m_useZlib = !m_useZlib;
m_Operation.nOpState = NeedOptsCommand() ? LIST_OPTS : LIST_TYPE;
break;
case LIST_OPTS:
if (code == 2 || code == 3)
m_zlibLevel = pData->newZlibLevel;
m_Operation.nOpState = LIST_TYPE;
break;
case LIST_TYPE:
if (code!=2 && code!=3)
error=TRUE;
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;
}
if (GetFamily() == AF_INET)
{
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);
pData->host.Replace(',', '.');
}
else if (GetFamily() == AF_INET6)
{
temp = temp.Mid(3);
pData->port = atol( T2CA(temp.Left(temp.GetLength() - 1) ) );
if (pData->port < 0 || pData->port > 65535)
{
LogMessage(__FILE__, __LINE__, this, FZ_LOG_WARNING, _T("Port %u not valid"), pData->port);
error = TRUE;
break;
}
unsigned int tmpPort;
if (!GetPeerName(pData->host, tmpPort))
{
LogMessage(__FILE__, __LINE__, this, FZ_LOG_WARNING, _T("GetPeerName failed"));
error = TRUE;
break;
}
}
else
{
LogMessage(__FILE__, __LINE__, this, FZ_LOG_WARNING, _T("Protocol %d not supported"), GetFamily());
error = TRUE;
break;
}
}
m_Operation.nOpState = LIST_LIST;
break;
case LIST_LIST:
if (IsMisleadingListResponse())
{
ShowStatus(IDS_STATUSMSG_DIRLISTSUCCESSFUL, 0);
t_directory listing;
listing.server = m_CurrentServer;
listing.path = m_pOwner->GetCurrentPath();
CDirectoryCache cache;
cache.Lock();
t_directory dir;
if (!pData->path.IsEmpty() && pData->subdir != "")
{
if (cache.Lookup(listing.path, listing.server, dir))
listing.Merge(dir, pData->ListStartTime);
cache.Store(listing, pData->path, pData->subdir);
}
else
{
if (cache.Lookup(listing.path, listing.server, dir))
listing.Merge(dir, pData->ListStartTime);
cache.Store(listing);
}
cache.Unlock();
SetDirectoryListing(&listing);
ResetOperation(FZ_REPLY_OK);
return;
}
else 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;
CServerPath realpath = m_pOwner->GetCurrentPath();
if (!realpath.IsEmpty())
{
if (!pData->path.IsEmpty() && pData->path != 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(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 = NeedModeCommand() ? LIST_MODE : (NeedOptsCommand() ? LIST_OPTS : LIST_TYPE);;
}
}
}
else
m_Operation.nOpState = LIST_PWD;
}
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("..") )
{
if (m_CurrentServer.nServerType & FZ_SERVERTYPE_SUB_FTP_VMS)
{
CServerPath path = m_pOwner->GetCurrentPath();
path.AddSubdir(pData->subdir);
cmd = _T("CWD ") + path.GetPath();
}
else
cmd = _T("CWD ") + pData->subdir;
}
else
{
if (pData->lastCmdSentCDUP)
{
pData->lastCmdSentCDUP = false;
cmd = _T("CWD ..");
}
else
{
pData->lastCmdSentCDUP = true;
cmd = _T("CDUP");
}
}
}
else if (m_Operation.nOpState == LIST_PWD3)
cmd=_T("PWD");
else if (m_Operation.nOpState == LIST_MODE)
{
if (m_useZlib)
cmd = _T("MODE S");
else
cmd = _T("MODE Z");
}
else if (m_Operation.nOpState == LIST_OPTS)
{
pData->newZlibLevel = COptions::GetOptionVal(OPTION_MODEZ_LEVEL);
cmd.Format(_T("OPTS MODE Z LEVEL %d"), pData->newZlibLevel);
}
else if (m_Operation.nOpState == LIST_PORT_PASV)
{
m_pTransferSocket = new CTransferSocket(this, m_Operation.nOpMode);
if (m_useZlib)
{
if (!m_pTransferSocket->InitZlib(m_zlibLevel))
{
ShowStatus("Failed to initialize zlib", 1);
ResetOperation(FZ_REPLY_ERROR);
return;
}
}
m_pTransferSocket->m_nInternalMessageID = m_pOwner->m_nInternalMessageID;
if (m_pGssLayer && m_pGssLayer->AuthSuccessful())
m_pTransferSocket->UseGSS(m_pGssLayer);
m_pTransferSocket->SetFamily(GetFamily());
if (!m_pTransferSocket->Create(m_pSslLayer && m_bProtP) ||
!m_pTransferSocket->AsyncSelect())
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
if (pData->bPasv)
switch (GetFamily())
{
case AF_INET:
cmd = _T("PASV");
break;
case AF_INET6:
cmd = _T("EPSV");
break;
default:
LogMessage(__FILE__, __LINE__, this, FZ_LOG_WARNING, _T("Protocol %d not supported"), GetFamily());
ResetOperation(FZ_REPLY_ERROR);
return;
}
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 tempHostname;
UINT nPort;
if (// create listen socket (let MFC choose the port) & start the socket listening
!m_pTransferSocket->Listen() ||
!m_pTransferSocket->GetSockName(tempHostname, nPort))
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
CString host;
bool bError = false;
if (GetFamily() == AF_INET)
{
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))
bError = true;
host.Replace('.', ',');
}
if (!bError)
{
host.Format(host+",%d,%d", nPort/256, nPort%256);
cmd = _T("PORT ") + host; // send PORT cmd to server
}
}
else if (GetFamily() == AF_INET6)
{
host = COptions::GetOption(OPTION_TRANSFERIP6);
if (host != "")
{
USES_CONVERSION;
addrinfo hints, *res;
memset(&hints, 0, sizeof(addrinfo));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_STREAM;
if (!p_getaddrinfo(T2CA(host), "1024", &hints, &res))
{
host = Inet6AddrToString(((SOCKADDR_IN6 *)res->ai_addr)->sin6_addr);
p_freeaddrinfo(res);
}
else
host = _T("");
}
if (host == "")
{
UINT temp;
if(!GetSockName(host, temp))
bError = true;
}
if (!bError)
{
// assamble EPRT command
cmd.Format(_T("EPRT |2|") + host + "|%d|", nPort);
}
}
else
{
LogMessage(__FILE__, __LINE__, this, FZ_LOG_WARNING, _T("Protocol %d not supported"), GetFamily());
bError = true;
}
if (bError)
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?