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 + -
显示快捷键?