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

📄 ftpcommandprocessor.cpp

📁 一个电视台专用的信息管理软件源代码
💻 CPP
字号:
// FTPCommandProcessor.cpp: implementation of the CFTPCommandProcessor class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "tvnews.h"
#include "FTPCommandProcessor.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

//构造函数,变量初始化
CFTPCommandProcessor::CFTPCommandProcessor()
{
	m_pCtrlsokfile=NULL;
	m_pCtrlTxarch=NULL;
	m_pCtrlRxarch=NULL;
	m_Ctrlsok=NULL;
}


CFTPCommandProcessor::~CFTPCommandProcessor()
{
	CloseControlChannel();
}


//////////////////////////////////////////////////////////////////////
// Public Functions
//////////////////////////////////////////////////////////////////////


// 登录到服务器
BOOL CFTPCommandProcessor::LogOnToServer(CString hostname,int hostport,CString username, CString password, CString acct, CString fwhost,CString fwusername, CString fwpassword,int fwport,int logontype) 
{
	int port,logonpoint=0;
	const int LO=-2, ER=-1;
	CString buf,temp;
	const int NUMLOGIN=9; // 支持9种不同的登录方式
	int logonseq[NUMLOGIN][100] = {
		// 下面的数组保存了针对不同防火墙的登录序列
		{0,LO,3, 1,LO,6, 2,LO,ER}, // 没有防火墙
		{3,6,3, 4,6,ER, 5,ER,9, 0,LO,12, 1,LO,15, 2,LO,ER}, // 主机名
		{3,6,3, 4,6,ER, 6,LO,9, 1,LO,12, 2,LO,ER}, // USER after logon
		{7,3,3, 0,LO,6, 1,LO,9, 2,LO,ER}, //proxy OPEN
		{3,6,3, 4,6,ER, 0,LO,9, 1,LO,12, 2,LO,ER}, // Transparent
		{6,LO,3, 1,LO,6, 2,LO,ER}, // USER with no logon
		{8,6,3, 4,6,ER, 0,LO,9, 1,LO,12, 2,LO,ER}, //USER fireID@remotehost
		{9,ER,3, 1,LO,6, 2,LO,ER}, //USER remoteID@remotehost fireID
		{10,LO,3, 11,LO,6, 2,LO,ER} // USER remoteID@fireID@remotehost
	};

	if(logontype<0||logontype>=NUMLOGIN) return FALSE; // illegal connect code
	if(!logontype) {
		temp=hostname;
		port=hostport;
	}
	else {
		temp=fwhost;
		port=fwport;
	}
	if(hostport!=21) 
		hostname.Format(hostname+":%d",hostport); // 如果端口不是默认端口21,则设定端口
	if(!OpenControlChannel(temp,port)) 
		return false;
	if(!FTPcommand("")) 
		return FALSE; // 获得连接服务器初始化信息
	// 获得登录类型
	while(1) {
		switch(logonseq[logontype][logonpoint]) {
		case 0:
			temp="USER "+username;
			break;
		case 1:
			temp="PASS "+password;
			break;
		case 2:
			temp="ACCT "+acct;
			break;
		case 3:
			temp="USER "+fwusername;
			break;
		case 4:
			temp="PASS "+fwpassword;
			break;
		case 5:
			temp="SITE "+hostname;
			break;
		case 6:
			temp="USER "+username+"@"+hostname;
			break;
		case 7:
			temp="OPEN "+hostname;
			break;
		case 8:
			temp="USER "+fwusername+"@"+hostname;
			break;
		case 9:
			temp="USER "+username+"@"+hostname+" "+fwusername;
			break;
		case 10:
			temp="USER "+username+"@"+fwusername+"@"+hostname;
			break;
		case 11:
			temp="PASS "+password+"@"+fwpassword;
			break;
		}
		// 发出命令,获得响应
		if(!WriteStr(temp)) return FALSE;
		if(!ReadStr()) return FALSE;
		// 只有这些响应是合法的
		if(m_fc!=2&&m_fc!=3) return FALSE;
		logonpoint=logonseq[logontype][logonpoint+m_fc-1]; //get next command from array
		switch(logonpoint) {
		case ER: // 出现错误
			m_retmsg.LoadString(IDS_FTPMSG1);
			return FALSE;
		case LO: // L0表示成功登录
			return TRUE;
		}
	}
}


// 退出服务器
void CFTPCommandProcessor::LogOffServer() 
{
	WriteStr("QUIT");
	CloseControlChannel();
}


// 发送命令到服务器
BOOL CFTPCommandProcessor::FTPcommand(CString command) 
{
	if(command!=""&&!WriteStr(command)) return FALSE;
	if((!ReadStr())||(m_fc!=2)) return FALSE;
	return TRUE;
}


// 上载或者下载文件
BOOL CFTPCommandProcessor::MoveFile(CString remotefile, CString localfile,BOOL pasv,BOOL get) 
{
	CString lhost,temp,rhost;
	UINT localsock,serversock,i,j;
	CFile datafile;
	CSocket sockSrvr;
	CAsyncSocket datachannel;
	int num,numread,numsent;
	const int BUFSIZE=4096;
	char cbuf[BUFSIZE];
	DWORD lpArgument=0;
	
	// 打开本地文件
	if(!datafile.Open(localfile,(get?CFile::modeWrite|CFile::modeCreate:CFile::modeRead))) {
		m_retmsg.LoadString(IDS_FTPMSG4);
		return FALSE;
	}
	if(!FTPcommand("TYPE I")) return FALSE; // 请求二进制传输
	if(pasv) { // 建立被动传输方式
		if(!FTPcommand("PASV")) return FALSE;
		// 分析出服务器传回的临时IP地址以及端口号
		if((i=m_retmsg.Find("("))==-1||(j=m_retmsg.Find(")"))==-1) return FALSE;
		temp=m_retmsg.Mid(i+1,(j-i)-1);
		i=temp.ReverseFind(',');
		serversock=atol(temp.Right(temp.GetLength()-(i+1))); //get ls byte of server socket
		temp=temp.Left(i);
		i=temp.ReverseFind(',');
		serversock+=256*atol(temp.Right(temp.GetLength()-(i+1))); // add ms byte to server socket
		rhost=temp.Left(i);
		while(1) { // 将逗号转化成点
			if((i=rhost.Find(","))==-1) break;
			rhost.SetAt(i,'.');
		}
	}
	else { // 设置主动的传输模式
		m_retmsg.LoadString(IDS_FTPMSG6);
		//获取本地的ip地址,发送到服务器
		if(!m_Ctrlsok->GetSockName(lhost,localsock)) return FALSE;;
		while(1) { // 将IP地址中的点转化成逗号
			if((i=lhost.Find("."))==-1) break;
			lhost.SetAt(i,',');
		}
		// 创建本地侦听进程
		if((!sockSrvr.Create(0,SOCK_STREAM,NULL))||(!sockSrvr.Listen())) return FALSE;
		if(!sockSrvr.GetSockName(temp,localsock)) return FALSE;// get the port that MFC chose
		// 将端口转化成2字节,然后加入到本地IP地址中
		lhost.Format(lhost+",%d,%d",localsock/256,localsock%256);
		if(!FTPcommand("PORT "+lhost)) return FALSE;// 发送端口到服务器
	}
	// 发送 RETR/STOR 命令到服务器
	if(!WriteStr((get?"RETR ":"STOR ")+remotefile)) return FALSE;
	if(pasv) {// 如果是PASV模式,则创建socket并初始化外部数据连接,即数据传输通道
		if(!datachannel.Create()) {
			m_retmsg.LoadString(IDS_FTPMSG6);
			return FALSE;
		}
		datachannel.Connect(rhost,serversock); // 试图异步连接服务器
	}
	if(!ReadStr()||m_fc!=1) return FALSE; // 获得服务器响应
	if(!pasv&&!sockSrvr.Accept(datachannel)) return FALSE; // 接收从服务器来的内部绑定数据
	// 连接成功,然后进行阻塞式数据传输
	if((!datachannel.AsyncSelect(0))||(!datachannel.IOCtl(FIONBIO,&lpArgument))) {
		m_retmsg.LoadString(IDS_FTPMSG6);
		return FALSE;
	}
	while(1) { // 开始传输数据
		TRY {
			if(get) {
				if(!(num=datachannel.Receive(cbuf,BUFSIZE,0))||num==SOCKET_ERROR) break; // (EOF||network error)
				else datafile.Write(cbuf,num);
			}
			else {
				if(!(numread=datafile.Read(cbuf,BUFSIZE))) break; //EOF
				if((numsent=datachannel.Send(cbuf,numread,0))==SOCKET_ERROR) break;
				// 如果发送出去的字节少于从文件读取的字节,则调整发送指针,以使得数据发送正确
				if(numread!=numsent) datafile.Seek(numsent-numread,CFile::current);
			}
		}
		CATCH (CException,e) {
			m_retmsg.LoadString(IDS_FTPMSG5);
			return FALSE;
		}
		END_CATCH
	}
	datachannel.Close();
	datafile.Close();
	if(!FTPcommand("")) return FALSE; // 检查从服务器发送的传输结果信息
	return TRUE; // 传输成功
}


// 通过控制通道向服务器发送命令
BOOL CFTPCommandProcessor::WriteStr(CString outputstring) 
{
	m_retmsg.LoadString(IDS_FTPMSG6); // pre-load "network error" msg (in case there is one) #-)
	TRY 
	{
		m_pCtrlTxarch->WriteString(outputstring+"\r\n");
		m_pCtrlTxarch->Flush();
	}

	CATCH(CException,e) 
	{
		return FALSE;
	}
	END_CATCH
	return TRUE;
}


// 获得服务器的响应
BOOL CFTPCommandProcessor::ReadStr() 
{
	int retcode;

	if(!ReadStr2()) return FALSE;

	if(m_retmsg.GetLength()<4||m_retmsg.GetAt(3)!='-') return TRUE;
	retcode=atol(m_retmsg);
	while(1) 
	{ //处理多行服务器响应

		if(m_retmsg.GetLength()>3&&(m_retmsg.GetAt(3)==' '&&atol(m_retmsg)==retcode)) 
			return TRUE;
		if(!ReadStr2()) 
			return FALSE;
	}
}



//////////////////////////////////////////////////////////////////////
// Private functions
//////////////////////////////////////////////////////////////////////


// 从服务器控制通道获取一行响应
BOOL CFTPCommandProcessor::ReadStr2() 
{
	TRY 
	{
		if(!m_pCtrlRxarch->ReadString(m_retmsg)) 
		{
			m_retmsg.LoadString(IDS_FTPMSG6);
			return FALSE;
		}
	}
	CATCH(CException,e) 
	{
		m_retmsg.LoadString(IDS_FTPMSG6);
		return FALSE;
	}
	END_CATCH
	if(m_retmsg.GetLength()>0) m_fc=m_retmsg.GetAt(0)-48; // get 1st digit of the return code (indicates primary result)
	return TRUE;
}


// 打开控制通道
BOOL CFTPCommandProcessor::OpenControlChannel(CString serverhost,int serverport) 
{
	m_retmsg.LoadString(IDS_FTPMSG2);
	if(!(m_Ctrlsok=new CSocket)) 
		return FALSE;

	WSADATA    wsaData;
    WORD    version=MAKEWORD(2,0);
    int    ret=WSAStartup(version,&wsaData);
    if(ret!=0)
	{
        AfxMessageBox("网络初始化失败!");
		return FALSE;
	} 

	if(!(m_Ctrlsok->Create())) 
		return FALSE;
	m_retmsg.LoadString(IDS_FTPMSG3);
	if(!(m_Ctrlsok->Connect(serverhost,serverport))) 
		return FALSE;
	m_retmsg.LoadString(IDS_FTPMSG2);
	if(!(m_pCtrlsokfile=new CSocketFile(m_Ctrlsok))) 
		return FALSE;
	if(!(m_pCtrlRxarch=new CArchive(m_pCtrlsokfile,CArchive::load))) 
		return FALSE;
	if(!(m_pCtrlTxarch=new CArchive(m_pCtrlsokfile,CArchive::store))) 
		return FALSE;

	return TRUE;
}


// 关闭控制通道
void CFTPCommandProcessor::CloseControlChannel() 
{
	if(m_pCtrlTxarch) delete m_pCtrlTxarch;
	m_pCtrlTxarch=NULL;
	if(m_pCtrlRxarch) delete m_pCtrlRxarch;
	m_pCtrlRxarch=NULL;
	if(m_pCtrlsokfile) delete m_pCtrlsokfile;
	m_pCtrlsokfile=NULL;
	if(m_Ctrlsok) delete m_Ctrlsok;
	m_Ctrlsok=NULL;
	return;
}


//列出文件列表
BOOL CFTPCommandProcessor::List()
{
	CString lhost,temp,rhost;
	UINT localsock,i;
	CFile datafile;
	CSocket sockSrvr;
	CAsyncSocket datachannel;
	int num, sum;
	const int BUFSIZE = 4096;
	DWORD lpArgument=0;
	
	m_buf.RemoveAll();
	m_buf.SetSize(BUFSIZE);
	if(!FTPcommand("TYPE I")) 
		return FALSE; // 请求二进制模式

	m_retmsg.LoadString(IDS_FTPMSG6);
	// 获取本地IP地址
	if(!m_Ctrlsok->GetSockName(lhost,localsock)) 
		return FALSE;;
	while(1) {
		// 将点转化成逗号
		if((i=lhost.Find("."))==-1) break;
		lhost.SetAt(i,',');
	}
	if((!sockSrvr.Create(0, SOCK_STREAM, NULL))
			|| (!sockSrvr.Listen()))
		return FALSE;
	if(!sockSrvr.GetSockName(temp,localsock))
		return FALSE;
	lhost.Format(lhost+",%d,%d", localsock / 256, localsock % 256);
	if(!FTPcommand("PORT "+lhost)) 
		return FALSE;

	if(!WriteStr("LIST") )
		return FALSE;
	if(!ReadStr())
		return FALSE; 
	if(!sockSrvr.Accept(datachannel)) 
		return FALSE; 
	if((!datachannel.AsyncSelect(0)) || 
		(!datachannel.IOCtl(FIONBIO,&lpArgument))) {
		m_retmsg.LoadString(IDS_FTPMSG6);
		return FALSE;
	}
	sum = 0;
	while(1) { // 获得数据
		TRY {
			if(!(num = datachannel.Receive(m_buf.GetData() + sum, BUFSIZE, 0)) 
				|| num == SOCKET_ERROR)
				break;
			TRACE("Received :%d\n", num);
			Sleep(0);
			sum += num;
			m_buf.SetSize(sum + BUFSIZE);
		}
		CATCH (CException,e) {
			m_retmsg.LoadString(IDS_FTPMSG5);
			return FALSE;
		}
		END_CATCH
	}
	datachannel.Close();
}


void CFTPCommandProcessor::ProcessList()
{
}

BOOL CFTPCommandProcessor::GetLine(int& ndx)
{
	m_strLine.Empty();
	int nBytes = m_buf.GetSize();
	BOOL bLine = FALSE;
	while ( bLine == FALSE && ndx < nBytes )
	{
		char ch = (char)(m_buf.GetAt( ndx ));
		switch( ch )
		{
		case '\n': // 行尾
			bLine = TRUE;
			break;
		default:   // 其他情况
			m_strLine += ch;
			break;
		}
		++ndx;
	}
	m_strLine = m_strLine.Left(m_strLine.GetLength() - 1);
	return bLine;
}

⌨️ 快捷键说明

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