⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftpcontrolsocket.cpp

📁 一个FTP下载的源代码。代码质量非常高
💻 CPP
📖 第 1 页 / 共 5 页
字号:
				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 + -