📄 ftp-server-code.txt
字号:
if( GetFullUnixPath(command+i, m_szUnixWorkDir, unixFullPath)
&& UnixPathToDosPath(unixFullPath, dosFullPath)
&& ( memicmp(command, "RETR", 4) != 0 || ExistFile(dosFullPath) ) )
{
m_block.sockData = GetDataSocket();
if( m_block.sockData != INVALID_SOCKET )
{
m_block.sockCtrl = m_sockCtrl;
strcpy(m_block.filename, dosFullPath);
if( memicmp(command, "RETR", 4)==0 )
m_block.translateType = TYPE_RETR;
else if( memicmp(command, "STOR", 4) == 0 )
m_block.translateType = TYPE_STOR;
else
m_block.translateType = TYPE_APPE;
m_block.bDeleteFileAfterCompletion = FALSE;
m_block.bAbort = FALSE;
m_block.bThreadExited = FALSE;
DWORD threadId;
HANDLE hThread = CreateThread(NULL, 0, FtpDataThreadProc, &m_block, 0, &threadId);
CloseHandle(hThread);
bReplyHasSend = TRUE;
}
else
sprintf(line, "450 cannot open data connection\r\n");
}
else
sprintf(line, "550 %s not found, or cannot be created\r\n", command + i);
}
else if( memicmp(command, "STOU", 4) == 0 )
{
bCommandNotSupport = TRUE;
}
else if( memicmp(command, "ALLO", 4) == 0 )
{
sprintf(line, "250 ALLO ok!\r\n");
}
else if( memicmp(command, "REST", 4) == 0 )
{
m_block.dwStartPos = atoi(command+4);
sprintf(line, "350 start pos set to %u\r\n", m_block.dwStartPos);
}
else if( memicmp(command, "RNFR", 4) == 0 )
{
for(int i=4; ' ' == command[i]; i++)NULL; //skip white space
char unixFullPath[MAX_PATH], dosFullPath[MAX_PATH];
if( GetFullUnixPath(command+i, m_szUnixWorkDir, unixFullPath)
&& UnixPathToDosPath( unixFullPath, dosFullPath)
&& ExistFileOrDirectory(dosFullPath) )
{
strcpy(m_szUnixRnfrName, unixFullPath);
m_status = SERVER_NEED_RNTO;
sprintf(line, "350 RNFR ( %s ) ok, need RNTO \r\n", m_szUnixRnfrName);
}
else
sprintf(line, "500 %s not exist\r\n", command+i);
}
else if( memicmp(command, "ABOR", 4) == 0 )
{
if( m_block.bThreadExited == FALSE )
{
m_block.bAbort = TRUE;
bReplyHasSend = TRUE;
}
else
sprintf(line, "225 abort ok\r\n");
}
else if( memicmp(command, "DELE", 4) == 0 )
{
for(int i=4; ' ' == command[i]; i++)NULL; //skip white space
char unixFullPath[MAX_PATH], dosFullPath[MAX_PATH];
if( GetFullUnixPath(command+i, m_szUnixWorkDir, unixFullPath)
&& UnixPathToDosPath( unixFullPath, dosFullPath)
&& ExistFile(dosFullPath)
&& DeleteFile(dosFullPath) )
{
sprintf(line, "250 file ( %s ) deleted\r\n", unixFullPath);
}
else
sprintf(line, "500 ( %s )doesn't exist or cannot be deleted\r\n", command+i);
}
else if( memicmp(command, "RMD", 3) == 0 )
{
for(int i=3; ' ' == command[i]; i++)NULL; //skip white space
char unixFullPath[MAX_PATH], dosFullPath[MAX_PATH];
if( GetFullUnixPath(command+i, m_szUnixWorkDir, unixFullPath)
&& UnixPathToDosPath( unixFullPath, dosFullPath)
&& ExistDirectory(dosFullPath)
&& RemoveDirectory(dosFullPath) )
{
sprintf(line, "250 directory ( %s ) deleted\r\n", unixFullPath);
}
else
sprintf(line, "500 ( %s ) doesn't exist or cannot be remove\r\n", command+i);
}
else if( memicmp(command, "MKD", 3) == 0 )
{
for(int i=3; ' ' == command[i]; i++)NULL; //skip white space
char unixFullPath[MAX_PATH], dosFullPath[MAX_PATH];
if( GetFullUnixPath(command+i, m_szUnixWorkDir, unixFullPath)
&& UnixPathToDosPath( unixFullPath, dosFullPath)
&& CreateDirectory( dosFullPath, NULL) )
{
sprintf(line, "250 directory ( %s ) created\r\n", unixFullPath);
}
else
sprintf(line, "500 ( %s ) cannot be created\r\n", command+i);
}
else if( memicmp(command, "PWD", 3) == 0 )
{
sprintf(line, "257 \"%s\" is current directory\r\n", m_szUnixWorkDir);
}
else if( memicmp(command, "LIST", 4) == 0
|| memicmp(command, "NLST", 4) == 0 )
{
char tempFile[MAX_PATH];
GetTempFullFileName(tempFile);
FILE *fp = fopen(tempFile, "wb");
if( fp )
{
GetListResult(command, m_szUnixWorkDir, fp);
fclose(fp);
m_block.sockData = GetDataSocket();
if( m_block.sockData == INVALID_SOCKET )
sprintf(line, "450 cannot open data connection\r\n");
else
{
m_block.sockCtrl = m_sockCtrl;
strcpy(m_block.filename, tempFile);
m_block.translateType = TYPE_RETR;
m_block.bDeleteFileAfterCompletion = TRUE;
m_block.bAbort = FALSE;
m_block.bThreadExited = FALSE;
DWORD threadId;
HANDLE hThread = CreateThread(NULL, 0, FtpDataThreadProc, &m_block, 0, &threadId);
CloseHandle(hThread);
bReplyHasSend = TRUE;
}
}
else
sprintf(line, "450 cannot create temporary file( %s )\r\n", tempFile);
}
else if( memicmp(command, "SITE", 4) == 0 )
{
bCommandNotSupport = TRUE;
}
else if( memicmp(command, "SYST", 4) == 0 )
{
sprintf(line, "215 Windows\r\n");
}
else if( memicmp(command, "STAT", 4) == 0 )
{
bCommandNotSupport = TRUE;
}
else if( memicmp(command, "HELP", 4) == 0 )
{
bCommandNotSupport = TRUE;
}
else if( memicmp(command, "NOOP", 4) == 0 )
{
sprintf(line, "200 NOOP ok\r\n");
}
//command that aren't standard
else if( memicmp(command, "SIZE", 4) == 0 )
{
for(int i=4; ' ' == command[i]; i++)NULL; //skip white space
char unixFullPath[MAX_PATH], dosFullPath[MAX_PATH];
DWORD dwFileLength;
if( GetFullUnixPath(command+i, m_szUnixWorkDir, unixFullPath)
&& UnixPathToDosPath( unixFullPath, dosFullPath)
&& ExistFile(dosFullPath)
&& GetFileLength(dosFullPath, &dwFileLength) )
{
sprintf(line, "213 %lu\r\n", dwFileLength);
}
else
sprintf(line, "500 %s not exist, or cannot get length\r\n", command+i);
}
//unsupported commands
else
{
bCommandNotSupport = TRUE;
}
}
else if( m_status == SERVER_NEED_USER )
{
if( memicmp(command, "USER", 4)==0 )
{
sprintf(line, "331 password required for %s\r\n", command + 5);
m_status = SERVER_NEED_PASS;
}
else
{
sprintf(line, "500 USER command required now\r\n");
}
}
else if( m_status == SERVER_NEED_PASS )
{
if( memicmp(command, "PASS", 4)==0 )
{
sprintf(line, "230 access permitted for you\r\n");
m_status = SERVER_NEED_ANY;
}
else
{
sprintf(line, "500 PASS command required now\r\n");
}
}
else if( m_status == SERVER_NEED_RNTO )
{
m_status = SERVER_NEED_ANY;
if( memicmp(command, "RNTO", 4) == 0 )
{
for(int i=4; ' ' == command[i]; i++)NULL; //skip white space
char unixFullPath[MAX_PATH], dosOldPath[MAX_PATH], dosNewPath[MAX_PATH];
if( GetFullUnixPath(command+i, m_szUnixWorkDir, unixFullPath)
&& UnixPathToDosPath( unixFullPath, dosNewPath)
&& UnixPathToDosPath( m_szUnixRnfrName, dosOldPath )
&& MoveFile(dosOldPath, dosNewPath) )
{
sprintf(line, "250 ( %s )->( %s )ok\r\n", m_szUnixRnfrName, unixFullPath);
}
else
sprintf(line, "500 ( %s ) cannot be created\r\n", command+i);
}
else
sprintf(line, "500 RNTO command needed\r\n");
}
//if program is quiting
if( *m_pbShouldExit )
return FALSE;
//if command not supported
if( bCommandNotSupport )
{
sprintf(line, "500 command not supported: %s\r\n", command);
}
//send reply line if it not send
if( !bReplyHasSend )
{
cprintf("%s", line);
if( !BlockingSendToSocket(m_sockCtrl, line, strlen(line), m_pbShouldExit, szError) )
{
debug_printf("CFtpServer::OnCommand(USER): %s\n", szError);
return FALSE;
}
}
//return FALSE when it's time to quit
if( bShouldExit )
return FALSE;
else
return TRUE;
}
void CFtpServer::Run()
{
char lineBuffer[FTP_MAX_LINE_BUFFER], line[FTP_MAX_LINE_BUFFER], szError[MAX_SOCKET_ERROR_STRING];
//first send greeting sentence like "220 flyboy ftp server started\r\n"
strcpy(lineBuffer, "220-it's a dangerous program!!!\r\n220 welcome to visit flyboy ftp server(Version: alpha 0.1)\r\n");
if( !BlockingSendToSocket(m_sockCtrl, lineBuffer, strlen(lineBuffer), m_pbShouldExit, szError) )
{
debug_printf("CFtpServer::Run() %s\n", szError);
return;
}
//loop to process each command
fd_set fds;
timeval timeout;
timeout.tv_sec = 1; //wait at most one second
timeout.tv_usec = 0;
while( !*m_pbShouldExit )
{
FD_ZERO(&fds);
FD_SET(m_sockCtrl, &fds);
int nReady = select(m_sockCtrl+1, &fds, NULL, NULL, &timeout);
if( nReady == SOCKET_ERROR )
{
debug_printf("CFtpServer::Run(): select %d\n", WSAGetLastError() );
goto RETURN_POINT;
}
if( nReady == 0 )
continue;
int nRead = recv(m_sockCtrl, lineBuffer, sizeof(lineBuffer), 0);
if( nRead <= 0 )
{
debug_printf("CFtpServer::Run(): recv %d\n", WSAGetLastError() );
goto RETURN_POINT;
}
if( m_lineMaker.PutData(lineBuffer, nRead) )
{
int writeLen = 0;
while( !*m_pbShouldExit && m_lineMaker.GetLine(line, sizeof(line), &writeLen) )
{
line[writeLen-3] = 0; //get rid of CRLF
if( !OnCommand(line) )
goto RETURN_POINT;
}
if( writeLen >= sizeof(line) )
{
debug_printf("CFtpServer::Run(): command line is too long(>%d)\n", sizeof(line) );
goto RETURN_POINT;
}
}
else
{
debug_printf("CFtpServer::Run(): collectLine buffer is too small\n");
goto RETURN_POINT;
}
}
RETURN_POINT:
m_block.bAbort = TRUE;
while( !m_block.bThreadExited )Sleep(100);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -