// ConnectSocket.cpp : implementation file
//
#include "stdafx.h"
#include "ftpserver.h"
#include "ConnectSocket.h"
#include "DataSocket.h"
extern CFTPServer theServer;
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CConnectSocket
CConnectSocket::CConnectSocket()
{
m_bLoggedon = FALSE;
m_bPassiveMode = FALSE;
m_strRemoteHost = "";
m_nRemotePort = -1;
m_dwRestartOffset = 0;
m_pDataSocket = NULL;//数据连接的socket要记得初始化
}
CConnectSocket::~CConnectSocket()
{
}
// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CConnectSocket, CSocket)
//{{AFX_MSG_MAP(CConnectSocket)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0
#define BUFFERSIZE 4096
/////////////////////////////////////////////////////////////////////////////
// CConnectSocket member functions
void CConnectSocket::OnReceive(int nErrorCode)
{
TCHAR buff[BUFFERSIZE];
int nRead = Receive(buff,BUFFERSIZE);
switch(nRead)
{
case 0:
Close();
break;
case SOCKET_ERROR:
if(GetLastError() != WSAEWOULDBLOCK)
{
TCHAR szError[256];
wsprintf(szError,"OnReceive error:%d",GetLastError());
AfxMessageBox(szError);
}
break;
default:
if(nRead != SOCKET_ERROR && nRead != 0)
{
//((CConnectThread*)AfxGetThread())->IncReceivedBytes(nRead);
buff[nRead] = 0;//再接收到的数据后面加上了' ',0是' '的ASCII码值。接受的命令(有的带参数)最后两个字符是\r(13)\n(10).
m_RxBuffer += CString(buff);
GetRxLine();
}
break;
}
CSocket::OnReceive(nErrorCode);
}
//解析整个命令行
void CConnectSocket::GetRxLine()
{
CString strTemp;
int nIndex;
while(!m_RxBuffer.IsEmpty())
{
//寻找换行符
nIndex = m_RxBuffer.Find("\r\n");
if(nIndex != -1)
{
strTemp = m_RxBuffer.Left(nIndex);
m_RxBuffer = m_RxBuffer.Mid(nIndex+2);
if(!strTemp.IsEmpty())
{
m_strCommands.AddTail(strTemp);
//解析并执行命令
ParseCommand();
}
}
else
break;
}
}
//FireStatusMessage通过调用这个函数在TracePage页面显示记录信息的。
//从缓冲区中获得命令
BOOL CConnectSocket::GetRxCommand(CString &strCommand, CString &strArguments)
{
if(!m_strCommands.IsEmpty())
{
CString strBuff = m_strCommands.RemoveHead();
int nIndex = strBuff.Find(" ");
if(nIndex != -1)
{
CString strPassword = strBuff;
strPassword.MakeUpper();
//是密码不可见
if(strPassword.Left(5) == "PASS")
{
for(int i=5; i<strPassword.GetLength(); i++)
{
strPassword.SetAt(i,'*');
}
FireStatusMessage(strPassword,1);
}
else
{
FireStatusMessage(strBuff,1);
}
strCommand = strBuff.Left(nIndex);
strArguments = strBuff.Mid(nIndex+1);
}
else
{
FireStatusMessage(strBuff,1);
strCommand = strBuff;
}
if(strCommand != "")
{
strCommand.MakeUpper();
if(strCommand.Right(4) == "ABOR")
{
strCommand = "ABOR";
}
TRACE2("COMMAND: %s, ARGS: %s\n", strCommand, strArguments);
return TRUE;
}
}
return FALSE;
}
void CConnectSocket::ParseCommand()
{
static CFTPCommand commandList[] =
{
{TOK_ABOR, "ABOR", FALSE, "Abort transfer: ABOR"},
{TOK_BYE, "BYE", FALSE, "Logout or break the connection: BYE"},
{TOK_CDUP, "CDUP", FALSE, "Change to parent directory: CDUP"},
{TOK_CWD, "CWD", TRUE, "Change working directory: CWD [directory-name]"},
{TOK_DELE, "DELE", TRUE , "Delete file: DELE file-name"},
{TOK_DIR, "DIR", FALSE, "Get directory listing: DIR [path-name]"},
{TOK_HELP, "HELP", FALSE, "Show help: HELP [command]"},
{TOK_LIST, "LIST", FALSE, "Get directory listing: LIST [path-name]"},
{TOK_MKD, "MKD", TRUE, "Make directory: MKD path-name"},
{TOK_NOOP, "NOOP", FALSE, "Do nothing: NOOP"},
{TOK_PASS, "PASS", TRUE, "Supply a user password: PASS password"},
{TOK_PASV, "PASV", FALSE, "Set server in passive mode: PASV"},
{TOK_PORT, "PORT", TRUE, "Specify the client port number: PORT a0,a1,a2,a3,a4,a5"},
{TOK_PWD, "PWD", FALSE, "Get current directory: PWD"},
{TOK_QUIT, "QUIT", FALSE, "Logout or break the connection: QUIT"},
{TOK_REST, "REST", TRUE, "Set restart transfer marker: REST marker"},
{TOK_RETR, "RETR", TRUE, "Get file: RETR file-name"},
{TOK_RMD, "RMD", TRUE, "Remove directory: RMD path-name"},
{TOK_RNFR, "RNFR", TRUE, "Specify old path name of file to be renamed: RNFR file-name"},
{TOK_RNTO, "RNTO", TRUE, "Specify new path name of file to be renamed: RNTO file-name"},
{TOK_SIZE, "SIZE", TRUE, "Get filesize: SIZE file-name"},
{TOK_STOR, "STOR", TRUE, "Store file: STOR file-name"},
{TOK_SYST, "SYST", FALSE, "Get operating system type: SYST"},
{TOK_TYPE, "TYPE", TRUE, "Set filetype: TYPE [A | I]"},
{TOK_USER, "USER", TRUE, "Supply a username: USER username"},
{TOK_ERROR, "", FALSE, ""},
};
CString strCommand,strArguments;
if(!GetRxCommand(strCommand,strArguments))
{
return;
}
int nCommand;
for(nCommand = TOK_ABOR; nCommand < TOK_ERROR; nCommand++)
{
if(strCommand == commandList[nCommand].m_pszName)
{
if(commandList[nCommand].m_bHasArguments && (strArguments.IsEmpty()))
{
SendResponse("501 Syntax error:Invalid number of parameters.");
//AfxMessageBox(_T("501 Syntax error:Invalid number of parameters."));
return;
}
break;
}
}
if(nCommand == TOK_ERROR)
{
SendResponse("501 Syntax error:Command not understood.");
//AfxMessageBox(_T("501 Syntax error:Command not understood."));
return;
}
if((nCommand != TOK_USER && nCommand != TOK_PASS) && !m_bLoggedon)
{
SendResponse("530 Please login with USER and PASS.");
//AfxMessageBox(_T("530 Please login with USER and PASS."));
return;
}
switch(nCommand)
{
//指定用户名
case TOK_USER:
{
strArguments.MakeLower();
m_bLoggedon = FALSE;
m_strUserName = strArguments;
CString strPeerAddress;
UINT nPeerPort;
GetPeerName(strPeerAddress,nPeerPort);
// 通知FTP服务器一个新的用户已经连接
CConnectThread *pThread = (CConnectThread*)m_pThread;
((CFTPServer *)pThread->m_pWndServer)->m_pEventSink->OnFTPUserConnected(m_pThread->m_nThreadID, m_strUserName, strPeerAddress);
SendResponse("331 User name ok,need password.");
//AfxMessageBox(_T("331 User name ok,need password."));//test!!!
}
break;
//指定密码
case TOK_PASS:
{
if(m_bLoggedon)
{
SendResponse("503 Login with USER first.");
//AfxMessageBox(_T("503 Login with USER first."));//test
}
else
{
CUserAccount useraccount;
if(theServer.m_UserManager.GetUserAccount(m_strUserName,useraccount))
{
if(!useraccount.m_strPassword.Compare(strArguments) || useraccount.m_strPassword.IsEmpty())
{
m_strCurrentDir = "/";
m_bLoggedon = TRUE;
SendResponse("230 User sucessfully logged in.");
break;
}
}
SendResponse("530 Not logged in,user or password incorrect!");
}
break;
// 改变传输模式
case TOK_TYPE:
{
SendResponse("200 Type set to %s", strArguments);
}
break;
//打印当前路径
case TOK_PWD:
{
SendResponse("257 \"%s\" is current directory.", m_strCurrentDir);
}
break;
//重新启动传输
case TOK_REST:
{
if(!IsNumeric(strArguments.GetBuffer(strArguments.GetLength())))
{
strArguments.ReleaseBuffer();
SendResponse("501 Invalid numeric!");
}
else
{
strArguments.ReleaseBuffer();
m_dwRestartOffset = atol(strArguments);
SendResponse("350 Restarting at %d.", m_dwRestartOffset);
}
}
break;
//改变到被动模式
case TOK_PASV:
{
//删除当前的数据连接
DestroyDataConnection();
//创建新的数据套接字连接
m_pDataSocket = new CDataSocket(this,-1);
if(!m_pDataSocket-
- 1
- 2
- 3
- 4
- 5
- 6
前往页