#pragma ident "@(#) ftplib.cc 1.0.8 2012.12.10,14:57"
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/un.h>
#include <arpa/tftp.h>
#include <sys/select.h>
#include <sys/ioctl.h>
#include <errno.h>

#include "ftx.h"

#define SOCKET_ERROR	(-1)

#define PROG_NAME "ftplib"

#define handle_error(msg) \
	do { perror(msg); exit(EXIT_FAILURE); } while (0)

#define DEFAULT_PROTOCOL 0		// No protocol specified, use default
#define NO_FLAGS 0				// No special flags specified
#define QUEUE_SIZE 1			// Size of connection queue for listen()
#define LINEFEED 0x0A			// Line-feed character
#define MULTILINE_REPLY '-'		// FTP flag for multiline replies
//#define EOL_MARKER "\r\n"		// FTP end-of-line marker
#define EOL_MARKER "\n"			// FTP end-of-line marker

static char gsServerReplyText[MAX_TXT_BUFF];		// FTP server reply buffer
static char gsServerReplyTextString[MAX_TXT_BUFF];	// FTP server reply buffer
static char messagebuff[MAX_DATA_BUFF];	// Buffer used to error meessage
//static char *lpszFunctionName;			// Pointer to function names
static char lpszFunctionName[MAX_DATA_BUFF];			// Pointer to function names
static char gsReplyBuffer[MAX_TXT_BUFF];// Buffer for peeking at FTP server replies
static char gsDataBuffer[MAX_DATA_BUFF];// Storage buffer for data channel

u_int frmSockFTP::GetReplyCode(char * lpszServerReply)
{
	u_int nCode;		// Reply code as a number
	char c;				// Temporary storage

	sprintf(lpszFunctionName ,"%s", "GetReplyCode");

	c = *(lpszServerReply+3);			// Save the character
	*(lpszServerReply+3) = '\0';		// Terminate the code

	nCode = atoi((const char *)lpszServerReply);	// Convert code to number
	*(lpszServerReply+3) = c;						// Restore the character

	return(nCode);	// Return the reply code
}

BOOL frmSockFTP::IsReadyToRead(int hSocket)
{
	fd_set setReadyToRead;		// Socket set to test ready-to-read status
	struct timeval timeTimeOut;	// Amount of time to wait for status change
	int nReady;					// Ready-to-read flag
	
	try {
			sprintf(lpszFunctionName ,"%s", "IsReadyToRead");

			timerclear(&timeTimeOut);
			FD_ZERO(&setReadyToRead);
			FD_SET(hSocket, &setReadyToRead);
			if ((nReady = select(hSocket, (fd_set *)&setReadyToRead, NULL, NULL, (struct timeval *)&timeTimeOut)) == SOCKET_ERROR)
			{
				ftxError message("error");
				throw message;
				perror("select");
				sprintf(messagebuff, "errno %d: %s:error of select()", errno,lpszFunctionName);   
				errormsg(0,0,messagebuff);
				return(FALSE);
			}
		} catch(ftxError& ftxErrorExpection) {
			MsgBox("select()関数のエラー");
	}
		
	return(nReady ? TRUE : FALSE);
}

u_int  frmSockFTP::ReadReplyLine(char *lpszReplyBuffer)
{
	char * lpEOL;						// End-of-line
	u_int nLimitReplyBytes;				// Length of first reply in the buffer
	char pLastLineCode[MAX_TXT_BUFF];		// Storage buffer for reply code
	char *lpLastLine;					// Pointer to the last line
	int i;								// General purpose index

 	sprintf(lpszFunctionName ,"%s", "ReadReplyLine");
	sprintf(pLastLineCode,"%s","123?");		// Storage buffer for reply code

	nLimitReplyBytes = 0;
	
	if (*(lpszReplyBuffer+3) == MULTILINE_REPLY)		
	{
		// Get the code from the reply buffer
		for (i = 0; i <3; i++ )
			*(pLastLineCode+i) = *(lpszReplyBuffer+i);
   
		// Use a trailing space to look for the last line
		*(pLastLineCode+i) = ' ';
			
		// Search the buffer for the last line
		if ((lpLastLine = (char *)strstr(lpszReplyBuffer, pLastLineCode)))
		{
			// Okay, be cautious and make sure a CRLF exists
			lpEOL = (char *)strstr(lpLastLine, EOL_MARKER);
			// Note length to read if more than one reply is in the buffer
			nLimitReplyBytes = lpEOL ? (u_int)((lpEOL - lpszReplyBuffer)+2) : 0;
		}
		else
			nLimitReplyBytes = 0;
	}
	else
	{
		// If the reply is not multiline then find the end of the line.
		lpEOL = (char *)strstr(lpszReplyBuffer, EOL_MARKER);

		// If an end-of-line marker was not found, read everything
		// (i.e. don't limit the reply size). Otherwise, only read to the 
		// end of line marker.
		nLimitReplyBytes = lpEOL ? (u_int)((lpEOL - lpszReplyBuffer)+2) : 0;
	}
	return(nLimitReplyBytes);
}


char * frmSockFTP::GetFTPServerReplyText(void)
{
	//完全な文字列で返すようにした。2009.06.06
	return((char *)gsServerReplyTextString);	// Return full text of server's reply
}

BOOL frmSockFTP::CheckReceivable(int hControlSocket)
{
   fd_set fdset;
   int ret;
   struct timeval timeout;

   FD_ZERO( &fdset );
   FD_SET(hControlSocket , &fdset );

   /* timeoutは0秒。*/
   timeout.tv_sec = 0;
   timeout.tv_usec = 0;

   /* read */
   ret = select(hControlSocket+1 ,&fdset, NULL, NULL, &timeout);

   return (ret == 1) ? TRUE : FALSE;

}

u_int   frmSockFTP::ReadFTPServerReply(int hControlChannel)
{
	int iBytesRead;				// Bytes read from the control channel
	int iBufferLength;			// Length of the server reply buffer
	int iEnd;					// Index into the server reply buffer
	int iSpaceRemaining;		// Space remaining in the buffer
	int iReplySize;				// Length of first reply in the buffer
	
 	sprintf(lpszFunctionName ,"%s", "ReadFTPServerReply");

	// Be cautious and zero fill the buffer
	memset(gsReplyBuffer, '\0', sizeof(gsReplyBuffer));
	
	// Be tricky and peek ahead to see what's in the buffer.
	if ((iBytesRead = recv(hControlChannel, 
				(char *)(gsReplyBuffer), sizeof(gsReplyBuffer), MSG_PEEK)) > 0)
	{
		if ((iReplySize = ReadReplyLine(gsReplyBuffer)) == 0)
			iBufferLength = iSpaceRemaining = sizeof(gsServerReplyText);
		else 
			iBufferLength = iSpaceRemaining = iReplySize;
	}
	else
	{
		switch(errno)
		{
		case EPIPE:
			break;
		}
		sprintf(messagebuff, "Error %d: %s:error of control channel", errno,lpszFunctionName);   
		errormsg(0,0,messagebuff);
		return(999);
	}

	iEnd = 0;	// Start with zero bytes.
	do
	{
		iSpaceRemaining -= iEnd;
		iBytesRead = recv(hControlChannel, (char *)(gsServerReplyText+iEnd), iSpaceRemaining, NO_FLAGS);
		if(iBytesRead == -1)
		{
			return(0);
		}
				
   		iEnd+=iBytesRead;
			
   		// Make sure CRLF was not the the last byte pair received. 
   		// Otherwise, recv() will wait forever for the next packet.
		if (*(gsServerReplyText+(iEnd-1)) == LINEFEED)
   		{
			char * lpLineFeed;
			char * lpLastLine;
							                                                    
			// Temporarily replace the real last line marker (LF)
			// with a NULL so _fstrstr doesn't go crazy.
			*(gsServerReplyText+(iEnd-1)) = '\0';
					
			// See if any other line-feeds exist in the buffer 
			// (which means the buffer contains multiple lines).
			lpLineFeed = strrchr(gsServerReplyText, LINEFEED);
					
	        // Restore the line-feed character.
			*(gsServerReplyText+(iEnd-1)) = LINEFEED;
							
			if (lpLineFeed)
				// If a line-feed was found then the next character is 
				// the start of the last line.
				lpLastLine = lpLineFeed+1;

			else
				// Otherwise, the buffer contains only have one line
				lpLastLine = gsServerReplyText;

			// Be cautious and make sure the last line includes a reply code
			if (GetReplyCode(lpLastLine))
			{ 
				// Test the reply code to see if it indicates more lines
   				if (*(lpLastLine+3) != MULTILINE_REPLY)
   					break;	// If not, break out of the loop.
			}
			else
			{
			;	// Whoops, somebody's server is not playing by the rules.
			}
		}
	}
	while (iBytesRead > 0 && iEnd < iBufferLength); 
	
	if (iBytesRead == SOCKET_ERROR)
  	{
		switch(errno)
		{
		case EPIPE:
			break;
		}
		sprintf(messagebuff, "errno %d: %s: error of recv()", errno,lpszFunctionName);   
		errormsg(0,0,messagebuff);
	// Return 999 to indicate an error has occurred
		return(999);
	} 
	gsServerReplyText[iEnd] = '\0';
	sprintf(messagebuff,"%s",Left(gsServerReplyText,iEnd-2));
	// Extract the reply code from the server reply and return as an integer
	sprintf(gsServerReplyText,"%s",messagebuff);
	sprintf(messagebuff,"%s",strCutCrLf(gsReplyBuffer));
	sprintf(gsServerReplyTextString,"%s",messagebuff);
	return(GetReplyCode(gsServerReplyText));	            
}

u_int frmSockFTP::SendFTPCommand(int hControlChannel, const std::string gszCommandBuffer)
{
	try {
			sprintf(lpszFunctionName ,"%s", "SendFTPCommand");
			char  s2[128];

			if ((send(hControlChannel, (void *)gszCommandBuffer.c_str(),(size_t)strlen(gszCommandBuffer.c_str()), NO_FLAGS)) == SOCKET_ERROR)
			{
				switch(errno)
				{
				case EPIPE:
					break;
				}
				ftxError message("send error");
				throw message;
				perror("send");
				sprintf(messagebuff, "errno %d: %s:error of send()", errno,lpszFunctionName);   
				errormsg(0,0,messagebuff);
			// Return 999 to indicate an error has occurred
				return(999);
			}
		} catch(ftxError& ftxErrorExpection) {
			MsgBox(ftxErrorExpection.Msg);
	}
	// Read the server's reply and return the reply code as an integer
	return(ReadFTPServerReply(hControlChannel));	            
}

BOOL frmSockFTP::ReadDataChannel(int hControlSocket, int hDataSocket, char * lpszFileName)
{
	int nBytesRecv;				// Bytes received from the data channel
	int hFile;				// File handle for data file
	long lData = 0L;			// Bytes received and written to the data file
	char *nl;

	sprintf(lpszFunctionName ,"%s", "ReadDataChannel");

	if ((hFile = open(lpszFileName, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) == -1)
	{
		close(hFile);
		sprintf(messagebuff, "h_errno %d:open() %s:<%s> error of open() - LOCAL",h_errno,lpszFunctionName,lpszFileName);   
		errormsg(0,0,messagebuff);

		return(FALSE);
	}
		
	
	do	// Ready read and write
	{
		nBytesRecv = recv(hDataSocket, (char *)&gsDataBuffer, sizeof(gsDataBuffer), NO_FLAGS);
						
		lData += nBytesRecv;
		if (nBytesRecv > 0 )
		{
			if (-1 == write (hFile, gsDataBuffer, nBytesRecv))
			{
				sprintf(messagebuff, "errno %d: %s:<%s> error of write()", errno,lpszFunctionName,lpszFileName);   
				errormsg(0,0,messagebuff);
			}
		}
	}
	while (nBytesRecv > 0);
							
	// Close the file and check for error returns.
	close(hFile);

	if (nBytesRecv == SOCKET_ERROR)
	{ 
		sprintf(messagebuff, "errno %d: %s:<%s> error of recv()", errno,lpszFunctionName,lpszFileName);   
		errormsg(0,0,messagebuff);
		return(FALSE);
	}
	else if (lData == 0)
	{
		sprintf(messagebuff, "errno %d: %s:error of data channel", errno,lpszFunctionName);   
		errormsg(0,0,messagebuff);
		return(FALSE);
	}

	if(CheckReceivable(hControlSocket) == FALSE)
	{
		return(222);
	}
		
	// Read the control channel to see what the server thought about it.
	return(ReadFTPServerReply(hControlSocket));
}

ssize_t frmSockFTP::TransferFile(int hControlSocket, int hDataSocket, int hFile)
{
	char szFileData[1024];	 	// Buffer to hold file data
	ssize_t nCharRecv;				// Number of characters received
	char szMsg[100];			// General purpose buffer for messages

	sprintf(lpszFunctionName ,"%s", "TransferFile");
	nCharRecv = recv((int)hDataSocket, (void *)&szFileData, (int)sizeof(szFileData), NO_FLAGS);

	if (nCharRecv > 0 )
	{
		if (-1 == write (hFile, szFileData, nCharRecv))
		{
			close(hFile);
			perror("write");
			sprintf(szMsg,"%ld write()Error： error of write() - LOCAL", nCharRecv);
			errormsg(0,0,szMsg);
			return(-1);
		}
	}
	else if (nCharRecv == SOCKET_ERROR)
	{
		switch(errno)
		{
		case EPIPE:
			break;
		}
		close(hFile);
		sprintf(messagebuff, "errno %d: %s: error of recv()", errno,lpszFunctionName);   
		errormsg(0,0,messagebuff);
		return(SOCKET_ERROR);
	}

	if (nCharRecv == 0)
   	{
		if(CheckReceivable(hControlSocket) == FALSE)
		{
			return(nCharRecv);
		}
   	}
	return(nCharRecv);
}

int frmSockFTP::ftpwrite(int hDataSocket,char * buff,int bcount)
{
	int dest,num;

	dest = bcount;
	num = send(hDataSocket,(void *)buff,(size_t)((dest>1024)?1024:dest),0);

	if(num == -1)
	{
		switch(errno)
		{
		case EPIPE:
			break;
		}
		sprintf(messagebuff, "errno %d: %s: erroro of send()", errno,lpszFunctionName);   
		errormsg(0,0,messagebuff);
		return(INVALID_SOCKET);
	}
	return(num);
}

// send a file through the data socket
//int SendMass(int sockfd,char * filename,BOOL binaryflag)

int frmSockFTP::TransferFile3(int hControlSocket, int hDataSocket, int hFile)
{
	int iNumBytes;
	int  iRetCode;
	int  iFileHandle;
	long lBytesWritten = 0L;
	char szMsgBuf[MAX_DATA_BUFF];
	char szString[MAX_TXT_BUFF];

	iRetCode=0;

	memset(szMsgBuf,0,sizeof(szMsgBuf));
	memset(szString,0,sizeof(szString));

	// get the start time
	// loop to send output to remote end
	iNumBytes=read(hFile,szMsgBuf,512);
	iRetCode = ftpwrite(hDataSocket,szMsgBuf,iNumBytes);

	if (iNumBytes == SOCKET_ERROR)
	{
		switch(errno)
		{
		case EPIPE:
			break;
		}
		close(hFile);
		sprintf(messagebuff, "errno %d: %s: error of read() ", errno,lpszFunctionName);   
		errormsg(0,0,messagebuff);
		return(SOCKET_ERROR);
	}
	if (iRetCode == INVALID_SOCKET)
	{
		close(hFile);
		return (iRetCode);
	}
	if(iNumBytes == 0)
	{
		close(hFile);
		return (iNumBytes);
	}
	else
	{
		return(iNumBytes);
	}
}


void frmSockFTP::ExtractFileName(char * lpPathString, char * lpszFileName)
{
	char * lp;					// General purpose pointer
	int i;					// General purpose index
	int iExtLength = 0;		// Length of file extension (following the dash)

	// Find the last forward slash (assume UNIX/NT directory conventions)		
	if (lp = strrchr(lpPathString, '/'))
		lp++;
	else
		lp = lpPathString;
		
	// Loop while the length of the name is less than 8 characters 
	// (a valid DOS length), the character is not a dot and the 
	// pointer is valid
	for (i = 0; i < 8 && *lp != '.' && lp; i++)
		*(lpszFileName+i) = *(lp++);
			    
	// Add a dot to mark the start of the file extension
	*(lpszFileName+i) = '.';
	i++;
			
	// Find the last dot and use up to the next three characters for
	// the new file name.
	if (lp = strrchr(lpPathString, '.'))
		for (iExtLength = 0; iExtLength < 3 && (*(lp)); iExtLength++)
				*(lpszFileName+(i++)) = *(++lp);
					
	// Null-terminate the new file name
	*(lpszFileName+i) = '\0';

	return;
}

int frmSockFTP::CreateTransferFile(const std::string lpszFileName)
{
	int hFile;							// File handle for data file
	sprintf(lpszFunctionName ,"%s", "CreateTransferFile");
	
	if ((hFile = open(lpszFileName.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1)
	{
		close(hFile);
		sprintf(messagebuff, "errno %d: %s:<%s>を作成出来ません",errno,lpszFunctionName,lpszFileName.c_str());   
		//errormsg(0,0,messagebuff);
	}
	return(hFile);
}

int frmSockFTP::CreateTransferFile2(const std::string lpszFileName)
{
	int hFile;							// File handle for data file
	sprintf(lpszFunctionName ,"%s", "CreateSendTransferFile2");

	
	if ((hFile = open(lpszFileName.c_str(), O_RDONLY)) == -1)
	{
		close(hFile);
		sprintf(messagebuff, "h_errno %d:open() %s:<%s> error of open()",h_errno,lpszFunctionName,txtEditFile);   
		errormsg(0,0,messagebuff);
	}

	return(hFile);
}

int frmSockFTP::CreateTransferFile3(char *lpszFileName, char *strEditFileName)
{
	int hFile;							// File handle for data file
	sprintf(lpszFunctionName ,"%s", "CreateSendTransferFile3");

	if ((hFile = open(strEditFileName, O_RDONLY)) == -1)
	{
		close(hFile);
		sprintf(messagebuff, "h_errno %d:open() %s:<%s> error of open()",h_errno,lpszFunctionName,txtEditFile);   
		errormsg(0,0,messagebuff);
	}
	return(hFile);
}


SOCKET frmSockFTP::ConnectFTPControlSocket(char * lpszHost)
{
	struct hostent *lpHostEnt;	// Internet host information structure
	struct sockaddr_in sockaddr;	// Socket address structure
	struct servent *lpServEnt;	// Service information structure
	int nProtocolPort;	// Protocol port
	int nConnect;			// Socket connection results

	struct in_addr *inp;
	struct in_addr in;

	int hControlSocket = INVALID_SOCKET;	
	
	sprintf(lpszFunctionName ,"%s", "ConnectFTPControlSocket");


	in.s_addr = inet_addr(lpszHost);
	lpHostEnt = (struct hostent *)gethostbyname(lpszHost);
	if(!lpHostEnt)
	{
	//2010.03.10
	//	sprintf(messagebuff, "Error:%d:%s:<Host=%s> gethostbyaddr()",h_errno,lpszFunctionName,lpszHost);   
	//	errormsg(0,0,messagebuff);
		lpHostEnt = (struct hostent *)gethostbyaddr((char *)&in.s_addr, sizeof(in.s_addr),AF_INET);
	}
	else
	{
		goto skip;
	}

	if(!lpHostEnt)
	{
		sprintf(messagebuff, "Error:%d:%s:<Host=%s> gethostbyname()",h_errno,lpszFunctionName,lpszHost);   
		errormsg(0,0,messagebuff);
		return(INVALID_SOCKET);
	}

skip:

	if ((hControlSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
	{
		sprintf(messagebuff, "h_errno %d: %s:error of socket()",h_errno,lpszFunctionName);   
		errormsg(0,0,messagebuff);
		return(INVALID_SOCKET);
	}
					
	lpServEnt = (struct servent *)getservbyname("ftp", DEFAULT_PROTOCOL);
					
	if (lpHostEnt == NULL)
	{
		nProtocolPort = htons(IPPORT_FTP);	
	}
	else
	{
		nProtocolPort = lpServEnt->s_port;
	}

	// Define the socket address	
	memset(&sockaddr,0,sizeof(sockaddr));
	sockaddr.sin_family = AF_INET;
	sockaddr.sin_port = nProtocolPort;
	sockaddr.sin_addr.s_addr = *((u_int *)*lpHostEnt->h_addr_list);


	// Connect the socket
	if( nConnect = connect((int)hControlSocket, (struct sockaddr *)&sockaddr, (socklen_t)sizeof(sockaddr)))
		{
			sprintf(messagebuff, "h_errno %d: %s:erroro of connect()",h_errno,lpszFunctionName);   
			errormsg(0,0,messagebuff);
			return(INVALID_SOCKET);
		}

	// Make the control socket non-blocking before returning.
	IsReadyToRead(hControlSocket);

	if (ReadFTPServerReply(hControlSocket) >= 400)
		return(INVALID_SOCKET);
	else
		return(hControlSocket);
}

SOCKET  frmSockFTP::RequestDataConnection(int hControlSocket, int hListenSocket)
{
	struct sockaddr_in sockaddr;			// Socket address structure
	socklen_t iLength;					// Length of the address structure
	int nLocalPort;				// Local port for listening
	u_int nReplyCode;				// FTP server reply code

	struct hostent *lpHostEnt;	// Internet host information structure

	sprintf(lpszFunctionName ,"%s", "RequestDataConnection");

	// Get the address for the hListenSocket
	iLength = sizeof(sockaddr);
	if (getsockname(hListenSocket, (struct sockaddr *)&sockaddr, &iLength) == -1)
	{
		sprintf(messagebuff, "errno %d: %s: #%d: error of getsockname()",errno,lpszFunctionName,nReplyCode);   
		errormsg(0,0,messagebuff);
		return(INVALID_SOCKET);
	}

	// Extract the local port from the hListenSocket
	nLocalPort = sockaddr.sin_port;
							
	// Now, reuse the socket address structure to 
	// get the IP address from the control socket.
	if (getsockname(hControlSocket, (struct sockaddr *)&sockaddr, 
			&iLength) == SOCKET_ERROR)
	{
		sprintf(messagebuff, "errno %d: %s: #%d: error of getsockname()",errno,lpszFunctionName,nReplyCode);   
		errormsg(0,0,messagebuff);
		return(INVALID_SOCKET);
	}
	if((!strcmp(txtHostName,"localhost")) || (!strcmp(txtHostName,"127.0.0.1")))
	{
		sprintf(gszCommandBuffer,"PORT 127,0,0,1,%d,%d\n",
			nLocalPort & 0xFF,	
			nLocalPort >> 8 & 0xff);
		subShowServerCommand ("in localhost");
		subShowServerCommand (gszCommandBuffer);
	}
	else
	{
		sprintf(gszCommandBuffer, "PORT %d,%d,%d,%d,%d,%d\n",
			sockaddr.sin_addr.s_addr & 0xff,
			sockaddr.sin_addr.s_addr >> 8 & 0xff,
			sockaddr.sin_addr.s_addr >> 16 & 0xff,
			sockaddr.sin_addr.s_addr >> 24 & 0xff,
			nLocalPort & 0xFF,	
			nLocalPort >> 8 & 0xff);
		subShowServerCommand (gszCommandBuffer);
	}

	// Tell the server which port to use for data.
	nReplyCode = SendFTPCommand(hControlSocket, gszCommandBuffer);
	if (nReplyCode >= 0 && nReplyCode <= 259)
	{
		subGetServerReplyText();
		return(hListenSocket);
	}
	else
	{
		sprintf(messagebuff,"%d",nReplyCode);

		sprintf(messagebuff, "errno %d: %s: #%d: error of SendFTPCommand()",errno,lpszFunctionName,nReplyCode);   
		errormsg(0,0,messagebuff);
		return(INVALID_SOCKET);
	}
}

SOCKET frmSockFTP::CreateListenSocket(int hControlSocket)
{
	struct sockaddr_in sockaddr;		// Socket address structure
	int hListenSocket;					// Handle for the listener socket
	
	sprintf(lpszFunctionName ,"%s", "CreateListenSocket");

	if ((hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
	{
		perror("socket");
		sprintf(messagebuff, "errno %d: %s: error of socket()",errno,lpszFunctionName);   
		errormsg(0,0,messagebuff);
		return(INVALID_SOCKET);
	}
	// Let the system assign a socket address	
	memset(&sockaddr,0,sizeof(sockaddr));
	sockaddr.sin_family = AF_INET;		
	sockaddr.sin_port = htons(0);		// htons() is just a reminder.
	sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
					
	// Bind the socket
	if (bind((int)hListenSocket, (struct sockaddr *)&sockaddr, (socklen_t)sizeof(sockaddr)) == -1)
	{
		perror("bind");
		sprintf(messagebuff, "errno %d: %s: error of bind()",errno,lpszFunctionName);   
		errormsg(0,0,messagebuff);
		return(INVALID_SOCKET);
	}

	// Listen for the FTP server connection
	if (listen(hListenSocket, QUEUE_SIZE) == -1)	
	{
		perror("listen");
		sprintf(messagebuff, "errno %d: %s: error of listen()",errno,lpszFunctionName);   
		errormsg(0,0,messagebuff);
		return(INVALID_SOCKET);
	}
	
	// Ask the server to connect to the port monitored by the listener socket
	return(RequestDataConnection(hControlSocket, hListenSocket));
}
//create data socket
SOCKET frmSockFTP::AcceptDataConnection(int hListenSocket)
{
	int hDataSocket;				// Handle for socket that receives data
	struct sockaddr *sockaddr;			// Socket address structure
	socklen_t iAddrLength = 16;			// The length of the socket address
	int ret;

	sprintf(lpszFunctionName ,"%s", "AcceptDataConnection");

	try {
			hDataSocket = accept((int)hListenSocket, (struct sockaddr *)&sockaddr, (socklen_t *)&iAddrLength); 
			if(hDataSocket == INVALID_SOCKET)
			{
				ftxError message("accept() error");
				throw message;
				perror("accept");
				sprintf(messagebuff, "errno %d: %s: error of accept()",errno,lpszFunctionName);   
				errormsg(0,0,messagebuff);
				return(INVALID_SOCKET);
			}
			else
			{
				// Make the data channel non-blocking before returning
				IsReadyToRead(hDataSocket);
				// Close the listener socket since it is no longer needed
				return(hDataSocket);
			}
		} catch(ftxError& ftxErrorExpection) {
			MsgBox(ftxErrorExpection.Msg);
	}
}

SOCKET frmSockFTP::CreateDataSocketPASV(char * lpszHost, char *port)
{
	struct hostent *lpHostEnt;	// Internet host information structure
	struct sockaddr_in sockaddr;	// Socket address structure
	struct servent *lpServEnt;	// Service information structure
	int nProtocolPort;	// Protocol port
	int nConnect;			// Socket connection results

	struct in_addr *inp;
	struct in_addr in;

	int hDataSocket = INVALID_SOCKET;	
	
	sprintf(lpszFunctionName ,"%s", "CreateDataSocket");


	in.s_addr = inet_addr(lpszHost);
	lpHostEnt = (struct hostent *)gethostbyname(lpszHost);
	if(!lpHostEnt)
	{
		lpHostEnt = (struct hostent *)gethostbyaddr((char *)&in.s_addr, sizeof(in.s_addr),AF_INET);
	}
	else
	{
		goto skip;
	}

	if(!lpHostEnt)
	{
		sprintf(messagebuff, "Error:%d:%s:<Host=%s> error of gethostbyname()",h_errno,lpszFunctionName,lpszHost);   
		errormsg(0,0,messagebuff);
		return(INVALID_SOCKET);
	}

skip:

	if ((hDataSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
	{
		sprintf(messagebuff, "h_errno %d: %s:error of socket()",h_errno,lpszFunctionName);   
		errormsg(0,0,messagebuff);
		return(INVALID_SOCKET);
	}
					
	lpServEnt = (struct servent *)getservbyname("ftp", DEFAULT_PROTOCOL);
					
	if (lpHostEnt == NULL)
	{
		nProtocolPort = htons(IPPORT_FTP);	
	}
	else
	{
		nProtocolPort = htons(atoi(port));
	}

	// Define the socket address	
	memset(&sockaddr,0,sizeof(sockaddr));
	sockaddr.sin_family = AF_INET;
	sockaddr.sin_port = nProtocolPort;
	sockaddr.sin_addr.s_addr = *((u_int *)*lpHostEnt->h_addr_list);


	// Connect the socket
	if( nConnect = connect((int)hDataSocket, (struct sockaddr *)&sockaddr, (socklen_t)sizeof(sockaddr)))
	{
		sprintf(messagebuff, "h_errno %d: %s:error of connect()",h_errno,lpszFunctionName);   
		errormsg(0,0,messagebuff);
		return(INVALID_SOCKET);
	}
	return(hDataSocket);
}

