📄 connectsocket.cpp
字号:
break;
}
// 改变到被动模式
case TOK_PASV:
{
// 删除当前的数据连接
DestroyDataConnection();
// 创建新的数据套接字连接
m_pDataSocket = new CDataSocket(this, -1);
if (!m_pDataSocket->Create())
{
DestroyDataConnection();
SendResponse("421 Failed to create socket.");
break;
}
//开始侦听
m_pDataSocket->Listen();
m_pDataSocket->AsyncSelect();
CString strIP, strTmp;
UINT nPort;
// 获得我们的IP地址
GetSockName(strIP, nPort);
//获得端口号
m_pDataSocket->GetSockName(strTmp, nPort);
// 替换"."
strIP.Replace(".",",");
// 通知客户端要连接的IP地址和端口
SendResponse("227 Entering Passive Mode (%s,%d,%d).", strIP, nPort/256, nPort%256);
m_bPassiveMode = TRUE;
break;
}
// 列出当前路径
case TOK_LIST:
case TOK_DIR:
{
// 如果不是被动模式,我们先需要PORT命令指定端口
if(!m_bPassiveMode && (m_strRemoteHost == "" || m_nRemotePort == -1))
{
SendResponse("503 Bad sequence of commands.");
}
else
{
// 如果用户没有指定路径,用当前路径
if (strArguments == "")
{
strArguments = m_strCurrentDir;
}
else
{
// 检查参数是文件名还是路径
CString strResult;
int nResult = theServer.m_UserManager.CheckFileName(m_strUserName, strArguments, m_strCurrentDir, FTP_LIST, strResult);
if (nResult == 0)
{
strArguments = strResult;
}
}
CString strListing;
int nResult = theServer.m_UserManager.GetDirectoryList(m_strUserName, strArguments, strListing);
switch(nResult)
{
case 1:
SendResponse("550 Permission denied.");
break;
case 2:
SendResponse("550 Directory not found.");
break;
default:
//创建套接字连接获得路径列表
if (!CreateDataConnection(0, strListing))
{
DestroyDataConnection();
}
break;
}
}
break;
}
// 获得文件
case TOK_RETR:
{
// 如果不是被动模式,我们先需要PORT命令指定端口
if(!m_bPassiveMode && (m_strRemoteHost == "" || m_nRemotePort == -1))
{
SendResponse("503 Bad sequence of commands.");
break;
}
CString strResult;
int nResult = theServer.m_UserManager.CheckFileName(m_strUserName, strArguments, m_strCurrentDir, FTP_DOWNLOAD, strResult);
switch(nResult)
{
case 1:
SendResponse("550 Permission denied.");
break;
case 2:
SendResponse("550 File not found.");
break;
default:
//为文件传输创建一个套接字
if (!CreateDataConnection(1, strResult))
{
DestroyDataConnection();
}
break;
}
break;
}
//客户端上传文件
case TOK_STOR:
{
// 如果不是被动模式,我们先需要PORT命令指定端口
if(!m_bPassiveMode && (m_strRemoteHost == "" || m_nRemotePort == -1))
{
SendResponse("503 Bad sequence of commands.");
break;
}
CString strResult;
int nResult = theServer.m_UserManager.CheckFileName(m_strUserName, strArguments, m_strCurrentDir, FTP_UPLOAD, strResult);
switch(nResult)
{
case 1:
SendResponse("550 Permission denied.");
break;
case 2:
SendResponse("550 Filename invalid.");
break;
default:
//为文件传输创建一个套接字
if (!CreateDataConnection(2, strResult))
{
DestroyDataConnection();
}
break;
}
}
break;
//获得文件大小
case TOK_SIZE:
{
CString strResult;
int nResult = theServer.m_UserManager.CheckFileName(m_strUserName, strArguments, m_strCurrentDir, FTP_DOWNLOAD, strResult);
switch(nResult)
{
case 1:
SendResponse("550 Permission denied.");
break;
case 2:
SendResponse("550 File not found.");
break;
default:
{
CFileStatus status;
CFile::GetStatus(strResult, status);
SendResponse("213 %d", status.m_size);
break;
}
}
}
break;
// 删除文件
case TOK_DELE:
{
CString strResult;
int nResult = theServer.m_UserManager.CheckFileName(m_strUserName, strArguments, m_strCurrentDir, FTP_DELETE, strResult);
switch(nResult)
{
case 1:
SendResponse("550 Permission denied.");
break;
case 2:
SendResponse("550 File not found.");
break;
default:
//删除文件
if (!DeleteFile(strResult))
{
SendResponse("450 Internal error deleting the file: \"%s\".", strArguments);
}
else
{
SendResponse("250 File \"%s\" was deleted successfully.", strArguments);
}
break;
}
}
break;
// 删除目录
case TOK_RMD:
{
CString strResult;
int nResult = theServer.m_UserManager.CheckDirectory(m_strUserName, strArguments, m_strCurrentDir, FTP_DELETE, strResult);
switch(nResult)
{
case 1:
SendResponse("550 Permission denied.");
break;
case 2:
SendResponse("550 Directory not found.");
break;
default:
// 删除目录
if (!RemoveDirectory(strResult))
{
if (GetLastError() == ERROR_DIR_NOT_EMPTY)
{
SendResponse("550 Directory not empty.");
}
else
{
SendResponse("450 Internal error deleting the directory.");
}
}
else
{
SendResponse("250 Directory deleted successfully.");
}
break;
}
}
break;
// 创建目录
case TOK_MKD:
{
CString strResult;
int nResult = theServer.m_UserManager.CheckDirectory(m_strUserName, strArguments, m_strCurrentDir, FTP_CREATE_DIR, strResult);
switch(nResult)
{
case 0:
SendResponse("550 Directory already exists.");
break;
case 1:
SendResponse("550 Can't create directory. Permission denied.");
break;
default:
//创建目录
if (!MakeSureDirectoryPathExists(strResult))
{
SendResponse("450 Internal error creating the directory.");
}
else
{
SendResponse("250 Directory created successfully.");
}
break;
}
}
break;
//重命名文件名或者路径
case TOK_RNFR:
{
CString strResult;
int nResult = theServer.m_UserManager.CheckFileName(m_strUserName, strArguments, m_strCurrentDir, FTP_RENAME, strResult);
if (nResult == 0)
{
m_strRenameFile = strResult;
m_bRenameFile = TRUE;
SendResponse("350 File exists, ready for destination name.");
break;
}
else
{
// 用户端重命名目录
nResult = theServer.m_UserManager.CheckDirectory(m_strUserName, strArguments, m_strCurrentDir, FTP_RENAME, strResult);
switch(nResult)
{
case 0:
m_strRenameFile = strResult;
m_bRenameFile = FALSE;
SendResponse("350 Directory exists, ready for destination name.");
break;
case 1:
SendResponse("550 Permission denied.");
break;
default:
SendResponse("550 File/directory not found.");
break;
}
}
}
break;
// 重命名文件名或目录
case TOK_RNTO:
{
if (m_strRenameFile.IsEmpty())
{
SendResponse("503 Bad sequence of commands.");
break;
}
if (m_bRenameFile)
{
CString strResult;
// 检查目标文件名
int nResult = theServer.m_UserManager.CheckFileName(m_strUserName, strArguments, m_strCurrentDir, FTP_RENAME, strResult);
switch(nResult)
{
case 0:
SendResponse("550 File already exists.");
break;
case 1:
SendResponse("550 Permission denied.");
break;
default:
// 重命名文件
if (!MoveFile(m_strRenameFile, strResult))
{
SendResponse("450 Internal error renaming the file: \"%s\".", m_strRenameFile);
}
else
{
SendResponse("250 File \"%s\" renamed successfully.", m_strRenameFile);
}
break;
}
}
else
{
CString strResult;
// 检查目标路径名
int nResult = theServer.m_UserManager.CheckDirectory(m_strUserName, strArguments, m_strCurrentDir, FTP_RENAME, strResult);
switch(nResult)
{
case 0:
SendResponse("550 Directory already exists.");
break;
case 1:
SendResponse("550 Permission denied.");
break;
case 3:
SendResponse("550 Directory invalid.");
break;
default:
// 重命名路径
if (!MoveFile(m_strRenameFile, strResult))
{
SendResponse("450 Internal error renaming the directory: \"%s\".", m_strRenameFile);
}
else
{
SendResponse("250 Directory \"%s\" renamed successfully.", m_strRenameFile);
}
break;
}
}
}
break;
// 取消传输
case TOK_ABOR:
{
if (m_pDataSocket)
{
if (m_pDataSocket->GetStatus() != XFERMODE_IDLE)
{
SendResponse("426 Data connection closed.");
}
//销毁数据连接
m_pThread->PostThreadMessage(WM_THREADMSG, 0, 0);
}
SendResponse("226 ABOR command successful.");
break;
}
// 获得系统信息
case TOK_SYST:
SendResponse("215 UNIX emulated by Li's FTP Server.");
break;
// 关闭连接
case TOK_QUIT:
case TOK_BYE:
{
// 发送再见消息给客户机
CConnectThread *pThread = (CConnectThread *)m_pThread;
SendResponse("220 %s", ((CFTPServer *)pThread->m_pWndServer)->GetGoodbyeMessage());
Close();
//通知线程已经结束关闭连接
m_pThread->PostThreadMessage(WM_THREADMSG, 1, 0);
break;
}
//重新启动传输
case TOK_REST:
{
if (!IsNumeric(strArguments.GetBuffer(strArguments.GetLength())))
{
strArguments.ReleaseBuffer();
SendResponse("501 Invalid parameter.");
}
else
{
strArguments.ReleaseBuffer();
m_dwRestartOffset = atol(strArguments);
SendResponse("350 Restarting at %d.", m_dwRestartOffset);
}
}
break;
//显示帮助信息
case TOK_HELP:
//如果客户端不指定命令名显示所有可有命令
if (strArguments == "")
{
CString strResponse = "214-The following commands are recognized:\r\n";
// 在命令列表中查找命令
for (int i = TOK_ABOR; i < TOK_ERROR; i++)
{
strResponse += commandList[i].m_pszName;
strResponse += "\r\n";
}
strResponse += "214 HELP command successful.";
SendResponse(strResponse);
}
else
{
int nHelpCmd;
// 在命令列表中查找命令
for (nHelpCmd = TOK_ABOR; nHelpCmd < TOK_ERROR; nHelpCmd++)
{
//判断是否找到命令
if (strArguments.CompareNoCase(commandList[nHelpCmd].m_pszName) == 0)
{
break;
}
}
if (nHelpCmd != TOK_ERROR)
{
//显示命令帮助信息
SendResponse("214 %s", commandList[nHelpCmd].m_pszDescription);
}
else
{
SendResponse("501 Unknown command %s", strArguments);
}
}
break;
// 空命令
case TOK_NOOP:
SendResponse("200 OK");
break;
default:
SendResponse("502 Command not implemented - Try HELP.");
break;
}
}
/********************************************************************/
/* */
/* Function name: FireStatusMessage */
/* Description : Fire status message. */
/* */
/********************************************************************/
void CConnectSocket::FireStatusMessage(LPCTSTR lpszStatus, int nType)
{
CConnectThread *pThread = (CConnectThread *)m_pThread;
((CFTPServer *)pThread->m_pWndServer)->AddTraceLine(nType, "[%d] %s", m_pThread->m_nThreadID, lpszStatus);
}
/********************************************************************/
/* */
/* Function name: CreateDataConnection */
/* Description : Create data transfer connection. */
/* */
/********************************************************************/
BOOL CConnectSocket::CreateDataConnection(int nTransferType, LPCTSTR lpszData)
{
if (!m_bPassiveMode)
{
m_pDataSocket = new CDataSocket(this, nTransferType);
if (m_pDataSocket->Create())
{
m_pDataSocket->AsyncSelect();
m_pDataSocket->SetRestartOffset(m_dwRestartOffset);
m_pDataSocket->SetData(lpszData);
// connect to remote site
if (m_pDataSocket->Connect(m_strRemoteHost, m_nRemotePort) == 0)
{
if (GetLastError() != WSAEWOULDBLOCK)
{
SendResponse("425 Can't open data connection.");
return FALSE;
}
}
switch(nTransferType)
{
case 0:
SendResponse("150 Opening ASCII mode data connection for directory list.");
break;
case 1:
case 2:
SendResponse("150 Opening BINARY mode data connection for file transfer.");
break;
}
}
else
{
SendResponse("421 Failed to create data connection socket.");
return FALSE;
}
}
else
{
m_pDataSocket->SetRestartOffset(m_dwRestartOffset);
m_pDataSocket->SetData(lpszData);
m_pDataSocket->SetTransferType(nTransferType, TRUE);
}
return TRUE;
}
/********************************************************************/
/* */
/* Function name: DestroyDataConnection */
/* Description : Close data transfer connection. */
/* */
/********************************************************************/
void CConnectSocket::DestroyDataConnection()
{
if (!m_pDataSocket)
return;
delete m_pDataSocket;
// reset transfer status
m_pDataSocket = NULL;
m_strRemoteHost = "";
m_nRemotePort = -1;
m_dwRestartOffset = 0;
m_bPassiveMode = FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -