#include <time.h>
#include <winsock.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
//////////////////////////////////////////////////////////////////////////
#define WSVERS MAKEWORD(2, 0)
#define WSA_RECV 0
#define WSA_SEND 1
#define DATA_BUFSIZE 1024
#define FTP_PORT 21
#define FTP_USER "toldo"
#define FTP_PASS "toldo"
#define DEFAULT_HOME_DIR "C:\\TEMP"
#define MAX_NAME_LEN 128
#define MAX_PWD_LEN 128
#define MAX_RESP_LEN 1024
#define MAX_REQ_LEN 256
#define MAX_ADDR_LEN 80
#define FTP_PORT 21 // FTP 控制端口
#define DATA_FTP_PORT 20 // FTP 数据端口
#define USER_OK 331
#define LOGGED_IN 230
#define LOGIN_FAILED 530
#define CMD_OK 200
#define OPENING_AMODE 150
#define TRANS_COMPLETE 226
#define CANNOT_FIND 550
#define FTP_QUIT 221
#define CURR_DIR 257
#define DIR_CHANGED 250
#define OS_TYPE 215
#define REPLY_MARKER 504
#define PASSIVE_MODE 227
#define MAX_FILE_NUM 1024
#define MODE_PORT 0
#define MODE_PASV 1
#define PORT_BIND 1821
typedef struct {
TCHAR szFileName[MAX_PATH];
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
} FILE_INF, *LPFILE_INF;
//////////////////////////////////////////////////////////////////////////
SOCKET passiveUDP(const char *);
void errexit(const char *, ...);
SOCKET
passivesock(const int port, const char *transport, int qlen);
int DealCommand( );
int GetFileList( LPFILE_INF pFI, UINT nArraySize, const char* szPath );
char* GetLocalAddress();
char* HostToNet( char* szPath ) ;
char* NetToHost( char* szPath ) ;
char* RelativeDirectory( char* szDir );
char* AbsoluteDirectory( char* szDir );
int DataSend( SOCKET s, char* buff,int nBufSize );
int LoginIn();
DWORD ReadFileToBuffer( const char* szFile, char *buff, DWORD nFileSize );
int DataRecv( SOCKET s, const char* szFileName );
DWORD WriteToFile( SOCKET s , const char* szFile );
// BOOL WelcomeInfo( SOCKET s );
//////////////////////////////////////////////////////////////////////////
#pragma comment(lib,"ws2_32.lib")
u_short portbase = 0; /* port base, for test servers */
CHAR buffRecv[DATA_BUFSIZE];
CHAR buffSend[DATA_BUFSIZE];
BOOL g_beLogin = FALSE;
struct sockaddr_in fsin;
SOCKET sock; //command socket
int
main(int argc, char *argv[])
{
int alen; /* from-address length */
WSADATA wsadata;
if (WSAStartup(WSVERS, &wsadata))
errexit("WSAStartup failed\n");
sock = passivesock(FTP_PORT,"udp",0);
printf("FTPServer is Started\n");
while (1)
{
alen = sizeof(fsin);
memset(buffRecv,0x0,DATA_BUFSIZE);
if (recvfrom(sock, buffRecv, sizeof(buffRecv), 0,
(struct sockaddr *)&fsin, &alen) == SOCKET_ERROR)
errexit("recvfrom: error %d\n", GetLastError());
//解析命令
DealCommand();
}
return 1; /* not reached */
}
int LoginIn()
{
const char* szUserOK = "331 User name okay, need password.\r\n";
const char* szLoggedIn = "230 User logged in, proceed.\r\n";
int nRetVal = 0;
static char szUser[MAX_NAME_LEN], szPwd[MAX_PWD_LEN];
// 取得登录用户名
if( strstr(strupr(buffRecv),"USER") )
{
sprintf(szUser,"%s",buffRecv+strlen("USER")+1);
strtok( szUser,"\r\n");
// 响应信息
sprintf(buffSend,"%s",szUserOK );
if( sendto(sock,szUserOK,strlen(szUserOK),0,(struct sockaddr *)&fsin,sizeof(fsin)) == -1 ) return -1;
return USER_OK;
}
if( strstr(strupr(buffRecv),"PASS") || strstr(buffRecv,"pass") )
{
sprintf(szPwd,"%s",buffRecv+strlen("PASS")+1 );
strtok( szPwd,"\r\n");
// 判断用户名跟口令正确性
if( stricmp( szUser,FTP_USER) || stricmp(szPwd,FTP_PASS) )
{
sprintf(buffSend,"530 User %s cannot log in.\r\n",szUser );
printf("User %s cannot log in\n",szUser );
nRetVal = LOGIN_FAILED;
}
else
{
sprintf(buffSend,"%s",szLoggedIn);
printf("User %s logged in\n",szUser );
nRetVal = LOGGED_IN;
}
if( sendto(sock,buffSend,strlen(buffSend),0,(struct sockaddr *)&fsin,sizeof(fsin)) == -1 ) return -1;
}
return nRetVal;
}
int ConvertDotAddress( char* szAddress, LPDWORD pdwIpAddr, LPWORD pwPort )
{
int idx = 0,i = 0, iCount = 0;
char szIpAddr[MAX_ADDR_LEN]; memset( szIpAddr,0,sizeof(szIpAddr) );
char szPort[MAX_ADDR_LEN]; memset( szPort,0, sizeof(szPort) );
*pdwIpAddr = 0; *pwPort = 0;
while( szAddress[idx] )
{
if( szAddress[idx] == ',' )
{
iCount ++;
szAddress[idx] ='.';
}
if( iCount < 4 )
szIpAddr[idx] = szAddress[idx];
else
szPort[i++] = szAddress[idx];
idx++;
}
if( iCount != 5 ) return -1;
*pdwIpAddr = inet_addr( szIpAddr );
if( *pdwIpAddr == INADDR_NONE ) return -1;
char *pToken = strtok( szPort+1,"." );
if( pToken == NULL ) return -1;
*pwPort = (WORD)(atoi(pToken));
// pToken = strtok(NULL,".");
// if( pToken == NULL ) return -1;
// *pwPort += (WORD)atoi(pToken);
return 0;
}
UINT FileListToString( char* buff, UINT nBuffSize,BOOL bDetails )
{
FILE_INF fi[MAX_FILE_NUM];
int nFiles = GetFileList( fi, MAX_FILE_NUM, "*.*" );
char szTemp[128];
sprintf( buff,"%s","" );
if( bDetails ) {
for( int i=0; i<nFiles; i++) {
if( strlen(buff)>nBuffSize-128 ) break;
if(!strcmp(fi[i].szFileName,".")) continue;
if(!strcmp(fi[i].szFileName,"..")) continue;
// 时间
SYSTEMTIME st;
FileTimeToSystemTime(&(fi[i].ftLastWriteTime), &st);
char *szNoon = "AM";
if( st.wHour > 12 )
{
st.wHour -= 12;
szNoon = "PM";
}
if( st.wYear >= 2000 )
st.wYear -= 2000;
else st.wYear -= 1900;
sprintf( szTemp,"%02u-%02u-%02u %02u:%02u%s ",
st.wMonth,st.wDay,st.wYear,st.wHour,st.wMonth,szNoon );
strcat( buff,szTemp );
if( fi[i].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
strcat(buff,"<DIR>");
strcat(buff," ");
}
else
{
strcat(buff," ");
// 文件大小
sprintf( szTemp,"% 9d ",fi[i].nFileSizeLow );
strcat( buff,szTemp );
}
// 文件名
strcat( buff,fi[i].szFileName );
strcat( buff,"\r\n");
}
}
else
{
for( int i=0; i<nFiles; i++)
{
if( strlen(buff) + strlen( fi[i].szFileName ) + 2 < nBuffSize )
{
strcat( buff, fi[i].szFileName );
strcat( buff, "\r\n");
}
else
break;
}
}
return strlen( buff );
}
char* GetLocalAddress()
{
struct in_addr *pinAddr;
LPHOSTENT lpHostEnt;
int nRet;
int nLen;
char szLocalAddr[80];
memset( szLocalAddr,0,sizeof(szLocalAddr) );
// Get our local name
nRet = gethostname(szLocalAddr,sizeof(szLocalAddr) );
if (nRet == SOCKET_ERROR)
{
return NULL;
}
// "Lookup" the local name
lpHostEnt = gethostbyname(szLocalAddr);
if (NULL == lpHostEnt)
{
return NULL;
}
// Format first address in the list
pinAddr = ((LPIN_ADDR)lpHostEnt->h_addr);
nLen = strlen(inet_ntoa(*pinAddr));
if ((DWORD)nLen > sizeof(szLocalAddr))
{
WSASetLastError(WSAEINVAL);
return NULL;
}
return inet_ntoa(*pinAddr);
}
int DataConn( SOCKET& s, DWORD dwIp, WORD wPort, int nMode )
{
// 创建一个socket
s = socket( AF_INET,SOCK_DGRAM,IPPROTO_UDP);
if( s == INVALID_SOCKET )
{
printf("Failed to get a socket %d\n", WSAGetLastError());
return -1;
}
struct sockaddr_in inetAddr;
inetAddr.sin_family = AF_INET;
if( nMode == MODE_PASV )
{
inetAddr.sin_port = htons( wPort );
inetAddr.sin_addr.s_addr = dwIp;
}
else
{
inetAddr.sin_port = htons( DATA_FTP_PORT );
inetAddr.sin_addr.s_addr = inet_addr(GetLocalAddress());
}
BOOL optval = TRUE;
if( setsockopt(s,SOL_SOCKET,SO_REUSEADDR,
(char*)&optval,sizeof(optval) ) == SOCKET_ERROR )
{
printf("Failed to setsockopt %d.\n"