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

📄 ftpclient.cpp

📁 自己改写的在WINCE上开发用的EVC++的FTP操作示例工程,希望能给相关人士提供帮助.
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	default:
		ASSERT( false );
	}
	return "";
}

/// Sends a command to the server.
/// @param[in] strCommand Command to send.
bool CFTPClient::SendCommand(CStringA& strCommand)
{
	if( !IsConnected() )
		return false;
	
	try
	{
		if(m_pNotification)
			m_pNotification->OnSendCommand(strCommand);
		
		CDataStack2 data;
		data.Append(strCommand.GetString(),strCommand.GetLength());
		data.Append("\r\n",2);
		
		m_apSckControlConnection->Write(data.GetData(), data.Length(), mc_uiTimeout);
	}
	catch(CBlockingSocketException& blockingException)
	{
		ReportError(blockingException.GetErrorMessage(), __FILE__, __LINE__);
		const_cast<CFTPClient*>(this)->m_apSckControlConnection->Cleanup();
		return false;
	}
	
	return true;
}

/// Sends a command to the server.
/// @param[in]  strCommand Command to send.
/// @param[out] Reply The Reply of the server to the sent command.
bool CFTPClient::SendCommand(CStringA& strCommand, CReply& Reply)
{
	if( !SendCommand(strCommand) || !GetResponse(Reply) )
		return false;
	return true;
}

/// This function gets the server response.
/// A server response can exists of more than one line. This function
/// returns the full response (multiline).
/// @param[out] Reply Reply of the server to a command.
bool CFTPClient::GetResponse(CReply& Reply)
{
	CStringA strResponse;
	if( !GetSingleResponseLine(strResponse) )
		return false;
	
	if( strResponse.GetLength()>3 && strResponse.GetAt(3)=='-' )
	{
		CStringA strSingleLine(strResponse);
		int iRetCode=StringToLong(strResponse);
		// handle multi-line server responses
		while( !(strSingleLine.GetLength()>3 && 
			strSingleLine.GetAt(3)==' ' &&
			StringToLong(strSingleLine)==iRetCode) )
		{ 
			if( !GetSingleResponseLine(strSingleLine) )
				return false;
			strResponse += "\r\n" + strSingleLine;
		}
	}
	
	bool fRet = Reply.Set(strResponse);

	if(m_pNotification)
		m_pNotification->OnResponse(Reply);
	
	return fRet;
}

/// Reads a single response line from the server control channel.
/// @param[out] strResponse Response of the server as string.
bool CFTPClient::GetSingleResponseLine(CStringA& strResponse)
{
	if( !IsConnected() )
		return false;
	
	try
	{
		if( m_qResponseBuffer.empty() )
		{
			// internal buffer is empty ==> get response from ftp-server
			int iNum=0;
			CStringA strTemp;
			
			do
			{
				iNum = m_apSckControlConnection->Receive(m_vBuffer.GetData(), static_cast<int>(m_vBuffer.Length())-1, mc_uiTimeout);
				if( mc_uiResponseWait !=0 )
					Sleep(mc_uiResponseWait);
				m_vBuffer.SetAt(iNum,'\0');
				strTemp += m_vBuffer.GetData();
			} while( iNum==static_cast<int>(m_vBuffer.Length())-1 && m_apSckControlConnection->CheckReadability() );
			
			// each line in response is a separate entry in the internal buffer
			int nPos1 = 0,nPos2 = -1;
			nPos2 = strTemp.Find('\n',nPos1);
			while( nPos2 > -1 )
			{
				if( nPos2 != -1 )
				{
					m_qResponseBuffer.push(strTemp.Mid(nPos1, nPos2 - nPos1 + 1));
					nPos1 = nPos2 + 1;
					nPos2 = strTemp.Find('\n',nPos1);
				}
				else
				{
					// this is not rfc standard; normally each command must end with CRLF
					// in this case it doesn't
					m_qResponseBuffer.push(strTemp);
				}
			}
			
			if( m_qResponseBuffer.empty() )
				return false;
		}
		
		// get first response-line from buffer
		strResponse = m_qResponseBuffer.front();
		m_qResponseBuffer.pop();
		
		// remove CrLf if exists
		if( strResponse.GetLength() > 1 && strResponse.Mid(strResponse.GetLength()-2) == "\r\n")
		{
			strResponse = strResponse.Left(strResponse.GetLength()-2);
		}
	}
	catch(CBlockingSocketException& blockingException)
	{
		ReportError(blockingException.GetErrorMessage(), __FILE__, __LINE__);
		const_cast<CFTPClient*>(this)->m_apSckControlConnection->Cleanup();
		return false;
	}
	
	return true;
}

/// Executes the ftp command CDUP (change to parent directory).
/// This command is a special case of CFTPClient::ChangeWorkingDirectory 
/// (CWD), and is  included to simplify the implementation of programs for 
/// transferring directory trees between operating systems having different 
/// syntaxes for naming the parent directory.
/// @return see return values of CFTPClient::SimpleErrorCheck
int CFTPClient::ChangeToParentDirectory()
{
	CStringA strCmd;
	strCmd = (CMakeString() << "CDUP").GetString();
	
	CReply Reply;
	if( !SendCommand(strCmd, Reply) )
		return FTP_ERROR;
	return SimpleErrorCheck(Reply);
}

/// Executes the ftp command QUIT.
/// This command terminates a USER and if file transfer is not in progress, 
/// the server closes the control connection. If  file transfer is in progress, 
/// the connection will remain open for result response and the server will 
/// then close it.
/// If the user-process is transferring files for several USERs but does not 
/// wish to close and then reopen connections for each, then the REIN command 
/// should be used instead of QUIT.
/// An unexpected close on the control connection will cause the server to take 
/// the effective action of an abort (ABOR) and a logout.
/// @return see return values of CFTPClient::SimpleErrorCheck
int CFTPClient::Logout()
{
	CStringA strCmd;
	strCmd = (CMakeString() << "QUIT").GetString();
	
	CReply Reply;
	if( !SendCommand(strCmd, Reply) )
		return FTP_ERROR;
	
	CloseControlChannel();
	
	return SimpleErrorCheck(Reply);
}

/// Executes the ftp command PASV. Set the passive mode.
/// This command requests the server-DTP (data transfer process) on a data to 
/// "listen"  port (which is not its default data port) and to wait for a 
/// connection rather than initiate one upon receipt of a transfer command. 
/// The response to this command includes the host and port address this 
/// server is listening on.
/// @param[out] ulIpAddress IP address the server is listening on.
/// @param[out] ushPort Port the server is listening on.
/// @return see return values of CFTPClient::SimpleErrorCheck
int CFTPClient::Passive(ULONG& ulIpAddress, USHORT& ushPort)
{
	CStringA strCmd;
	strCmd = (CMakeString() << "PASV").GetString();
	
	CReply Reply;
	if( !SendCommand(strCmd, Reply) )
		return FTP_ERROR;
	
	if( Reply.Code().IsPositiveCompletionReply() )
	{
		if( !GetIpAddressFromResponse(Reply.Value(), ulIpAddress, ushPort) )
			return FTP_ERROR;
	}
	
	return SimpleErrorCheck(Reply);
}

/// Parses a response string and extracts the ip address and port information.
/// @param[in]  strResponse The response string of a ftp server which holds 
///                         the ip address and port information.
/// @param[out] ulIpAddress Buffer for the ip address.
/// @param[out] ushPort     Buffer for the port information.
/// @retval true  Everything went ok.
/// @retval false An error occurred (invalid format).
bool CFTPClient::GetIpAddressFromResponse(CStringA strResponse, ULONG& ulIpAddress, USHORT& ushPort)
{
	// parsing of ip-address and port implemented with a finite state machine
	// ...(192,168,1,1,3,44)...
	enum T_enState { state0, state1, state2, state3, state4 } enState = state0;
	
	CStringA strIpAddress, strPort;
	USHORT ushTempPort = 0;
	ULONG  ulTempIpAddress = 0;
	int iCommaCnt = 4;
	for( int it = 0; it < strResponse.GetLength(); it++ )
	{
		switch( enState )
		{
		case state0:
			if( strResponse.GetAt(it) == '(' )
				enState = state1;
			break;
		case state1:
			if( strResponse.GetAt(it) == ',' )
			{
				if( --iCommaCnt == 0 )
				{
					enState = state2;
					ulTempIpAddress += StringToLong(strIpAddress);
				}
				else
				{
					ulTempIpAddress += StringToLong(strIpAddress)<<8*iCommaCnt;
					strIpAddress = "";
				}
			}
			else
			{
				if( !_istdigit(strResponse.GetAt(it)) )
					return false;
				strIpAddress += strResponse.GetAt(it);
			}
			break;
		case state2:
			if( strResponse.GetAt(it) == ',' )
			{
				ushTempPort = static_cast<USHORT>(StringToLong(strPort)<<8);
				strPort = "";
				enState = state3;
			}
			else
			{
				if( !_istdigit(strResponse.GetAt(it)) )
					return false;
				strPort += strResponse.GetAt(it);
			}
			break;
		case state3:
			if( strResponse.GetAt(it) == ')' )
			{
				// compiler warning if using +=operator
				ushTempPort = ushTempPort + static_cast<USHORT>(StringToLong(strPort));
				enState = state4;
			}
			else
			{
				if( !_istdigit(strResponse.GetAt(it)) )
					return false;
				strPort += strResponse.GetAt(it);
			}
		}
	}
	
	if( enState==state4 )
	{
		ulIpAddress = ulTempIpAddress;
		ushPort = ushTempPort;
	}
	
	return enState==state4;
}

/// Executes the ftp command ABOR.
/// This command tells the server to abort the previous FTP service command 
/// and any associated transfer of data.  The abort command may require 
/// "special action", as discussed in the Section on FTP Commands, to force 
/// recognition by the server.  No action is to be taken if the previous 
/// command has been completed (including data transfer).  The control
/// connection is not to be closed by the server, but the data connection 
/// must be closed.
/// There are two cases for the server upon receipt of this command:<BR>
/// (1) the FTP service command was already completed, or <BR>
/// (2) the FTP service command is still in progress.<BR>
/// In the first case, the server closes the data connection (if it is open)
/// and responds with a 226 reply, indicating that the abort command was 
/// successfully processed.
/// In the second case, the server aborts the FTP service in progress and 
/// closes the data connection, returning a 426 reply to indicate that the 
/// service request terminated abnormally.  The server then sends a 226 reply,
/// indicating that the abort command was successfully processed.
/// @return see return values of CFTPClient::SimpleErrorCheck
int CFTPClient::Abort()
{
	if( m_fTransferInProgress )
	{
		m_fAbortTransfer = true;
		return FTP_OK;
	}
	
	CStringA strCmd;
	strCmd = (CMakeString() << "ABOR").GetString();
	
	m_fAbortTransfer = false;
	CReply Reply;
	if( !SendCommand(strCmd, Reply) )
		return FTP_ERROR;
	return SimpleErrorCheck(Reply);
}
/// Executes the ftp command PWD (PRINT WORKING DIRECTORY)
/// This command causes the name of the current working directory 
/// to be returned in the reply.
int CFTPClient::PrintWorkingDirectory()
{
	CStringA strCmd;
	strCmd = (CMakeString() << "PWD").GetString();
	
	CReply Reply;
	if( !SendCommand(strCmd, Reply) )
		return FTP_ERROR;
	return SimpleErrorCheck(Reply);
}

/// Executes the ftp command SYST (SYSTEM)
/// This command is used to find out the type of operating system at the server.
/// The reply shall have as its first word one of the system names listed in the 
/// current version of the Assigned Numbers document [Reynolds, Joyce, and 
/// Jon Postel, "Assigned Numbers", RFC 943, ISI, April 1985.].
/// @return see return values of CFTPClient::SimpleErrorCheck
int CFTPClient::System()
{
	CStringA strCmd;
	strCmd = (CMakeString() << "SYST").GetString();
	
	CReply Reply;
	if( !SendCommand(strCmd, Reply) )
		return FTP_ERROR;
	return SimpleErrorCheck(Reply);
}

/// Executes the ftp command NOOP
/// This command does not affect any parameters or previously entered commands. 
/// It specifies no action other than that the server send an FTP_OK reply.
/// @return see return values of CFTPClient::SimpleErrorCheck
int CFTPClient::Noop()
{
	CStringA strCmd;
	strCmd = (CMakeString() << "NOOP").GetString();
	
	CReply Reply;
	if( !SendCommand(strCmd, Reply) )
		return FTP_ERROR;
	return SimpleErrorCheck(Reply);
}

/// Executes the ftp command PORT (DATA PORT)
/// The argument is a HOST-PORT specification for the data port to be used in data 
/// connection. There are defaults for both the user and server data ports, and 
/// under normal circumstances this command and its reply are not needed.  If
/// this command is used, the argument is the concatenation of a 32-bit internet 
/// host address and a 16-bit TCP port address.
/// @param[in] strHostIP IP-address like xxx.xxx.xxx.xxx
/// @param[in] uiPort 16-bit TCP port address.
/// @return see return values of CFTPClient::SimpleErrorCheck
int CFTPClient::DataPort(CStringA& strHostIP, USHORT ushPort)
{
	CStringA strPortCmd;
	// convert the port number to 2 bytes + add to the local IP
	strPortCmd = (CMakeString() << "PORT " << strHostIP << "," << (ushPort>>8) << "," << (ushPort&0xFF)).GetString();
	
	strPortCmd.Replace(".", ",");
	
	CReply Reply;
	if( !SendCommand(strPortCmd, Reply) )
		return FTP_ERROR;
	return SimpleErrorCheck(Reply);
}

/// Executes the ftp command TYPE (REPRESENTATION TYPE)
/// see Documentation of nsFTP::CRepresentation
/// @param[in] representation see Documentation of nsFTP::CRepresentation
/// @param[in] iSize Indicates Bytesize for type LocalByte.
/// @return see return values of CFTPClient::SimpleErrorCheck
int CFTPClient::RepresentationType(CRepresentation& representation, DWORD dwSize)
{
	CStringA strCmd;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -