www.pudn.com > vcʵÏÖftp.rar > VIEW_OLD.CPP
// View.cpp : implementation of the CMiniFTPView class
//
#include "stdafx.h"
#include "miniftp.h"
#include "Doc.h"
#include "View.h"
//#include "cwinsock.h" // in this files .h
#include "mainfrm.h"
#include "conndlg.h"
#include "XportDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define WM_WINSOCK_EVENT_FRAME_CONTROL (WM_USER+4) // for winsock messages
#define WM_WINSOCK_EVENT_VU_CONTROL (WM_USER+4+10) // for winsock messages
#define WM_WINSOCK_EVENT_FRAME_LISTEN (WM_USER+6) // for winsock messages
#define WM_WINSOCK_EVENT_VU_LISTEN (WM_USER+6+10) // for winsock messages
#define WM_WINSOCK_EVENT_FRAME_DATA (WM_USER+8) // for winsock messages
#define WM_WINSOCK_EVENT_VU_DATA (WM_USER+8+10) // for winsock messages
/////////////////////////////////////////////////////////////////////////////
// CMiniFTPView
IMPLEMENT_DYNCREATE(CMiniFTPView, CEditView)
BEGIN_MESSAGE_MAP(CMiniFTPView, CEditView)
//{{AFX_MSG_MAP(CMiniFTPView)
ON_COMMAND(ID_CONNECT, OnConnect)
ON_COMMAND(ID_CLOSECONN, OnCloseconn)
ON_COMMAND(ID_CLEARVIEW, OnClearview)
ON_UPDATE_COMMAND_UI(ID_CLOSECONN, OnUpdateCloseconn)
ON_UPDATE_COMMAND_UI(ID_CONNECT, OnUpdateConnect)
ON_WM_TIMER()
ON_COMMAND(ID_FSETTINGS, OnFsettings)
//}}AFX_MSG_MAP
ON_MESSAGE(WM_WINSOCK_EVENT_VU_CONTROL,OnWinsockEventControl)
ON_MESSAGE(WM_WINSOCK_EVENT_VU_LISTEN,OnWinsockEventListen)
ON_MESSAGE(WM_WINSOCK_EVENT_VU_DATA,OnWinsockEventData)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMiniFTPView construction/destruction
CMiniFTPView::CMiniFTPView()
{
WSAData WsaData;
int ret = WSAStartup(0x0101, &WsaData);
if( ret != 0 )
{
AfxMessageBox("WSAStartup failed");
}
m_sktControl = INVALID_SOCKET;
m_sktListen = INVALID_SOCKET;
m_sktData = INVALID_SOCKET;
//m_pWinsockControl = NULL;
//m_pWinsockListen = NULL;
//m_pWinsockData = NULL;
m_nState = 0;
m_pXferFilePointer = NULL;
m_bTimerOn = FALSE;
m_bWaitingForTimeout = FALSE;
MakeSafeState();
m_nRadioASCII = AfxGetApp()->GetProfileInt("Setting", "ASCII", 0);
m_sExportFileName = AfxGetApp()->GetProfileString("Setting", "Name", "RETRFILE.txt");
}
void CMiniFTPView::MakeSafeState(void)
{
if( m_bWaitingForTimeout )
{
KillTimer( ID_MYTIMEOUT );
}
m_bWaitingForTimeout = FALSE;
if( m_bTimerOn )
{
KillTimer( ID_MYTIMER );
}
m_bTimerOn = FALSE;
m_nState = 0;
if( m_pXferFilePointer != NULL)
{
fclose( m_pXferFilePointer );
m_pXferFilePointer = NULL;
}
//m_bInTransit = FALSE;
//m_bStartLogon = FALSE;
//m_bStartCommand = FALSE;
m_bReplyReceived = FALSE;
//m_bCommandToSend = FALSE;
m_bTimerOn = FALSE;
m_bBusy = FALSE;
m_bWaitingForTimeout = FALSE;
strcpy(m_szCommandToServer, "" );
m_bSavingFile = FALSE;
m_bFileHasBeenSaved = FALSE;
m_bStoringFile = FALSE;
m_bFileHasBeenStored = FALSE;
}
CMiniFTPView::~CMiniFTPView()
{
if( m_sktData != INVALID_SOCKET )
{
closesocket(m_sktData);
}
if( m_sktListen != INVALID_SOCKET )
{
closesocket(m_sktListen);
}
if( m_sktControl != INVALID_SOCKET )
{
closesocket(m_sktControl);
}
WSACleanup();
}
BOOL CMiniFTPView::PreCreateWindow(CREATESTRUCT& cs)
{
BOOL bPreCreated = CEditView::PreCreateWindow(cs);
cs.style &= ~(ES_AUTOHSCROLL|WS_HSCROLL); // Enable word-wrapping
cs.style |= ES_READONLY; // make read only - it is a log window
return bPreCreated;
}
/////////////////////////////////////////////////////////////////////////////
// CMiniFTPView drawing
void CMiniFTPView::OnDraw(CDC* pDC)
{
CMiniFTPDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
}
/////////////////////////////////////////////////////////////////////////////
// CMiniFTPView diagnostics
#ifdef _DEBUG
void CMiniFTPView::AssertValid() const
{
CEditView::AssertValid();
}
void CMiniFTPView::Dump(CDumpContext& dc) const
{
CEditView::Dump(dc);
}
CMiniFTPDoc* CMiniFTPView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMiniFTPDoc)));
return (CMiniFTPDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CMiniFTPView message handlers
/////////////////////////////////////////////////////////////////////////////
void CMiniFTPView::Log(const char * szBuffer)
{
int nChars=GetWindowTextLength(); // get the index of the last line
// point end of document
GetEditCtrl().SetSel( nChars,nChars );
GetEditCtrl().ReplaceSel((LPCSTR)szBuffer); // display text
// defeat the final "save document" dialog on app exit
GetDocument()->SetModifiedFlag(FALSE);
}
/////////////////////////////////////////////////////////////////////////////
void CMiniFTPView::OnTimer(UINT nIDEvent)
{
if( nIDEvent == ID_MYTIMER)
{
StateMachine();
}
else if( nIDEvent == ID_MYTIMEOUT)
{
MakeSafeState();
Log("\r\nMiniFTP Status>Client Timeout\r\n\r\n");
}
}
////////////////////////////////////////////////////////////////////////////
// the major sequencer for client/server stuff
void CMiniFTPView::StateMachine(void)
{
CString sOut;
switch ( m_nState ) // which state are we in now ?
{
case 0:
if( !m_sCommandList.IsEmpty() && !m_bBusy )
{
m_bBusy = TRUE;
SetTimer(ID_MYTIMEOUT, 30000, NULL);
m_bWaitingForTimeout = TRUE;
m_bReplyReceived = FALSE;
sOut = m_sCommandList.GetHead();
m_sCommandList.RemoveHead();
DoCommand( sOut );
m_nState = 1;
}
break;
case 1:
if( m_bReplyReceived )
{
m_bReplyReceived = FALSE;
m_nState = 0;
KillTimer(ID_MYTIMEOUT);
m_bWaitingForTimeout = FALSE;
if( m_sCommandList.IsEmpty() )
{
KillTimer(ID_MYTIMER);
m_bTimerOn =FALSE;
}
m_bBusy = FALSE;
}
break;
}
}
/////////////////////////////////////////////////////////////////////////////
void CMiniFTPView::DisplaySktRead( char * szBuffer )
{
char * str=strtok(szBuffer,"\n");
while( str && *str)
{
Log((const char *)str);
int nLen = strlen(str);
int nCount = (int)(str-szBuffer)+nLen;
if( nCount != NUM1024 )
{
Log("\r\n");
}
else
{
ASSERT( nCount == NUM1024 );
char c = *(szBuffer + NUM1024 -1);
if( c == '\n' )
{
Log("\r\n");
}
}
str=strtok((char *)NULL,"\n");
}
}
/////////////////////////////////////////////////////////////////////////////
LONG CMiniFTPView::OnWinsockEventControl (WPARAM wParam, LPARAM lParam)
{
ASSERT( m_sktControl == wParam );
memset( m_szControlReplyBuffer, 0, NUM1024+2);
// this memset trick avoids having strtok insert a wild \0 somewhere bad
// it is guaranteed to find a \n (the delimiter in this case) before
// running off into other memory
memset( m_szControlReplyBuffer+NUM1024, '\n', 1);
CString sOut;
switch ( WSAGETSELECTEVENT(lParam) ) // which message arrived?
{
case FD_CLOSE:
sOut.Format( "\r\nMiniFTP Status>Control Connection closed by server (socket %d)\r\n\r\n", wParam);
Log(sOut);
m_sktControl = INVALID_SOCKET;
break;
case FD_READ:
recv( m_sktControl, m_szControlReplyBuffer, NUM1024, 0 );
DisplaySktRead( m_szControlReplyBuffer );
m_bReplyReceived = TRUE;
break;
case FD_ACCEPT:
/*ASSERT(m_pWinsockListen != NULL);
sTemp = m_pWinsockListen->Accept(NULL,NULL);*/
//sTemp = m_pWinsockListen->GetWSocket();
/*ASSERT(sTemp != INVALID_SOCKET);
m_pWinsockData->SetSocket(sTemp);
m_pWinsockData->SetSockOpt(SOL_SOCKET,SO_LINGER,0,0);
m_pWinsockData->SetSockOpt(SOL_SOCKET,SO_REUSEADDR,0,0);
m_pWinsockData->SetSockOpt(SOL_SOCKET,SO_KEEPALIVE,0,0);
m_pWinsockData->SetSockOpt(SOL_SOCKET,SO_OOBINLINE,0,0);*/
//m_pWinsockListen->CloseSocket();
// its a window so destroy it first
//m_pWinsockListen->DestroyWindow();
//delete m_pWinsockListen;
//m_pWinsockListen = NULL;
//sOut.Format("\r\nMiniFTP Status>Data Connection made OK (socket %d)\r\n\r\n", sTemp);
sOut.Format("\r\nMiniFTP Status>Data Connection made OK\r\n\r\n");
Log(sOut);
break;
case FD_WRITE:
recv( m_sktControl, m_szControlReplyBuffer, NUM1024, 0 );
DisplaySktRead( m_szControlReplyBuffer );
break;
}
return 0L;
}
/* FOR REFERENCE
#define FD_READ 0x01
#define FD_WRITE 0x02
#define FD_OOB 0x04
#define FD_ACCEPT 0x08
#define FD_CONNECT 0x10
#define FD_CLOSE 0x20 */
/////////////////////////////////////////////////////////////////////////////
LONG CMiniFTPView::OnWinsockEventListen (WPARAM wParam, LPARAM lParam)
{
//ASSERT( m_sktListen == wParam );
if( m_sktListen != wParam )
{
int asdf = 1;
}
memset( m_szControlReplyBuffer, 0, NUM1024+2);
// this memset trick avoids having strtok insert a wild \0 somewhere bad
// it is guaranteed to find a \n (the delimiter in this case) before
// running off into other memory
memset( m_szControlReplyBuffer+NUM1024, '\n', 1);
CString sOut;
switch ( WSAGETSELECTEVENT(lParam) ) // which message arrived?
{
case FD_CLOSE:
sOut.Format( "\r\nMiniFTP Status>Listen Connection closed by server (socket %d)\r\n\r\n", wParam);
Log(sOut);
m_sktListen = INVALID_SOCKET;
break;
case FD_READ:
recv( m_sktListen, m_szControlReplyBuffer, NUM1024, 0 );
DisplaySktRead( m_szControlReplyBuffer );
m_bReplyReceived = TRUE;
break;
case FD_ACCEPT:
//ASSERT(m_pWinsockListen != NULL);
m_sktData = accept( m_sktListen, NULL, NULL);
//sTemp = m_pWinsockListen->GetWSocket();
//ASSERT(sTemp != INVALID_SOCKET);
//m_pWinsockData->SetSocket(sTemp);
setsockopt( m_sktData, SOL_SOCKET, SO_LINGER, 0, 0);
setsockopt( m_sktData, SOL_SOCKET, SO_REUSEADDR, 0, 0);
setsockopt( m_sktData, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
WSAAsyncSelect ( m_sktData, AfxGetMainWnd()->m_hWnd,
WM_WINSOCK_EVENT_FRAME_DATA,
FD_WRITE|FD_READ|FD_CLOSE|FD_ACCEPT);
//m_pWinsockData->SetSockOpt(SOL_SOCKET,SO_OOBINLINE,0,0);*/
//m_pWinsockListen->CloseSocket();
// its a window so destroy it first
//m_pWinsockListen->DestroyWindow();
//delete m_pWinsockListen;
//m_pWinsockListen = NULL;
sOut.Format("\r\nMiniFTP Status>Data Connection made OK (socket %d)\r\n\r\n", m_sktData);
//sOut.Format("\r\nMiniFTP Status>Data Connection made OK\r\n\r\n");
Log(sOut);
break;
case FD_WRITE:
recv( m_sktListen, m_szControlReplyBuffer, NUM1024, 0 );
DisplaySktRead( m_szControlReplyBuffer );
break;
}
return 0L;
}
/////////////////////////////////////////////////////////////////////////////
LONG CMiniFTPView::OnWinsockEventData (WPARAM wParam, LPARAM lParam)
{
ASSERT( m_sktData == wParam );
memset( m_szDataInBuffer, 0, NUM1024+2);
// this memset trick avoids having strtok insert a wild \0 somewhere bad
// it is guaranteed to find a \n (the delimiter in this case) before
// running off into other memory
memset( m_szDataInBuffer+NUM1024, '\n', 1);
CString sOut;
int nLen, nRet;
BOOL bCancel = FALSE;
char *str;
int nClose;
UINT nr;
switch ( WSAGETSELECTEVENT(lParam) ) // which message arrived?
{
case FD_CLOSE:
sOut.Format( "\r\nMiniFTP Status>Data Connection closed by server (socket %d)\r\n\r\n", wParam);
Log(sOut);
nClose = closesocket(m_sktData);
m_sktData = INVALID_SOCKET;
// close the listener too
if( m_sktListen != INVALID_SOCKET )
{
nClose = closesocket(m_sktListen);
}
m_sktListen = INVALID_SOCKET;
break;
case FD_READ: //asdf
// just a plain data socket (no file saving) - get the data to the screen
if( !m_bSavingFile)
{
recv( m_sktData, m_szDataInBuffer, NUM1024, 0 );
DisplaySktRead( m_szDataInBuffer );
}
else // we are saving file
{
if( m_bWaitingForTimeout ) // may be a big file
{
KillTimer(ID_MYTIMEOUT);
m_bWaitingForTimeout = FALSE;
}
ASSERT( m_pXferFilePointer==NULL );
m_pXferFilePointer = fopen( (const char *)m_sExportFileName, "r" );
if( m_pXferFilePointer )
{
fclose( m_pXferFilePointer );
sOut.Format( "File %s\nalready exists.\n\nOverwrite?", m_sExportFileName);
if( AfxMessageBox( sOut, MB_YESNO ) != IDYES )
{
bCancel = TRUE;
}
}
if( bCancel )
{
BeginWaitCursor(); // show hourglass
// just burn it off
do
{
nRet = recv( m_sktData, m_szDataInBuffer, NUM1024, 0 );
} while( nRet != SOCKET_ERROR && nRet > 0 );
m_bFileHasBeenSaved = TRUE; // kinda misnomer - more like "operation complete"
m_bSavingFile = FALSE;
m_pXferFilePointer = NULL;
EndWaitCursor(); // kill hourglass
}
else if( !bCancel && !m_nRadioASCII )
{
// a binary store to disk
BeginWaitCursor(); // show hourglass
m_pXferFilePointer = fopen( (const char *)m_sExportFileName, "wb" );
ASSERT( m_pXferFilePointer );
do
{
nRet = recv( m_sktData, m_szDataInBuffer, NUM1024, 0 );
if( nRet != SOCKET_ERROR && nRet > 0 )
{
fwrite( (char *)m_szDataInBuffer, sizeof( char ), nRet, m_pXferFilePointer );
}
} while( nRet != SOCKET_ERROR && nRet > 0 );
fclose(m_pXferFilePointer);
m_bFileHasBeenSaved = TRUE;
m_bSavingFile = FALSE;
m_pXferFilePointer = NULL;
EndWaitCursor(); // kill hourglass
}
else if( !bCancel && m_nRadioASCII )
{
// an ASCII store to disk
BeginWaitCursor(); // show hourglass
m_pXferFilePointer = fopen( (const char *)m_sExportFileName, "w" );
ASSERT( m_pXferFilePointer );
do
{
memset(m_szDataInBuffer,0,NUM1024+2);
// this memset trick avoids having strtok insert a wild \0 somewhere bad
// it is guaranteed to find a \n (the delimiter in this case) before
// running off into other memory
memset(m_szDataInBuffer+NUM1024, '\n', 1);
nRet = recv( m_sktData, m_szDataInBuffer, NUM1024, 0 );
if( nRet != SOCKET_ERROR && nRet > 0 )
{
str=strtok(m_szDataInBuffer,"\n");
while( str && *str)
{
char temp[NUM1024+1];
strcpy( temp, str);
nLen = strlen(str);
if( nLen > 0 )
{
if( *( str + nLen - 1 ) == 0x0d) // remove the 0x0d aka \r
{
*( str + nLen - 1 ) = 0;
fprintf( m_pXferFilePointer, "%s\n", str );
}
else
{
fprintf( m_pXferFilePointer, "%s", str );
}
}
str=strtok((char *)NULL,"\n");
}
}
} while( nRet != SOCKET_ERROR && nRet > 0 );
fclose(m_pXferFilePointer);
m_pXferFilePointer = NULL;
m_bSavingFile = FALSE;
m_bFileHasBeenSaved = TRUE;
EndWaitCursor(); // kill hourglass
} // end of else if on !bCancel && m_nRadioASCII
}
break;
case FD_ACCEPT:
AfxMessageBox("data accept");
/*ASSERT(m_pWinsockListen != NULL);
sTemp = m_pWinsockListen->Accept(NULL,NULL);*/
//sTemp = m_pWinsockListen->GetWSocket();
/*ASSERT(sTemp != INVALID_SOCKET);
m_pWinsockData->SetSocket(sTemp);
m_pWinsockData->SetSockOpt(SOL_SOCKET,SO_LINGER,0,0);
m_pWinsockData->SetSockOpt(SOL_SOCKET,SO_REUSEADDR,0,0);
m_pWinsockData->SetSockOpt(SOL_SOCKET,SO_KEEPALIVE,0,0);
m_pWinsockData->SetSockOpt(SOL_SOCKET,SO_OOBINLINE,0,0);*/
//m_pWinsockListen->CloseSocket();
// its a window so destroy it first
//m_pWinsockListen->DestroyWindow();
//delete m_pWinsockListen;
//m_pWinsockListen = NULL;
//sOut.Format("\r\nMiniFTP Status>Data Connection made OK (socket %d)\r\n\r\n", sTemp);
//sOut.Format("\r\nMiniFTP Status>Data Connection made OK\r\n\r\n");
//Log(sOut);
break;
case FD_WRITE:
if( m_bStoringFile)
{
if( m_bWaitingForTimeout ) // may be a big file
{
KillTimer(ID_MYTIMEOUT);
m_bWaitingForTimeout = FALSE;
}
ASSERT( m_pXferFilePointer==NULL );
m_pXferFilePointer = fopen( (const char *)m_sStoringFilePath, "rb" );
if( !m_pXferFilePointer )
{
sOut.Format( "Specifed file\n%s\ncannot be found", m_sStoringFilePath );
if( AfxMessageBox( sOut ) == IDOK )
{
m_bStoringFile = FALSE;
return 0L;
}
}
do
{
nr = fread( (char *)m_szDataInBuffer, sizeof( char ), 1024, m_pXferFilePointer );
if( nr > 0 )
{
send( m_sktData, m_szDataInBuffer, nr, 0);
}
} while( nr > 0 );
m_bStoringFile = FALSE;
m_bFileHasBeenStored = TRUE;
fclose( m_pXferFilePointer );
m_pXferFilePointer==NULL;
} // end of if on m_bStoringFile
break;
}
return 0L;
}
/////////////////////////////////////////////////////////////////////////////
void CMiniFTPView::OnConnect()
{
CConnectDlg dlg;
dlg.m_sHost = AfxGetApp()->GetProfileString("Connect", "Host", "");
dlg.m_sName = AfxGetApp()->GetProfileString("Connect", "Name", "");
dlg.m_sPassword = AfxGetApp()->GetProfileString("Connect", "Password", "");
// instantiate the winsock class if not active already.
// we do this here instead of the view's constructor
// because when the view's constructor is called, it's m_hwnd is NULL
// run dialog
if( dlg.DoModal() == IDOK)
{
// housecleaning?
if( dlg.m_bClearWindow )
{
GetEditCtrl().SetWindowText("");
}
// make the winsock object
//MakeSockObj();
//ASSERT( m_pWinsockControl != NULL);
// make the connection
BeginWaitCursor(); // show hourglass
//SOCKET sTemp;
m_sktControl = ConnectToServer(
(const char *)dlg.m_sHost,
"21" );
EndWaitCursor(); // kill hourglass
if( SOCKET_ERROR != m_sktControl && INVALID_SOCKET != m_sktControl )
{
WSAAsyncSelect ( m_sktControl, AfxGetMainWnd()->m_hWnd,
WM_WINSOCK_EVENT_FRAME_CONTROL,
FD_WRITE|FD_READ|FD_CLOSE|FD_ACCEPT);
int nChars=GetWindowTextLength(); // get the index of the last line
if( nChars != 0 )
{
Log("\r\n"); // only do if not the first line in the CEdit
}
CString sOut;
sOut.Format("MiniFTP Status>Control Connection made OK (socket %d)\r\n\r\n",
m_sktControl );
Log(sOut);
// save settings in ini file
AfxGetApp()->WriteProfileString("Connect", "Host", dlg.m_sHost);
AfxGetApp()->WriteProfileString("Connect", "Name", dlg.m_sName);
AfxGetApp()->WriteProfileString("Connect", "Password", dlg.m_sPassword);
// save so state machine can use
m_sName = dlg.m_sName;
m_sPassword = dlg.m_sPassword;
// need to logon
// form command list
// send name
sOut = "USER ";
sOut += m_sName;
m_sCommandList.AddTail(sOut);
// send password
sOut = "PASS ";
sOut += m_sPassword;
m_sCommandList.AddTail(sOut);
// kick off the state machine
// THIS IS WHERE THIS APP REALLY STARTS
ASSERT( !m_bTimerOn );
SetTimer(ID_MYTIMER, REPTIME, NULL);
m_bTimerOn = TRUE;
}
else
{
CString sOut, sMoreout;
sOut.Format("Connection error code %d", m_sktControl);
sMoreout = "";
switch (m_sktControl) // which error?
{
case SOCKET_ERROR:
sMoreout = " (SOCKET_ERROR or INVALID_SOCKET)";
break;
/* case INVALID_SOCKET:
sMoreout = " (INVALID_SOCKET)";
break; */
} // end of switch
sOut += sMoreout;
AfxMessageBox(sOut);
// kill the winsock object
//KillSockObj();
}
} // end of if on domodal
// defeat the final "save document" dialog on app exit
GetDocument()->SetModifiedFlag(FALSE);
}
/////////////////////////////////////////////////////////////////////////////
// use this function to connect to a host on a port
void CMiniFTPView::UserCommand(CString sCommand)
{
if( sCommand.GetLength() == 0 )
{
return;
}
//m_bSavingFile = FALSE; // if it ever was true, is isnt now!
//m_bInTransit = TRUE;
//SOCKET sTemp;
//ASSERT( m_pWinsockListen != NULL);
if( m_sktListen != INVALID_SOCKET )
{
closesocket(m_sktListen);
}
m_sktListen = INVALID_SOCKET;
CString sOut;
m_sktListen = ConnectToListen( "0", "0");
if( m_sktListen == INVALID_SOCKET )
{
Log("\r\nMiniFTP Status>Could not form Listen socket");
::MessageBeep(MB_OK);
return;
}
else
{
WSAAsyncSelect ( m_sktListen, AfxGetMainWnd()->m_hWnd,
WM_WINSOCK_EVENT_FRAME_LISTEN,
FD_WRITE|FD_READ|FD_CLOSE|FD_ACCEPT);
sOut.Format("\r\nMiniFTP Status>Listen Connection made OK (socket %d)\r\n\r\n",
m_sktListen );
Log(sOut);
listen( m_sktListen, 3 );
// inform remote end about our port that we created.
// get the port name that we got for later transmission in PORT cmd
struct sockaddr_in saCtrlAddr;
int iLength=sizeof(saCtrlAddr);
getsockname(m_sktListen,(struct sockaddr *)&saCtrlAddr,&iLength);
struct sockaddr_in saTmpAddr;
iLength = sizeof (saTmpAddr);
if (getsockname(m_sktControl,(LPSOCKADDR)&saTmpAddr, &iLength)
==SOCKET_ERROR)
{
AfxMessageBox("getsockname problem");
}
char *a,*p;
a = (char *)&saTmpAddr.sin_addr;
p = (char *)&saCtrlAddr.sin_port;
#define UC(b) (((int)b)&0xff)
CString sPort= "PORT ";
sPort.Format( "PORT %d,%d,%d,%d,%d,%d",
UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
UC(p[0]), UC(p[1]) );
/*m_pWinsockControl->Send((const char *)sPort, sPort.GetLength(), 0);
Log(sPort);
sPort = "\r\n";
m_pWinsockControl->Send((const char *)sPort, sPort.GetLength(), 0);
Log(sPort); */
m_sCommandList.AddTail(sPort);
// what else to add to list
CString sTemp = sCommand;
sTemp = sTemp.Left(4);
sTemp.MakeUpper();
if( sTemp == "RETR" || sTemp == "STOR" )
{
if(sTemp == "RETR")
{
m_bSavingFile = TRUE;
m_bFileHasBeenSaved = FALSE;
}
if(sTemp == "STOR")
{
m_bStoringFile = TRUE;
m_bFileHasBeenStored = FALSE;
sTemp = sCommand;
sTemp = sTemp.Right( sTemp.GetLength() - 5);
sTemp.TrimRight();
sTemp.TrimLeft();
m_sStoringFilePath = sTemp; // save it so the event handler can reference
}
m_bSavingFile = TRUE;
m_bFileHasBeenSaved = FALSE;
sTemp = "TYPE ";
if( m_nRadioASCII )
{
sTemp += "A";
}
else
{
sTemp += "I";
}
m_sCommandList.AddTail(sTemp);
}
m_sCommandList.AddTail(sCommand);
// kick off the state machine
// THIS IS WHERE THIS APP REALLY STARTS
ASSERT( !m_bTimerOn );
SetTimer(ID_MYTIMER, REPTIME, NULL);
m_bTimerOn = TRUE;
/*m_sktData = accept(m_sktListen, NULL, NULL);
memset(m_szDataInBuffer,0,NUM1024+2);
// this memset trick avoids having strtok insert a wild \0 somewhere bad
// it is guaranteed to find a \n (the delimiter in this case) before
// running off into other memory
memset(m_szDataInBuffer+NUM1024, '\n', 1);
recv( m_sktData, m_szDataInBuffer, NUM1024, 0 );
DisplaySktRead(m_szDataInBuffer);*/
//m_nState = 3;
//m_bInTransit= FALSE;
//m_bReplyReceived = FALSE;
} // end of else on m_sktListen
}
/////////////////////////////////////////////////////////////////////////////
// use this function to connect to a host on a port
int CMiniFTPView::DoCommand(CString s)
{
int nRet;
if( m_sktControl != INVALID_SOCKET )
{
send( m_sktControl, (const char *)s, s.GetLength(), 0);
CString sTemp;
sTemp = s;
sTemp.MakeUpper();
sTemp = sTemp.Left(4);
if( sTemp == "PASS" )
{
Log( "PASS (hidden)");
}
else
{
Log(s);
}
CString sCRLF = "\r\n";
send( m_sktControl, (const char *)sCRLF, sCRLF.GetLength(), 0);
Log(sCRLF);
CString sRet;
nRet = 200;
}
else
{
nRet = 600;
}
return( nRet / 100 );
}
/////////////////////////////////////////////////////////////
// use this function to connect to a host on a port
SOCKET CMiniFTPView::ConnectToListen(const char *name, const char *port)
{
SOCKET s = INVALID_SOCKET;
struct sockaddr_in far server;
struct hostent far *hp;
char msg[100];
int portnum = atoi(port);
while( *name != 0 && *name == ' ' )
{
name++;
}
if( (name[0] >= '0') && (name[0] <= '9') )
{
memset((char *) &server,0,sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(name);
server.sin_port = htons(portnum);
}
else
{
if ( (hp = (hostent far *) gethostbyname(name)) == NULL)
{
sprintf(msg,"Error: Connecting to %s.", name);
if(AfxMessageBox( msg ) == IDOK)
{
return INVALID_SOCKET;
}
}
memset((char *) &server,0,sizeof(server));
memcpy((char *) &server.sin_addr,hp->h_addr,hp->h_length);
server.sin_family = hp->h_addrtype;
server.sin_port = htons(portnum);
}// else
// create socket
if( (s = socket(AF_INET, SOCK_STREAM, 0)) < 1)
{
sprintf(msg,"Error opening stream socket");
if(AfxMessageBox( msg ) == IDOK)
{
return INVALID_SOCKET;
}
}
if (bind(s, (struct sockaddr far *)&server, sizeof(server))< 0)
{
sprintf(msg,"Cannot bind to %s on port %s",name,port);
if(AfxMessageBox( msg ) == IDOK)
{
return INVALID_SOCKET;
}
}
setsockopt( s, SOL_SOCKET,SO_LINGER,0,0);
setsockopt( s, SOL_SOCKET,SO_REUSEADDR,0,0);
setsockopt( s, SOL_SOCKET,SO_KEEPALIVE,0,0);
return s;
}
/////////////////////////////////////////////////////////////////////////////
// use this function to connect to a host on a port
SOCKET CMiniFTPView::ConnectToServer(const char *name, const char *port)
{
SOCKET s = INVALID_SOCKET;
struct sockaddr_in far server;
struct hostent far *hp;
char msg[100];
int portnum = atoi(port);
while( *name != 0 && *name == ' ' )
{
name++;
}
if( *name == 0 || portnum == 0)
{
return INVALID_SOCKET;
}
if( (name[0] >= '0') && (name[0] <= '9') )
{
memset((char *) &server,0,sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(name);
server.sin_port = htons(portnum);
}
else
{
if ( (hp = (hostent far *) gethostbyname(name)) == NULL)
{
sprintf(msg,"Error: Connecting to %s.", name);
if(AfxMessageBox( msg ) == IDOK)
{
return INVALID_SOCKET;
}
}
memset( (char *) &server, 0, sizeof(server));
memcpy( (char *) &server.sin_addr, hp->h_addr, hp->h_length );
server.sin_family = hp->h_addrtype;
server.sin_port = htons( portnum );
}// end of else
// create socket
if( (s = socket(AF_INET, SOCK_STREAM, 0)) < 1)
{
sprintf( msg,"Error opening stream socket" );
if(AfxMessageBox( msg ) == IDOK)
{
return INVALID_SOCKET;
}
}
if (connect( s, (struct sockaddr far *)&server, sizeof(server))< 0 )
{
sprintf( msg,"Cannot connect to %s on port %s",name,port);
if(AfxMessageBox( msg ) == IDOK)
{
return INVALID_SOCKET;
}
}
setsockopt( s, SOL_SOCKET, SO_LINGER, 0, 0 );
setsockopt( s, SOL_SOCKET, SO_REUSEADDR, 0, 0 );
setsockopt( s, SOL_SOCKET, SO_KEEPALIVE, 0, 0 );
return s;
}
/////////////////////////////////////////////////////////////////////////////
void CMiniFTPView::OnFsettings()
{
CXport dlg;
dlg.m_nRadioASCII = AfxGetApp()->GetProfileInt("Setting", "ASCII", 0);
dlg.m_sExportFileName = AfxGetApp()->GetProfileString("Setting", "Name", "");
if( dlg.DoModal() == IDOK)
{
// save settings in ini file
AfxGetApp()->WriteProfileInt("Setting", "ASCII", dlg.m_nRadioASCII );
AfxGetApp()->WriteProfileString("Setting", "Name", dlg.m_sExportFileName);
m_nRadioASCII = dlg.m_nRadioASCII;
m_sExportFileName = dlg.m_sExportFileName;
}
}
/////////////////////////////////////////////////////////////////////////////
void CMiniFTPView::OnCloseconn()
{
if( m_sktControl != INVALID_SOCKET )
{
closesocket(m_sktControl);
m_sktControl = INVALID_SOCKET;
}
if( m_sktListen != INVALID_SOCKET )
{
closesocket(m_sktListen);
m_sktListen = INVALID_SOCKET;
}
if( m_sktData != INVALID_SOCKET )
{
closesocket(m_sktData);
m_sktData = INVALID_SOCKET;
}
//CString sOut.Format( "\r\nMiniFTP Status>Connection closed by client\r\n\r\n");
Log("\r\nMiniFTP Status>Connection closed by client\r\n\r\n");
}
/////////////////////////////////////////////////////////////////////////////
void CMiniFTPView::OnClearview()
{
// clear the user input edit box
GetEditCtrl().SetWindowText("");
}
/////////////////////////////////////////////////////////////////////////////
void CMiniFTPView::OnUpdateCloseconn(CCmdUI* pCmdUI)
{
if( m_sktControl != INVALID_SOCKET )
{
pCmdUI->Enable(1 );
}
else
{
pCmdUI->Enable(0);
}
}
////////////////////////////////////////////////////////////////////////////
void CMiniFTPView::OnUpdateConnect(CCmdUI* pCmdUI)
{
if( m_sktControl == INVALID_SOCKET )
{
pCmdUI->Enable(1 );
}
else
{
pCmdUI->Enable(0);
}
}
/////////////////////////////////////////////////////////////////////////////
/*LONG CMiniFTPView::OnWinsockEvent (WPARAM wParam, LPARAM lParam)
{
ASSERT( m_pWinsockControl != NULL);
char szBuffer[NUM1024+2], *str;
CString sOut;
SOCKET sTemp;
int nLen;
BOOL bCancel = FALSE;
int nRet;
switch ( WSAGETSELECTEVENT(lParam) ) // which message arrived?
{
case FD_CLOSE:
sOut.Format( "\r\nMiniFTP Status>Connection closed by client (socket %d)\r\n\r\n", wParam);
Log(sOut);
// kill the winsock object
if( m_pWinsockControl != NULL &&
m_pWinsockControl->GetSocket() == wParam )
{
// its a window so destroy it first
m_pWinsockControl->DestroyWindow();
delete m_pWinsockControl;
m_pWinsockControl = NULL;
}
else if( m_pWinsockData != NULL &&
m_pWinsockData->GetSocket() == wParam )
{
// its a window so destroy it first
m_pWinsockData->DestroyWindow();
delete m_pWinsockData;
m_pWinsockData = NULL;
// if I am closing the Data socket, do the listner now, too
if( m_pWinsockListen != NULL )
{
// its a window so destroy it first
m_pWinsockListen->DestroyWindow();
delete m_pWinsockListen;
m_pWinsockListen = NULL;
}
}
else if( m_pWinsockListen != NULL &&
m_pWinsockListen->GetSocket() == wParam )
{
// its a window so destroy it first
m_pWinsockListen->DestroyWindow();
delete m_pWinsockListen;
m_pWinsockListen = NULL;
}
break;
case FD_READ:
if( m_bWaitingForTimeout )
{
KillTimer(ID_MYTIMEOUT);
m_bWaitingForTimeout = FALSE;
}
memset(szBuffer,0,NUM1024+2);
// this memset trick avoids having strtok insert a wild \0 somewhere bad
// it is guaranteed to find a \n (the delimiter in this case) before
// running off into other memory
memset(szBuffer+NUM1024, '\n', 1);
// process the control socket
if( m_pWinsockControl->GetSocket() == wParam )
{
m_pWinsockControl->Recv(szBuffer,NUM1024,0);
// make a copy for the state machine
strcpy( m_szReplyBuffer, szBuffer);
// set flag
m_bReplyReceived = TRUE;
// send to screen
DisplaySktRead( szBuffer );
// is it a 5xx reply?
if( *m_szReplyBuffer == '5' )
{
MakeSafeState();
}
}
// process the listen socket
if( m_pWinsockListen != NULL &&
m_pWinsockListen->GetSocket() == wParam )
{
m_pWinsockListen->Recv(szBuffer,NUM1024,0);
DisplaySktRead( szBuffer );
}
// process the data socket
if( m_bSavingFile && m_pWinsockData != NULL &&
m_pWinsockData->GetSocket() == wParam )
{
// deal with the data socket for saving to disk
ASSERT( m_pSaveFilePointer==NULL );
m_pSaveFilePointer = fopen( (const char *)m_sExportFileName, "r" );
if( m_pSaveFilePointer )
{
fclose( m_pSaveFilePointer );
sOut.Format( "File %s\nalready exists.\n\nOverwrite?", m_sExportFileName);
if( AfxMessageBox( sOut, MB_YESNO ) != IDYES )
{
bCancel = TRUE;
}
}
if( bCancel )
{
BeginWaitCursor(); // show hourglass
// just burn it off
do
{
nRet = m_pWinsockData->Recv(szBuffer,NUM1024,0);
} while( nRet != SOCKET_ERROR );
m_bFileHasBeenSaved = TRUE; // kinda misnomer - more like "operation complete"
m_pSaveFilePointer = NULL;
EndWaitCursor(); // kill hourglass
}
else if( !bCancel && !m_nRadioASCII )
{
// a binary store to disk
BeginWaitCursor(); // show hourglass
m_pSaveFilePointer = fopen( (const char *)m_sExportFileName, "wb" );
ASSERT( m_pSaveFilePointer );
do
{
nRet = m_pWinsockData->Recv(szBuffer,NUM1024,0);
if( nRet != SOCKET_ERROR && nRet > 0 )
{
fwrite( (char *)szBuffer, sizeof( char ), nRet, m_pSaveFilePointer );
}
} while( nRet != SOCKET_ERROR && nRet > 0 );
fclose(m_pSaveFilePointer);
m_bFileHasBeenSaved = TRUE;
m_pSaveFilePointer = NULL;
EndWaitCursor(); // kill hourglass
}
else if( !bCancel && m_nRadioASCII )
{
// an ASCII store to disk
BeginWaitCursor(); // show hourglass
m_pSaveFilePointer = fopen( (const char *)m_sExportFileName, "w" );
ASSERT( m_pSaveFilePointer );
do
{
memset(szBuffer,0,NUM1024+2);
// this memset trick avoids having strtok insert a wild \0 somewhere bad
// it is guaranteed to find a \n (the delimiter in this case) before
// running off into other memory
memset(szBuffer+NUM1024, '\n', 1);
nRet = m_pWinsockData->Recv(szBuffer,NUM1024,0);
if( nRet != SOCKET_ERROR && nRet > 0 )
{
str=strtok(szBuffer,"\n");
while( str && *str)
{
char temp[NUM1024+1];
strcpy( temp, str);
nLen = strlen(str);
if( nLen > 0 )
{
if( *( str + nLen - 1 ) == 0x0d) // remove the 0x0d aka \r
{
*( str + nLen - 1 ) = 0;
fprintf( m_pSaveFilePointer, "%s\n", str );
}
else
{
fprintf( m_pSaveFilePointer, "%s", str );
}
}
str=strtok((char *)NULL,"\n");
}
}
} while( nRet != SOCKET_ERROR && nRet > 0 );
fclose(m_pSaveFilePointer);
m_pSaveFilePointer = NULL;
m_bFileHasBeenSaved = TRUE;
EndWaitCursor(); // kill hourglass
} // end of else if on !bCancel && m_nRadioASCII
} // end of if on data socket if saving file
// just a plain data socket (no file saving) - get the data to the screen
if( (!m_bSavingFile) && (m_pWinsockData != NULL) &&
(m_pWinsockData->GetSocket() == wParam) ) //just send to the log window
{
m_pWinsockData->Recv(szBuffer,NUM1024,0);
DisplaySktRead(szBuffer);
}
// all dones saving?
if( m_bSavingFile && m_bFileHasBeenSaved )
{
m_bSavingFile = FALSE;
m_bFileHasBeenSaved = FALSE;
}
break;
case FD_OOB:
AfxMessageBox("OOB");
break;
case FD_ACCEPT:
ASSERT(m_pWinsockListen != NULL);
sTemp = m_pWinsockListen->Accept(NULL,NULL);
//sTemp = m_pWinsockListen->GetWSocket();
ASSERT(sTemp != INVALID_SOCKET);
m_pWinsockData->SetSocket(sTemp);
m_pWinsockData->SetSockOpt(SOL_SOCKET,SO_LINGER,0,0);
m_pWinsockData->SetSockOpt(SOL_SOCKET,SO_REUSEADDR,0,0);
m_pWinsockData->SetSockOpt(SOL_SOCKET,SO_KEEPALIVE,0,0);
m_pWinsockData->SetSockOpt(SOL_SOCKET,SO_OOBINLINE,0,0);
//m_pWinsockListen->CloseSocket();
// its a window so destroy it first
//m_pWinsockListen->DestroyWindow();
//delete m_pWinsockListen;
//m_pWinsockListen = NULL;
sOut.Format("\r\nMiniFTP Status>Data Connection made OK (socket %d)\r\n\r\n", sTemp);
Log(sOut);
break;
case FD_WRITE:
memset(szBuffer,0,NUM1024+2);
m_pWinsockControl->Recv(szBuffer,NUM1024,0);
str=strtok(szBuffer,"\n");
while( str && *str)
{
Log((const char *)str);
Log("\r\n");
str=strtok((char *)NULL,"\n");
}
break;
default:
AfxMessageBox("Default");
break;
} // end of switch
return 0L;
} */
////////////////////////////////////////////////////////////////////////////
// the major sequencer for client/server stuff
/*void CMiniFTPView::StateMachine(void)
{
CString sOut;
switch ( m_nState ) // which state are we in now ?
{
case 0:
// do we need to logon?
if( !m_bInTransit && m_bStartLogon)
{
m_bStartCommand = FALSE;
m_bReplyReceived = FALSE;
m_bStartLogon = FALSE;
m_bCommandToSend = FALSE;
// send name
sOut = "USER ";
sOut += m_sName;
m_pWinsockControl->Send((const char *)sOut, sOut.GetLength(), 0);
Log(sOut);
sOut = "\r\n";
m_pWinsockControl->Send((const char *)sOut, sOut.GetLength(), 0);
Log(sOut);
m_bInTransit = TRUE;
}
else
{
// all done with logon?
if( m_bInTransit && m_bReplyReceived )
{
m_nState = 1;
m_bInTransit = FALSE;
m_bReplyReceived = FALSE;
}
}
break;
case 1:
// do we need to send password?
if( !m_bInTransit )
{
// send password
sOut = "PASS ";
sOut += m_sPassword;
m_pWinsockControl->Send((const char *)sOut, sOut.GetLength(), 0);
sOut = "PASS xxx";
Log(sOut);
sOut = "\r\n";
m_pWinsockControl->Send((const char *)sOut, sOut.GetLength(), 0);
Log(sOut);
m_bInTransit = TRUE;
}
else
{
// all done with password?
if( m_bInTransit && m_bReplyReceived )
{
m_nState = 2;
m_bInTransit = FALSE;
m_bReplyReceived = FALSE;
}
}
break;
case 2:
// do we need to send the PORT coammand and get a listening socket?
if( !m_bInTransit)
{
m_bSavingFile = FALSE; // if it ever was true, is isnt now!
m_bInTransit = TRUE;
SOCKET sTemp;
ASSERT( m_pWinsockListen != NULL);
sTemp = m_pWinsockListen->ConnectToListen( "0", "0");
m_pWinsockListen->AsyncSelect(FD_WRITE|FD_READ|FD_CLOSE|FD_OOB|FD_ACCEPT);
CString sOut;
sOut.Format("\r\nMiniFTP Status>Listen Connection made OK (socket %d)\r\n\r\n",
m_pWinsockListen->GetSocket() );
Log(sOut);
m_pWinsockListen->Listen(3);
// inform remote end about our port that we created.
// get the port name that we got for later transmission in PORT cmd
struct sockaddr_in saCtrlAddr;
int iLength=sizeof(saCtrlAddr);
getsockname(m_pWinsockListen->GetSocket(),(struct sockaddr *)&saCtrlAddr,&iLength);
struct sockaddr_in saTmpAddr;
iLength = sizeof (saTmpAddr);
if (getsockname(m_pWinsockControl->GetSocket(),(LPSOCKADDR)&saTmpAddr, &iLength)
==SOCKET_ERROR)
{
AfxMessageBox("getsockname problem");
}
char *a,*p;
a = (char *)&saTmpAddr.sin_addr;
p = (char *)&saCtrlAddr.sin_port;
#define UC(b) (((int)b)&0xff)
CString sPort= "PORT ";
sPort.Format( "PORT %d,%d,%d,%d,%d,%d",
UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
UC(p[0]), UC(p[1]) );
m_pWinsockControl->Send((const char *)sPort, sPort.GetLength(), 0);
Log(sPort);
sPort = "\r\n";
m_pWinsockControl->Send((const char *)sPort, sPort.GetLength(), 0);
Log(sPort);
//m_pWinsockListen->Accept(NULL,NULL);
m_nState = 3;
m_bInTransit= FALSE;
m_bReplyReceived = FALSE;
}
break;
case 3:
// Do I have a command to send?
if( !m_bInTransit && m_bCommandToSend )
{
ASSERT( !m_bWaitingForTimeout );
SetTimer(ID_MYTIMEOUT, 10000, NULL);
m_bWaitingForTimeout = TRUE;
ASSERT( strlen( m_szCommandToServer ) > 0 );
sOut = m_szCommandToServer;
sOut = sOut.Left(4);
sOut.MakeUpper();
if( sOut == "RETR" )
{
m_bSavingFile = TRUE;
m_bFileHasBeenSaved = FALSE;
}
m_bInTransit = TRUE;
m_pWinsockControl->Send(m_szCommandToServer,
strlen(m_szCommandToServer), 0);
sOut = m_szCommandToServer;
Log(sOut);
m_bCommandToSend = FALSE;
}
else if( m_bInTransit && !m_bCommandToSend )
{
// all done sending the command?
m_bInTransit = FALSE;
//KillTimer(ID_MYTIMER);
}
break;
case 4:
break;
default:
break;
}
}*/
/////////////////////////////////////////////////////////////////////////////
/*void CMiniFTPView::KillSockObj(void)
{
ASSERT(m_pWinsockControl != NULL );
// its a window so destroy it first
m_pWinsockControl->DestroyWindow();
delete m_pWinsockControl;
m_pWinsockControl = NULL;
if(m_pWinsockListen != NULL )
{
// its a window so destroy it first
m_pWinsockListen->DestroyWindow();
delete m_pWinsockListen;
m_pWinsockListen = NULL;
}
if(m_pWinsockData != NULL )
{
// its a window so destroy it first
m_pWinsockData->DestroyWindow();
delete m_pWinsockData;
m_pWinsockData = NULL;
}
m_nState = 0;
MakeSafeState();
}*/
/////////////////////////////////////////////////////////////////////////////
/*void CMiniFTPView::MakeSockObj(void)
{
// make the winsock object
if(m_pWinsockControl == NULL )
{
m_pWinsockControl = new CWinsock(this);
ASSERT( m_pWinsockControl != NULL);
}
// make the winsock object
if(m_pWinsockListen == NULL )
{
m_pWinsockListen = new CWinsock(this);
ASSERT( m_pWinsockListen != NULL);
}
// make the winsock object
if(m_pWinsockData == NULL )
{
m_pWinsockData = new CWinsock(this);
ASSERT( m_pWinsockData != NULL);
}
}*/